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