1 // Copyright 2014-2017 the openage authors. See copying.md for legal info.
2 
3 #pragma once
4 
5 #include <memory>
6 #include <unordered_map>
7 #include <vector>
8 
9 #include "../coord/tile.h"
10 #include "../handlers.h"
11 #include "../util/timing.h"
12 
13 
14 namespace openage {
15 
16 class Command;
17 class Player;
18 class Terrain;
19 class TerrainObject;
20 class Unit;
21 class UnitContainer;
22 class UnitType;
23 
24 
25 /**
26  * Type used to identify each single unit in the game.
27  */
28 using id_t = unsigned long int;
29 
30 
31 /**
32  * immutable reference data
33  */
34 struct reference_data {
35 	reference_data(const UnitContainer *c, id_t id, Unit *);
36 
37 	const UnitContainer *const container;
38 	const id_t unit_id;
39 	Unit *const unit_ptr;
40 };
41 
42 /**
43  * Reference to a single unit, which may have been removed
44  * from the game, check is_valid() before calling get()
45  */
46 class UnitReference {
47 public:
48 
49 	/**
50 	 * create an invalid reference
51 	 */
52 	UnitReference();
53 
54 	/**
55 	 * create referece by unit id
56 	 */
57 	UnitReference(const UnitContainer *c, id_t id, Unit *);
58 
59 	bool is_valid() const;
60 	Unit *get() const;
61 
62 private:
63 
64 	/**
65 	 * The default copy constructor and assignment
66 	 * will just copy the shared pointer
67 	 */
68 	std::shared_ptr<reference_data> data;
69 };
70 
71 /**
72  * the list of units that are currently in use
73  * will also give a view of the current game state for networking in later milestones
74  */
75 class UnitContainer {
76 public:
77 	UnitContainer();
78 	~UnitContainer();
79 
80 	void reset();
81 
82 	/**
83 	 * sets terrain to initialise units on
84 	 */
85 	void set_terrain(std::shared_ptr<Terrain> &t);
86 
87 	/**
88 	 * returns the terrain which units are placed on
89 	 */
90 	std::shared_ptr<Terrain> get_terrain() const;
91 
92 	/**
93 	 * checks the id is valid
94 	 */
95 	bool valid_id(id_t id) const;
96 
97 	/**
98 	 * returns a reference to a unit
99 	 */
100 	UnitReference get_unit(id_t id);
101 
102 	/**
103 	 * creates a new unit without initialising
104 	 */
105 	UnitReference new_unit();
106 
107 	/**
108 	 * adds a new unit to the container and initialises using a unit type
109 	 */
110 	UnitReference new_unit(UnitType &type, Player &owner, coord::phys3 position);
111 
112 	/**
113 	 * adds a new unit to the container and initialises using a unit type
114 	 * places outside an existing object using the player of that object
115 	 */
116 	UnitReference new_unit(UnitType &type, Player &owner, TerrainObject *other);
117 
118 	/**
119 	 * give a command to a unit -- unit creation and deletion should be done as commands
120 	 */
121 	bool dispatch_command(id_t to_id, const Command &cmd);
122 
123 	/**
124 	 * update dispatched by the game engine on each physics tick.
125 	 * this will update all game objects.
126 	 */
127 	bool update_all(time_nsec_t lastframe_duration);
128 
129 	/**
130 	 * gets a list of all units in the container
131 	 */
132 	std::vector<openage::Unit *> all_units();
133 
134 private:
135 	id_t next_new_id;
136 
137 	/**
138 	 * mapping unit ids to unit objects
139 	 */
140 	std::unordered_map<id_t, std::unique_ptr<Unit>> live_units;
141 
142 	/**
143 	 * Terrain for initialising new units
144 	 */
145 	std::weak_ptr<Terrain> terrain;
146 };
147 
148 } // namespace openage
149