1 #ifndef MULTIPLAYER_H
2 #define MULTIPLAYER_H
3
4 #include <SFML/Network.hpp>
5 #include <SFML/Graphics/Color.hpp>
6 #include <stdint.h>
7 #include "Updatable.h"
8 #include "stringImproved.h"
9
10 class MultiplayerObject;
11
12
13 #define REGISTER_MULTIPLAYER_ENUM(type) \
14 static inline sf::Packet& operator << (sf::Packet& packet, const type& e) { return packet << int8_t(e); } \
15 static inline sf::Packet& operator >> (sf::Packet& packet, type& mw) { int8_t tmp; packet >> tmp; mw = type(tmp); return packet; }
16
17
18 #define REGISTER_MULTIPLAYER_CLASS(className, name) MultiplayerClassListItem MultiplayerClassListItem ## className(name, createMultiplayerObject<className>);
19
20 template<typename T> static inline sf::Packet& operator << (sf::Packet& packet, const sf::Vector2<T>& v)
21 {
22 return packet << v.x << v.y;
23 }
24 template<typename T> static inline sf::Packet& operator >> (sf::Packet& packet, sf::Vector2<T>& v)
25 {
26 return packet >> v.x >> v.y;
27 }
28 template<typename T> static inline sf::Packet& operator << (sf::Packet& packet, const sf::Vector3<T>& v)
29 {
30 return packet << v.x << v.y << v.z;
31 }
32 template<typename T> static inline sf::Packet& operator >> (sf::Packet& packet, sf::Vector3<T>& v)
33 {
34 return packet >> v.x >> v.y >> v.z;
35 }
36 template<typename T1, typename T2> static inline sf::Packet& operator << (sf::Packet& packet, const std::pair<T1, T2>& pair)
37 {
38 return packet << pair.first << pair.second;
39 }
40 template<typename T1, typename T2> static inline sf::Packet& operator >> (sf::Packet& packet, std::pair<T1, T2>& pair)
41 {
42 return packet >> pair.first >> pair.second;
43 }
44
45 static inline sf::Packet& operator << (sf::Packet& packet, const sf::Color& c) { return packet << c.r << c.g << c.b << c.a; } \
46 static inline sf::Packet& operator >> (sf::Packet& packet, sf::Color& c) { packet >> c.r >> c.g >> c.b >> c.a; return packet; }
47
48 template <typename T> struct multiplayerReplicationFunctions
49 {
50 static bool isChanged(void* data, void* prev_data_ptr);
sendDatamultiplayerReplicationFunctions51 static void sendData(void* data, sf::Packet& packet)
52 {
53 T* ptr = (T*)data;
54 packet << *ptr;
55 }
receiveDatamultiplayerReplicationFunctions56 static void receiveData(void* data, sf::Packet& packet)
57 {
58 T* ptr = (T*)data;
59 packet >> *ptr;
60 }
61
isChangedVectormultiplayerReplicationFunctions62 static bool isChangedVector(void* data, void* prev_data_ptr)
63 {
64 std::vector<T>* ptr = (std::vector<T>*)data;
65 std::vector<T>* prev_data = *(std::vector<T>**)prev_data_ptr;
66 bool changed = false;
67 if (prev_data->size() != ptr->size())
68 {
69 changed = true;
70 }else{
71 for(unsigned int n=0; n<ptr->size(); n++)
72 {
73 if ((*prev_data)[n] != (*ptr)[n])
74 {
75 changed = true;
76 break;
77 }
78 }
79 }
80 if (changed)
81 {
82 prev_data->resize(ptr->size());
83 for(unsigned int n=0; n<ptr->size(); n++)
84 (*prev_data)[n] = (*ptr)[n];
85 return true;
86 }
87 return false;
88 }
sendDataVectormultiplayerReplicationFunctions89 static void sendDataVector(void* data, sf::Packet& packet)
90 {
91 std::vector<T>* ptr = (std::vector<T>*)data;
92 uint16_t count = ptr->size();
93 packet << count;
94 for(unsigned int n=0; n<count; n++)
95 packet << (*ptr)[n];
96 }
receiveDataVectormultiplayerReplicationFunctions97 static void receiveDataVector(void* data, sf::Packet& packet)
98 {
99 std::vector<T>* ptr = (std::vector<T>*)data;
100 uint16_t count;
101 packet >> count;
102 ptr->resize(count);
103 for(unsigned int n=0; n<count; n++)
104 packet >> (*ptr)[n];
105 }
cleanupVectormultiplayerReplicationFunctions106 static void cleanupVector(void* prev_data_ptr)
107 {
108 std::vector<T>* prev_data = *(std::vector<T>**)prev_data_ptr;
109 delete prev_data;
110 }
111 };
112
113 template <typename T>
isChanged(void * data,void * prev_data_ptr)114 bool multiplayerReplicationFunctions<T>::isChanged(void* data, void* prev_data_ptr)
115 {
116 T* ptr = (T*)data;
117 T* prev_data = (T*)prev_data_ptr;
118 if (*ptr != *prev_data)
119 {
120 *prev_data = *ptr;
121 return true;
122 }
123 return false;
124 }
125
126 template <> bool multiplayerReplicationFunctions<string>::isChanged(void* data, void* prev_data_ptr);
127
128 //In between class that handles all the nasty synchronization of objects between server and client.
129 //I'm assuming that it should be a pure virtual class though.
130 class MultiplayerObject : public virtual PObject
131 {
132 constexpr static int32_t noId = 0xFFFFFFFF;
133 int32_t multiplayerObjectId;
134 bool replicated;
135 bool on_server;
136 string multiplayerClassIdentifier;
137
138 struct MemberReplicationInfo
139 {
140 #ifdef DEBUG
141 const char* name;
142 #endif
143 void* ptr;
144 uint64_t prev_data;
145 float update_delay;
146 float update_timeout;
147
148 bool(*isChangedFunction)(void* data, void* prev_data_ptr);
149 void(*sendFunction)(void* data, sf::Packet& packet);
150 void(*receiveFunction)(void* data, sf::Packet& packet);
151 void(*cleanupFunction)(void* prev_data_ptr);
152 };
153 std::vector<MemberReplicationInfo> memberReplicationInfo;
154 public:
155 MultiplayerObject(string multiplayerClassIdentifier);
156 virtual ~MultiplayerObject();
157
isServer()158 bool isServer() { return on_server; }
isClient()159 bool isClient() { return !on_server; }
160
161 #ifdef DEBUG
162 #define STRINGIFY(n) #n
163 #define registerMemberReplication(member, ...) registerMemberReplication_(STRINGIFY(member), member , ## __VA_ARGS__ )
164 #define F_PARAM const char* name,
165 #else
166 #define registerMemberReplication(member, ...) registerMemberReplication_(member , ## __VA_ARGS__ )
167 #define F_PARAM
168 #endif
169 template <typename T> void registerMemberReplication_(F_PARAM T* member, float update_delay = 0.0)
170 {
171 assert(!replicated);
172 assert(memberReplicationInfo.size() < 0xFFFF);
173 MemberReplicationInfo info;
174 #ifdef DEBUG
175 info.name = name;
176 #endif
177 info.ptr = member;
178 static_assert(
179 std::is_same<T, string>::value ||
180 (
181 std::is_default_constructible<T>::value &&
182 std::is_trivially_destructible<T>::value &&
183 sizeof(T) <= 8
184 ),
185 "T must be a string or must be a default constructible, trivially destructible and with a size of at most 64bit"
186 );
187 init_prev_data<T>(info);
188 info.update_delay = update_delay;
189 info.update_timeout = 0.0;
190 info.isChangedFunction = &multiplayerReplicationFunctions<T>::isChanged;
191 info.sendFunction = &multiplayerReplicationFunctions<T>::sendData;
192 info.receiveFunction = &multiplayerReplicationFunctions<T>::receiveData;
193 info.cleanupFunction = NULL;
194 memberReplicationInfo.push_back(info);
195 #ifdef DEBUG
196 if (multiplayerReplicationFunctions<T>::isChanged(member, &info.prev_data))
197 {
198 }
199 #endif
200 }
201
202 template <typename T> void registerMemberReplication_(F_PARAM std::vector<T>* member, float update_delay = 0.0)
203 {
204 assert(!replicated);
205 assert(memberReplicationInfo.size() < 0xFFFF);
206 MemberReplicationInfo info;
207 #ifdef DEBUG
208 info.name = name;
209 #endif
210 info.ptr = member;
211 info.prev_data = reinterpret_cast<std::uint64_t>(new std::vector<T>);
212 info.update_delay = update_delay;
213 info.update_timeout = 0.0;
214 info.isChangedFunction = &multiplayerReplicationFunctions<T>::isChangedVector;
215 info.sendFunction = &multiplayerReplicationFunctions<T>::sendDataVector;
216 info.receiveFunction = &multiplayerReplicationFunctions<T>::receiveDataVector;
217 info.cleanupFunction = &multiplayerReplicationFunctions<T>::cleanupVector;
218 memberReplicationInfo.push_back(info);
219 }
220
221 void registerMemberReplication_(F_PARAM sf::Vector3f* member, float update_delay = 0.0)
222 {
223 registerMemberReplication(&member->x, update_delay);
224 registerMemberReplication(&member->y, update_delay);
225 registerMemberReplication(&member->z, update_delay);
226 }
227
updateMemberReplicationUpdateDelay(void * data,float update_delay)228 void updateMemberReplicationUpdateDelay(void* data, float update_delay)
229 {
230 for(unsigned int n=0; n<memberReplicationInfo.size(); n++)
231 if (memberReplicationInfo[n].ptr == data)
232 memberReplicationInfo[n].update_delay = update_delay;
233 }
234
forceMemberReplicationUpdate(void * data)235 void forceMemberReplicationUpdate(void* data)
236 {
237 for(unsigned int n=0; n<memberReplicationInfo.size(); n++)
238 if (memberReplicationInfo[n].ptr == data)
239 memberReplicationInfo[n].update_timeout = 0.0;
240 }
241
242 void registerCollisionableReplication(float object_significant_range = -1);
243
getMultiplayerId()244 int32_t getMultiplayerId() { return multiplayerObjectId; }
getMultiplayerClassIdentifier()245 const string& getMultiplayerClassIdentifier() { return multiplayerClassIdentifier; }
246 void sendClientCommand(sf::Packet& packet);//Send a command from the client to the server.
247 void broadcastServerCommand(sf::Packet& packet);//Send a command from the server to all clients.
248
onReceiveClientCommand(int32_t client_id,sf::Packet & packet)249 virtual void onReceiveClientCommand(int32_t client_id, sf::Packet& packet) {} //Got data from a client, handle it.
onReceiveServerCommand(sf::Packet & packet)250 virtual void onReceiveServerCommand(sf::Packet& packet) {} //Got data from a server, handle it.
251 private:
252 friend class GameServer;
253 friend class GameClient;
254
255 template <typename T>
256 static inline
257 typename std::enable_if<!std::is_same<T, string>::value>::type
init_prev_data(MemberReplicationInfo & info)258 init_prev_data(MemberReplicationInfo& info) {
259 new (&info.prev_data) T{};
260 }
261
262 template <typename T>
263 static inline
264 typename std::enable_if<std::is_same<T, string>::value>::type
init_prev_data(MemberReplicationInfo & info)265 init_prev_data(MemberReplicationInfo& info) {
266 info.prev_data = 0;
267 }
268 };
269
270 typedef MultiplayerObject* (*CreateMultiplayerObjectFunction)();
271
272 class MultiplayerClassListItem;
273 extern MultiplayerClassListItem* multiplayerClassListStart;
274
275 class MultiplayerClassListItem
276 {
277 public:
278 string name;
279 CreateMultiplayerObjectFunction func;
280 MultiplayerClassListItem* next;
281
MultiplayerClassListItem(string name,CreateMultiplayerObjectFunction func)282 MultiplayerClassListItem(string name, CreateMultiplayerObjectFunction func)
283 {
284 this->name = name;
285 this->func = func;
286 this->next = multiplayerClassListStart;
287 multiplayerClassListStart = this;
288 }
289 };
290
createMultiplayerObject()291 template<class T> MultiplayerObject* createMultiplayerObject()
292 {
293 return new T();
294 }
295
296 #endif//MULTIPLAYER_H
297