CORGI
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
entity_factory.h
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef CORGI_COMPONENT_LIBRARY_ENTITY_FACTORY_H_
16 #define CORGI_COMPONENT_LIBRARY_ENTITY_FACTORY_H_
17 
18 #include <memory>
19 #include <string>
20 #include <unordered_map>
21 #include <vector>
22 #include "corgi/entity_manager.h"
23 #include "flatbuffers/flatbuffers.h"
24 #include "library_components_generated.h"
25 
26 namespace corgi {
27 namespace component_library {
28 
29 /// @file
30 /// @addtogroup corgi_component_library
31 /// @{
32 ///
33 /// @class EntityFactory
34 ///
35 /// @brief An EntityFactory builds Entities based on prototypes, using
36 /// FlatBuffers to specify the raw data for Entities.
38  public:
39  /// @var kDataTypeNone
40  ///
41  /// @brief This is equivalent to the `*_NONE` value of the FlatBuffer union
42  /// enum.
43  static const unsigned int kDataTypeNone = 0;
44 
45  /// @var kErrorLoadingEntities
46  ///
47  /// @brief The return value for `LoadEntitiesFromFile` and
48  /// `LoadEntityListFromMemory` if the methods are unable to read the
49  /// Entity list.
50  static const int kErrorLoadingEntities = -1;
51 
52  /// @brief The default constructor for an empty EntityFactory.
54  : max_component_id_(0),
55  debug_entity_creation_(false) {}
56  virtual ~EntityFactory() {}
57 
58  /// @brief Add a file from which you can load Entity prototype definitions.
59  ///
60  /// @param[in] entity_library_file A UTF-8 C-string representing the
61  /// filename of the Entity library file that contains the prototype
62  /// definitions.
63  ///
64  /// @return Returns `true` if the file was added successfully. Otherwise it
65  /// returns `false`.
66  bool AddEntityLibrary(const char* entity_library_file);
67 
68  /// @brief Check if the given pointer points to something that will be kept
69  /// in memory for the lifetime of the EntityFactory.
70  ///
71  /// @param[in] pointer A void pointer that should be checked if its data
72  /// will be kept in memory.
73  ///
74  /// @return Returns `true` if the given pointer points to something that will
75  /// be kept in memory for the of the EntityFactory. Otherwise it returns
76  /// `false`.
77  bool WillBeKeptInMemory(const void* pointer);
78 
79  /// @brief Load Entities from a given Entity list file.
80  ///
81  /// @param[in] filename A UTF-8 C-string representing the filename of the
82  /// Entity list file to load the Entities from.
83  /// @param[in, out] entity_manager An EntityManager pointer to the
84  /// EntityManager that should load all the Entities from `filename`.
85  ///
86  /// @return Returns the number of Entities that were loaded, or returns
87  /// `kErrorLoadingEntities` if there was en error.
88  virtual int LoadEntitiesFromFile(const char* filename,
89  corgi::EntityManager* entity_manager);
90 
91  /// @brief Loads a list of Entities from an in-memory buffer.
92  ///
93  /// @note This is a helper method used by `LoadEntitiesFromFile` to do a lot
94  /// of the work actually loading the Entities.
95  ///
96  /// @param[in] raw_entity_list A void pointer to the Entity list.
97  /// @param[in, out] entity_manager An EntityManager pointer to the
98  /// EntityManager that should load all the Entities from memory.
99  /// @param[out] entities_loaded An optional parameter to obtain the list of
100  /// the loaded Entities. Pass in a pointer to a std::vector of EntityRefs to
101  /// capture this output. Otherwise, pass in `NULL` to ignore this parameter.
102  ///
103  /// @return Returns the number of Entities that were loaded, or returns
104  /// `kErrorLoadingEntities` if there was an error.
105  int LoadEntityListFromMemory(const void* raw_entity_list,
106  corgi::EntityManager* entity_manager,
107  std::vector<corgi::EntityRef>* entities_loaded);
108 
109  /// @brief Override a cached file with data from memory that will persist
110  /// until exit.
111  ///
112  /// @param[in] filename A UTF-8 C-string representing the filename of the
113  /// cached file whose data should be overridden.
114  /// @param[in] new_data A std::unique_ptr that points to a std::string of
115  /// data to override the cached file with.
116  void OverrideCachedFile(const char* filename,
117  std::unique_ptr<std::string> new_data);
118 
119  /// @brief Initialize an Entity from an Entity definition.
120  ///
121  /// @note This helper method is called by `LoadRawEntityList` for each Entity
122  /// definition.
123  ///
124  /// @param[in] data A void pointer to the data to create an Entity from.
125  /// @param[in,out] entity_manager An EntityManager pointer to the
126  /// EntityManager that should load the Entity from the `data`.
127  ///
128  /// @return Returns an EntityRef to the new Entity that was created.
129  corgi::EntityRef CreateEntityFromData(const void* data,
130  corgi::EntityManager* entity_manager);
131 
132  /// @brief Initialize an entity from a given prototype.
133  ///
134  /// @param[in] prototype_name A C-string containing the name of the prototype
135  /// to initialize the Entity with.
136  /// @param[in,out] entity_manager An EntityManager pointer to the
137  /// EntityManager that should create the initialized Entity.
138  ///
139  /// @return Returns an EntityRef to the new Entity that was initialized
140  /// from the prototype.
142  const char* prototype_name, corgi::EntityManager* entity_manager);
143 
144  /// @brief When you register each Component with the Entity system, it will
145  /// get a component ID. This factory needs to know the Component ID assigned
146  /// for each Component data type (the data_type() in the flatbuffer union).
147  ///
148  /// @param[in] component_id The ComponentId of the Component in the Entity
149  /// system.
150  /// @param[in] data_type An enum for the data type of the Component definition
151  /// within the FlatBuffer union.
152  /// @param[in] table_name A C-string of the table name of the FlatBuffer
153  /// schema table for the Component definition.
154  void SetComponentType(corgi::ComponentId component_id, unsigned int data_type,
155  const char* table_name);
156 
157  /// @brief Get the Component Id for a given data type specifier.
158  ///
159  /// @param[in] data_type An int corresponding to the data type specifier.
160  ///
161  /// @return Returns a ComponentId for the Component with a data type
162  /// of `data_type`.
163  corgi::ComponentId DataTypeToComponentId(unsigned int data_type) {
164  if (data_type >= data_type_to_component_id_.size())
166  return data_type_to_component_id_[data_type];
167  }
168 
169  /// @brief Get the data type specifier for a Component, given a Component ID.
170  ///
171  /// @param[in] component_id The ComponentId of the Component whose data type
172  /// specifier should be returned.
173  ///
174  /// @return Returns an int corresponding to the data type specifier.
175  unsigned int ComponentIdToDataType(corgi::ComponentId component_id) {
176  if (component_id >= component_id_to_data_type_.size()) return kDataTypeNone;
177  return component_id_to_data_type_[component_id];
178  }
179 
180  /// @brief Get the table name for a Component, given a Component ID.
181  ///
182  /// @param[in] component_id The ComponentId of the Component whose table name
183  /// should be returned.
184  ///
185  /// @return Returns a C-string of the FlatBuffer schema table name for the
186  /// Component.
187  const char* ComponentIdToTableName(corgi::ComponentId component_id) {
188  if (component_id >= component_id_to_table_name_.size()) return "";
189  return component_id_to_table_name_[component_id].c_str();
190  }
191 
192  /// @brief Serialize an Entity into whatever binary type you are using
193  /// for them.
194  ///
195  /// @note Calls `CreateEntityDefinition()`, which you implement, to do the
196  /// work.
197  ///
198  /// @param[in] entity The Entity that should be serialized.
199  /// @param[in] entity_manager The EntityManager responsible for the Entity
200  /// that should be serialized.
201  /// @param[out] entity_serialized_output A vector to capture the output of the
202  /// Entity definition.
203  ///
204  /// @return Returns `true` if the Entity definition was successfully created.
205  /// Otherwise, it returns `false`.
206  virtual bool SerializeEntity(corgi::EntityRef& entity,
207  corgi::EntityManager* entity_manager,
208  std::vector<uint8_t>* entity_serialized_output);
209 
210  /// @brief After you call `SerializeEntity` on a few Entities, you may call
211  /// this method to put them into a proper list.
212  ///
213  /// @note: Calls `CreateEntityList()`, which you implement.
214  ///
215  /// @param[in] entity_definitions A reference to a vector list of Entity
216  /// definitions (vector<uint8_t>) that should be put into a proper Entity
217  /// list.
218  /// @param[out] entity_list_serialized A vector to capture the output of the
219  /// Entity list.
220  ///
221  /// @return Returns `true` if the Entity list was successfully created.
222  /// Otherwise, it returns `false`.
223  virtual bool SerializeEntityList(
224  const std::vector<std::vector<uint8_t>>& entity_definitions,
225  std::vector<uint8_t>* entity_list_serialized);
226 
227  /// @brief Get the maximum component ID.
228  ///
229  /// @return Returns the highest component ID.
230  corgi::ComponentId max_component_id() { return max_component_id_; }
231 
232  /// @brief Check if debug logging is enabled.
233  ///
234  /// @return Returns `true` if debug logging is enabled. Otherwise, it
235  /// returns `false`.
236  bool debug_entity_creation() const { return debug_entity_creation_; }
237 
238  /// @brief Enable debug logging during Entity creation.
239  ///
240  /// @param[in] b A bool determining if logging should be enabled.
241  void set_debug_entity_creation(bool b) { debug_entity_creation_ = b; }
242 
243  // Here are the virtual methods you must override to create your own entity
244  // factory. They are mainly the ones concerned with reading and writing your
245  // application's specific Flatbuffer format.
246 
247  /// @brief Handles reading an Entity list and extracting the individual
248  /// Entity data definitions.
249  ///
250  /// @note You MUST override this function to create your own EntityFactory.
251  ///
252  /// @param[in] entity_list A const void pointer to the start of the list
253  /// of Entities.
254  /// @param[out] entity_defs A vector that captures the output of the
255  /// extracted entity data definitions.
256  ///
257  /// @return returns `true` if the list was parsed successfully. Otherwise it
258  /// returns `false`.
259  virtual bool ReadEntityList(const void* entity_list,
260  std::vector<const void*>* entity_defs) = 0;
261 
262  /// @brief Handles reading an Entity definition and extracting the individual
263  /// Component data definitions.
264  ///
265  /// In your output, you should index `component_defs` by component ID, and
266  /// any Components not specified by this Entity's definition should be set to
267  /// `nullptr`.
268  ///
269  /// @note You MUST override this function to create your own EntityFactory.
270  ///
271  /// @param[in] entity_definition A const void pointer to the Entity definition
272  /// whose Component data definitions should be extracted.
273  /// @param[out] component_defs A vector that captures the output of
274  /// the extracted Component data definitions.
275  ///
276  /// @return Returns `true` if the `entity_definition` was parsed successfully.
277  /// Otherwise it returns `false`.
278  virtual bool ReadEntityDefinition(
279  const void* entity_definition,
280  std::vector<const void*>* component_defs) = 0;
281 
282  /// @brief Creates an Entity list that contains a single Entity definition,
283  /// which contains a single Component definition (a `MetaDef` with `prototype`
284  /// set to the requested prototype name).
285  ///
286  /// @note You MUST override this function to create your own EntityFactory.
287  ///
288  /// @param[in] prototype_name A C-string name of the prototype, which is used
289  /// to set the `prototype` field in the MetaComponent.
290  /// @param[out] request A vector to capture the output of the prototype
291  /// request.
292  ///
293  /// @return Returns `true` if the request was created successfully. Otherwise
294  /// it returns `false`.
295  virtual bool CreatePrototypeRequest(const char* prototype_name,
296  std::vector<uint8_t>* request) = 0;
297 
298  /// @brief Handles building a single Entity definition flatbuffer from a list
299  /// of an Entity's Component definitions.
300  ///
301  /// @note You MUST override this function to create your own EntityFactory.
302  ///
303  /// @param[in] component_data A const reference to a std::vector that contains
304  /// the list of the Entity's Component definitions, which can be indexed by
305  /// Component ID.
306  /// @param[out] entity_definition A vector to capture the output of the Entity
307  /// definition.
308  ///
309  /// @return Returns `true` if the Entity definition was successfully created.
310  /// Otherwise, it returns `false`.
311  virtual bool CreateEntityDefinition(
312  const std::vector<const void*>& component_data,
313  std::vector<uint8_t>* entity_definition) = 0;
314 
315  /// @brief Handles building an Entity list flatbuffer from a collection of
316  /// individual Entity flatbuffers.
317  ///
318  /// @note You MUST override this function to create your own EntityFactory.
319  ///
320  /// @param[in] entity_defs A const reference to a std::vector that contains
321  /// all the Entity flatbuffers.
322  /// @param[out] entity_list A vector to capture the output of the Entity
323  /// list.
324  ///
325  /// @return Returns `true` if the Entity list was successfully created.
326  /// Otherwise, it returns `false`.
327  virtual bool CreateEntityList(const std::vector<const void*>& entity_defs,
328  std::vector<uint8_t>* entity_list) = 0;
329 
330  // You MAY override this function, which takes a binary list of entities and
331  // outputs a human-readable text version (aka JSON) of the entity list.
332  //
333  // Takes a void* and outputs a std::string containing the human readable
334  // entity file.
335  //
336  // TODO: Implement this function using reflection.
337 
338  /// @brief Creates an Entity from the Entity definition, recursively building
339  /// up from the prototypes.
340  ///
341  /// @note: You MAY override this function if you wish to change the way that
342  /// prototyping works.
343  ///
344  /// @param[in] def A const void pointer to the Entity definition that will
345  /// be used to build the prototypes.
346  /// @param[in,out] entity_manager A pointer to the EntityManager that the
347  /// Entity will be created with.
348  /// @param[out] entity A reference to the Entity that is being created.
349  /// @param[in] is_prototype A bool determining if this is a prototype.
350  virtual void LoadEntityData(const void* def,
351  corgi::EntityManager* entity_manager,
352  corgi::EntityRef& entity, bool is_prototype);
353 
354  /// @brief This factory and its subclasses need to know how to parse the
355  /// Entity FlatBuffers using reflection.
356  ///
357  /// You will need to specify the .bfbs file for your Component data type.
358  ///
359  /// @param[in] binary_schema_filename A C-string of the filename for the
360  /// FlatBuffer schema file.
361  void SetFlatbufferSchema(const char* binary_schema_filename);
362 
363  /// @brief Get the FlatBuffer binary schema that you loaded
364  /// with `SetFlatbufferSchema()`.
365  ///
366  /// @return Returns a const reference to the std::string name
367  /// of the FlatBuffer schema.
368  const std::string& flatbuffer_binary_schema_data() const {
369  return flatbuffer_binary_schema_data_;
370  }
371 
372  /// @brief Get the map with all the current prototypes.
373  ///
374  /// @return Returns a const reference to the std::unordered_map with the
375  /// prototype data
376  const std::unordered_map<std::string, const void*>& prototype_data() const {
377  return prototype_data_;
378  }
379 
380  private:
381  // Storage for the Flatbuffer binary schema.
382  std::string flatbuffer_binary_schema_data_;
383 
384  // Storage for entity files.
385  std::unordered_map<std::string, std::unique_ptr<std::string>> loaded_files_;
386 
387  // Storage for old entity files we don't need any more; these will be cleared
388  // out once there are no entities referencing them.
389  std::vector<std::unique_ptr<std::string>> stale_files_;
390 
391  // Index the prototype library's entity definitions by prototype name.
392  std::unordered_map<std::string, const void*> prototype_data_;
393 
394  // Keep a list of previously-built entity definitions that we use to
395  // create an entity by prototype name.
396  std::unordered_map<std::string, std::vector<uint8_t>> prototype_requests_;
397 
398  // Look up ComponentId from data type, and vice versa.
399  std::vector<corgi::ComponentId> data_type_to_component_id_;
400  std::vector<unsigned int> component_id_to_data_type_;
401 
402  // Look up the table name from the data type.
403  std::vector<std::string> component_id_to_table_name_;
404 
405  // The highest component ID we've seen registered.
406  corgi::ComponentId max_component_id_;
407 
408  // Enable debug output for initializing entities.
409  bool debug_entity_creation_;
410 };
411 /// @}
412 
413 } // namespace component_library
414 } // namespace corgi
415 
416 #endif // CORGI_COMPONENT_LIBRARY_ENTITY_FACTORY_H_
bool WillBeKeptInMemory(const void *pointer)
Check if the given pointer points to something that will be kept in memory for the lifetime of the En...
virtual bool CreateEntityList(const std::vector< const void * > &entity_defs, std::vector< uint8_t > *entity_list)=0
Handles building an Entity list flatbuffer from a collection of individual Entity flatbuffers...
static const int kErrorLoadingEntities
The return value for LoadEntitiesFromFile and LoadEntityListFromMemory if the methods are unable to r...
Definition: entity_factory.h:50
void SetComponentType(corgi::ComponentId component_id, unsigned int data_type, const char *table_name)
When you register each Component with the Entity system, it will get a component ID. This factory needs to know the Component ID assigned for each Component data type (the data_type() in the flatbuffer union).
bool debug_entity_creation() const
Check if debug logging is enabled.
Definition: entity_factory.h:236
const char * ComponentIdToTableName(corgi::ComponentId component_id)
Get the table name for a Component, given a Component ID.
Definition: entity_factory.h:187
The EntityManager is the code that manages all Entities and Components in the game. Normally the game will instantiate EntityManager, and then use it to create and control all of its Entities.
Definition: entity_manager.h:61
corgi::ComponentId DataTypeToComponentId(unsigned int data_type)
Get the Component Id for a given data type specifier.
Definition: entity_factory.h:163
void set_debug_entity_creation(bool b)
Enable debug logging during Entity creation.
Definition: entity_factory.h:241
corgi::EntityRef CreateEntityFromData(const void *data, corgi::EntityManager *entity_manager)
Initialize an Entity from an Entity definition.
bool AddEntityLibrary(const char *entity_library_file)
Add a file from which you can load Entity prototype definitions.
virtual bool CreateEntityDefinition(const std::vector< const void * > &component_data, std::vector< uint8_t > *entity_definition)=0
Handles building a single Entity definition flatbuffer from a list of an Entity's Component definitio...
virtual void LoadEntityData(const void *def, corgi::EntityManager *entity_manager, corgi::EntityRef &entity, bool is_prototype)
Creates an Entity from the Entity definition, recursively building up from the prototypes.
virtual bool SerializeEntityList(const std::vector< std::vector< uint8_t >> &entity_definitions, std::vector< uint8_t > *entity_list_serialized)
After you call SerializeEntity on a few Entities, you may call this method to put them into a proper ...
EntityFactory()
The default constructor for an empty EntityFactory.
Definition: entity_factory.h:53
const ComponentId kInvalidComponent
A sentinel value to represent an invalid Component.
Definition: entity_common.h:44
unsigned int ComponentIdToDataType(corgi::ComponentId component_id)
Get the data type specifier for a Component, given a Component ID.
Definition: entity_factory.h:175
void SetFlatbufferSchema(const char *binary_schema_filename)
This factory and its subclasses need to know how to parse the Entity FlatBuffers using reflection...
virtual bool ReadEntityList(const void *entity_list, std::vector< const void * > *entity_defs)=0
Handles reading an Entity list and extracting the individual Entity data definitions.
virtual corgi::EntityRef CreateEntityFromPrototype(const char *prototype_name, corgi::EntityManager *entity_manager)
Initialize an entity from a given prototype.
virtual bool SerializeEntity(corgi::EntityRef &entity, corgi::EntityManager *entity_manager, std::vector< uint8_t > *entity_serialized_output)
Serialize an Entity into whatever binary type you are using for them.
void OverrideCachedFile(const char *filename, std::unique_ptr< std::string > new_data)
Override a cached file with data from memory that will persist until exit.
virtual bool CreatePrototypeRequest(const char *prototype_name, std::vector< uint8_t > *request)=0
Creates an Entity list that contains a single Entity definition, which contains a single Component de...
virtual int LoadEntitiesFromFile(const char *filename, corgi::EntityManager *entity_manager)
Load Entities from a given Entity list file.
A reference object for pointing into the vector pool. It acts as a pointer for vector pool elements a...
Definition: vector_pool.h:72
An interface for an Entity factory, which creates Entities for a given EntityManager.
Definition: entity_manager.h:408
An EntityFactory builds Entities based on prototypes, using FlatBuffers to specify the raw data for E...
Definition: entity_factory.h:37
static const unsigned int kDataTypeNone
This is equivalent to the *_NONE value of the FlatBuffer union enum.
Definition: entity_factory.h:43
int LoadEntityListFromMemory(const void *raw_entity_list, corgi::EntityManager *entity_manager, std::vector< corgi::EntityRef > *entities_loaded)
Loads a list of Entities from an in-memory buffer.
const std::string & flatbuffer_binary_schema_data() const
Get the FlatBuffer binary schema that you loaded with SetFlatbufferSchema().
Definition: entity_factory.h:368
virtual bool ReadEntityDefinition(const void *entity_definition, std::vector< const void * > *component_defs)=0
Handles reading an Entity definition and extracting the individual Component data definitions...
const std::unordered_map< std::string, const void * > & prototype_data() const
Get the map with all the current prototypes.
Definition: entity_factory.h:376
corgi::ComponentId max_component_id()
Get the maximum component ID.
Definition: entity_factory.h:230
uint16_t ComponentId
This represents the ID of a Component.
Definition: entity_common.h:36