1 /* 2 * Copyright (C) 2011-2016 OpenDungeons Team 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef ODPACKET_H 19 #define ODPACKET_H 20 21 #include <OgreVector3.h> 22 #include <SFML/Network.hpp> 23 24 #include <string> 25 #include <cstdint> 26 27 /*! \brief This class is an utility class to transfer data through ODSocketClient. 28 * It should also override operators << and >> for each standard types. 29 * ODPacket should preserve integrity. That means that if an ODSocketClient 30 * sends an ODPacket, the server should receive exactly 1 similar ODPacket (same data, 31 * nothing less, nothing more) 32 * IMPORTANT : ODPacket can handle different types of data the same way. For that, when we receive 33 * data, we have to know its type (when an int is sent, we know an int will be received). The typical 34 * use of ODPacket is : 35 * Emission : int myInt; 36 * ODPacket packet; 37 * packet << myInt; 38 * send(packet); 39 * Reception : ODPacket packet; 40 * receive(packet); 41 * int myInt; 42 * packet >> myInt; 43 * As we can see in this example, we have to know the data type within the packet before reading it. 44 * But depending on architecture, default datatype can be different between the server and the client. 45 * For this reason, the data returned by a function should never be used directly as ODPacket data. Instead, 46 * a temporary variable should be used and sent to ODPacket (sized variables such as int32_t, int8_t, ... 47 * should be as used as possible for the same reason). 48 * For example : You should NOT do : 49 * packet << getName(); 50 * You should do : 51 * std::string name = getName(); 52 * packet << name; 53 * This way, if the function signature changes or if the data type is different (int vs long for example) on 54 * different platforms, there will be an error when compiling instead of a probable buggy behaviour at runtime. 55 * When dealing with class/structure, the best is to use directly the variables themselves, no getter/setter. 56 * For example, You should NOT do : 57 * Emission : packet << creature->getHp(); 58 * Reception : double hp; 59 * packet >> hp; 60 * creature->setHp(hp); 61 * You should do : 62 * Emission : packet << creature->mHp; 63 * Reception : packet >> creature->mHp; 64 * This way, if mHp changes (from float to double for example), it will still work. 65 */ 66 class ODPacket 67 { 68 friend class ODSocketClient; 69 70 public: ODPacket()71 ODPacket() 72 {} ~ODPacket()73 ~ODPacket() 74 {} 75 76 /*! \brief Export data operators. 77 * The behaviour is the same as standard C++ streams 78 */ 79 ODPacket& operator >>(bool& data); 80 ODPacket& operator >>(int8_t& data); 81 ODPacket& operator >>(uint8_t& data); 82 ODPacket& operator >>(int16_t& data); 83 ODPacket& operator >>(uint16_t& data); 84 ODPacket& operator >>(int32_t& data); 85 ODPacket& operator >>(uint32_t& data); 86 ODPacket& operator >>(int64_t& data); 87 ODPacket& operator >>(uint64_t& data); 88 ODPacket& operator >>(float& data); 89 ODPacket& operator >>(double& data); 90 ODPacket& operator >>(char* data); 91 ODPacket& operator >>(std::string& data); 92 ODPacket& operator >>(wchar_t* data); 93 ODPacket& operator >>(std::wstring& data); 94 ODPacket& operator >>(Ogre::Vector3& data); 95 96 /*! \brief Import data operators 97 * The behaviour is the same as standard C++ streams 98 */ 99 ODPacket& operator <<(bool data); 100 ODPacket& operator <<(int8_t data); 101 ODPacket& operator <<(uint8_t data); 102 ODPacket& operator <<(int16_t data); 103 ODPacket& operator <<(uint16_t data); 104 ODPacket& operator <<(int32_t data); 105 ODPacket& operator <<(uint32_t data); 106 ODPacket& operator <<(int64_t data); 107 ODPacket& operator <<(uint64_t data); 108 ODPacket& operator <<(float data); 109 ODPacket& operator <<(double data); 110 ODPacket& operator <<(const char* data); 111 ODPacket& operator <<(const std::string& data); 112 ODPacket& operator <<(const wchar_t* data); 113 ODPacket& operator <<(const std::wstring& data); 114 ODPacket& operator <<(const Ogre::Vector3& data); 115 116 /*! \brief Return true if there were no error exporting data (operator >>). 117 * This behaviour is the same as standard C++ streams : 118 * If we try to export data while the packet is empty or from incompatible types, 119 * the data will be invalid and the function will return false 120 */ 121 operator bool() const; 122 123 /*! \brief Clears the packet. After calling Clear, the packet should 124 * be empty. 125 */ 126 void clear(); 127 128 /*! \brief Writes the packet content to the given ofstream. 129 */ 130 void writePacket(int32_t timestamp, std::ofstream& os); 131 132 /*! \brief Reads the packet content from the given ifstream. 133 * Returns the timestamp at which the packet has been sent. 134 * If EOF has been reached, returns -1 135 */ 136 int32_t readPacket(std::ifstream& is); 137 138 /*! \brief Template function to put arguments in a packet, used for in-place construction. 139 */ 140 template<typename FirstArg, typename ...Args> putInPacket(ODPacket & packet,const FirstArg & arg,const Args &...args)141 static void putInPacket(ODPacket& packet, const FirstArg& arg, const Args&... args) 142 { 143 packet << arg; 144 putInPacket(packet, args...); 145 } 146 147 template<typename Arg> putInPacket(ODPacket & packet,const Arg & arg)148 static void putInPacket(ODPacket& packet, const Arg& arg) 149 { 150 packet << arg; 151 } 152 153 private: 154 sf::Packet mPacket; 155 156 }; 157 158 #endif // ODPACKET_H 159 160