| [1505] | 1 | /* | 
|---|
|  | 2 | *   ORXONOX - the hottest 3D action shooter ever to exist | 
|---|
|  | 3 | *                    > www.orxonox.net < | 
|---|
|  | 4 | * | 
|---|
|  | 5 | * | 
|---|
|  | 6 | *   License notice: | 
|---|
|  | 7 | * | 
|---|
|  | 8 | *   This program is free software; you can redistribute it and/or | 
|---|
|  | 9 | *   modify it under the terms of the GNU General Public License | 
|---|
|  | 10 | *   as published by the Free Software Foundation; either version 2 | 
|---|
|  | 11 | *   of the License, or (at your option) any later version. | 
|---|
|  | 12 | * | 
|---|
|  | 13 | *   This program is distributed in the hope that it will be useful, | 
|---|
|  | 14 | *   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 15 | *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 16 | *   GNU General Public License for more details. | 
|---|
|  | 17 | * | 
|---|
|  | 18 | *   You should have received a copy of the GNU General Public License | 
|---|
|  | 19 | *   along with this program; if not, write to the Free Software | 
|---|
|  | 20 | *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
|---|
|  | 21 | * | 
|---|
|  | 22 | *   Author: | 
|---|
|  | 23 | *      Oliver Scheuss, (C) 2007 | 
|---|
|  | 24 | *   Co-authors: | 
|---|
|  | 25 | *      ... | 
|---|
|  | 26 | * | 
|---|
|  | 27 | */ | 
|---|
|  | 28 |  | 
|---|
|  | 29 | #ifndef _Synchronisable_H__ | 
|---|
|  | 30 | #define _Synchronisable_H__ | 
|---|
|  | 31 |  | 
|---|
| [2211] | 32 | #include "network/NetworkPrereqs.h" | 
|---|
| [1505] | 33 |  | 
|---|
|  | 34 | #include <list> | 
|---|
| [3084] | 35 | #include <vector> | 
|---|
| [1907] | 36 | #include <map> | 
|---|
|  | 37 | #include <queue> | 
|---|
| [2245] | 38 | #include <cassert> | 
|---|
| [3084] | 39 | #include <string> | 
|---|
| [2245] | 40 | #include "util/Math.h" | 
|---|
|  | 41 | #include "util/mbool.h" | 
|---|
| [1505] | 42 | #include "core/OrxonoxClass.h" | 
|---|
| [1534] | 43 | #include "NetworkCallback.h" | 
|---|
| [2245] | 44 | #include "SynchronisableVariable.h" | 
|---|
| [1505] | 45 |  | 
|---|
| [2245] | 46 | /*#define REGISTERDATA(varname, ...) \ | 
|---|
| [2171] | 47 | registerVariable((void*)&varname, sizeof(varname), DATA, __VA_ARGS__) | 
|---|
| [2087] | 48 | #define REGISTERSTRING(stringname, ...) \ | 
|---|
| [2245] | 49 | registerVariable(&stringname, stringname.length()+1, STRING, __VA_ARGS__)*/ | 
|---|
| [1907] | 50 |  | 
|---|
| [2171] | 51 | namespace orxonox | 
|---|
| [1505] | 52 | { | 
|---|
| [2087] | 53 |  | 
|---|
| [2245] | 54 | namespace objectDirection{ | 
|---|
|  | 55 | enum objectdirection{ | 
|---|
| [1907] | 56 | toclient=0x1, | 
|---|
|  | 57 | toserver=0x2, | 
|---|
| [2245] | 58 | bidirectional=0x3 | 
|---|
| [1907] | 59 | }; | 
|---|
|  | 60 | } | 
|---|
| [2485] | 61 |  | 
|---|
| [2415] | 62 | namespace priority{ | 
|---|
|  | 63 | enum prio{ | 
|---|
| [2419] | 64 | very_high   = -100, | 
|---|
| [2415] | 65 | high        = -15, | 
|---|
|  | 66 | normal      = 0, | 
|---|
|  | 67 | low         = 15, | 
|---|
| [2419] | 68 | very_low    = 100 | 
|---|
| [2415] | 69 | }; | 
|---|
|  | 70 | } | 
|---|
| [2087] | 71 |  | 
|---|
| [2662] | 72 | /** | 
|---|
|  | 73 | * @brief: stores information about a Synchronisable | 
|---|
|  | 74 | * | 
|---|
|  | 75 | * This class stores the information about a Synchronisable (objectID, classID, creatorID, dataSize) | 
|---|
|  | 76 | * in an emulated bitset. | 
|---|
|  | 77 | * Bit 1 to 31 store the size of the Data the synchronisable consumes in the stream | 
|---|
|  | 78 | * Bit 32 is a bool and defines whether the data is actually stored or is just filled up with 0 | 
|---|
|  | 79 | * Byte 5 to 8: objectID | 
|---|
|  | 80 | * Byte 9 to 12: classID | 
|---|
|  | 81 | * Byte 13 to 16: creatorID | 
|---|
|  | 82 | */ | 
|---|
|  | 83 | class _NetworkExport SynchronisableHeader{ | 
|---|
|  | 84 | private: | 
|---|
|  | 85 | uint8_t *data_; | 
|---|
|  | 86 | public: | 
|---|
|  | 87 | SynchronisableHeader(uint8_t* data) | 
|---|
|  | 88 | { data_ = data; } | 
|---|
|  | 89 | inline static uint32_t getSize() | 
|---|
|  | 90 | { return 16; } | 
|---|
|  | 91 | inline uint32_t getDataSize() const | 
|---|
|  | 92 | { return (*(uint32_t*)data_) & 0x7FFFFFFF; } //only use the first 31 bits | 
|---|
|  | 93 | inline void setDataSize(uint32_t size) | 
|---|
|  | 94 | { *(uint32_t*)(data_) = (size & 0x7FFFFFFF) | (*(uint32_t*)(data_) & 0x80000000 ); } | 
|---|
|  | 95 | inline bool isDataAvailable() const | 
|---|
|  | 96 | { return ( (*(uint32_t*)data_) & 0x80000000 ) == 0x80000000; } | 
|---|
|  | 97 | inline void setDataAvailable( bool b) | 
|---|
|  | 98 | { *(uint32_t*)(data_) = (b << 31) | (*(uint32_t*)(data_) & 0x7FFFFFFF ); } | 
|---|
|  | 99 | inline uint32_t getObjectID() const | 
|---|
|  | 100 | { return *(uint32_t*)(data_+4); } | 
|---|
|  | 101 | inline void setObjectID(uint32_t objectID) | 
|---|
|  | 102 | { *(uint32_t*)(data_+4) = objectID; } | 
|---|
|  | 103 | inline uint32_t getClassID() const | 
|---|
|  | 104 | { return *(uint32_t*)(data_+8); } | 
|---|
|  | 105 | inline void setClassID(uint32_t classID) | 
|---|
|  | 106 | { *(uint32_t*)(data_+8) = classID; } | 
|---|
|  | 107 | inline uint32_t getCreatorID() const | 
|---|
|  | 108 | { return *(uint32_t*)(data_+12); } | 
|---|
|  | 109 | inline void setCreatorID(uint32_t creatorID) | 
|---|
|  | 110 | { *(uint32_t*)(data_+12) = creatorID; } | 
|---|
|  | 111 | inline void operator=(SynchronisableHeader& h) | 
|---|
|  | 112 | { memcpy(data_, h.data_, getSize()); } | 
|---|
| [1505] | 113 | }; | 
|---|
|  | 114 |  | 
|---|
|  | 115 |  | 
|---|
|  | 116 | /** | 
|---|
|  | 117 | * This class is the base class of all the Objects in the universe that need to be synchronised over the network | 
|---|
| [2662] | 118 | * Every class, that inherits from this class has to link the DATA THAT NEEDS TO BE SYNCHRONISED into the linked list. | 
|---|
| [1505] | 119 | * @author Oliver Scheuss | 
|---|
|  | 120 | */ | 
|---|
| [2171] | 121 | class _NetworkExport Synchronisable : virtual public OrxonoxClass{ | 
|---|
| [1505] | 122 | public: | 
|---|
| [1907] | 123 | friend class packet::Gamestate; | 
|---|
| [1505] | 124 | virtual ~Synchronisable(); | 
|---|
|  | 125 |  | 
|---|
|  | 126 | static void setClient(bool b); | 
|---|
| [2087] | 127 |  | 
|---|
| [2171] | 128 | static Synchronisable *fabricate(uint8_t*& mem, uint8_t mode=0x0); | 
|---|
| [2309] | 129 | static bool deleteObject(uint32_t objectID); | 
|---|
|  | 130 | static Synchronisable *getSynchronisable(uint32_t objectID); | 
|---|
| [1907] | 131 | static unsigned int getNumberOfDeletedObject(){ return deletedObjects_.size(); } | 
|---|
| [2309] | 132 | static uint32_t popDeletedObject(){ uint32_t i = deletedObjects_.front(); deletedObjects_.pop(); return i; } | 
|---|
| [2087] | 133 |  | 
|---|
| [2485] | 134 | inline uint32_t getObjectID() const {return objectID;} | 
|---|
|  | 135 | inline unsigned int getCreatorID() const {return creatorID;} | 
|---|
|  | 136 | inline uint32_t getClassID() const {return classID;} | 
|---|
|  | 137 | inline unsigned int getPriority() const { return objectFrequency_;} | 
|---|
| [2355] | 138 |  | 
|---|
| [1505] | 139 | protected: | 
|---|
| [2171] | 140 | Synchronisable(BaseObject* creator); | 
|---|
| [2245] | 141 | template <class T> void registerVariable(T& variable, uint8_t mode=0x1, NetworkCallbackBase *cb=0, bool bidirectional=false); | 
|---|
| [3084] | 142 | //template <class T> void unregisterVariable(T& var); | 
|---|
| [2171] | 143 | void setObjectMode(uint8_t mode); | 
|---|
| [2415] | 144 | void setPriority(unsigned int freq){ objectFrequency_ = freq; } | 
|---|
| [2087] | 145 |  | 
|---|
|  | 146 |  | 
|---|
| [1505] | 147 | private: | 
|---|
| [3084] | 148 | uint32_t getData(uint8_t*& men, int32_t id, uint8_t mode=0x0); | 
|---|
| [2309] | 149 | uint32_t getSize(int32_t id, uint8_t mode=0x0); | 
|---|
| [2171] | 150 | bool updateData(uint8_t*& mem, uint8_t mode=0x0, bool forceCallback=false); | 
|---|
| [2710] | 151 | bool isMyData(uint8_t* mem); | 
|---|
|  | 152 | bool doSync(int32_t id, uint8_t mode=0x0); | 
|---|
| [2087] | 153 |  | 
|---|
| [2309] | 154 | uint32_t objectID; | 
|---|
|  | 155 | uint32_t creatorID; | 
|---|
|  | 156 | uint32_t classID; | 
|---|
| [2087] | 157 |  | 
|---|
| [3084] | 158 | std::vector<SynchronisableVariableBase*> syncList; | 
|---|
|  | 159 | std::vector<SynchronisableVariableBase*> stringList; | 
|---|
|  | 160 | uint32_t dataSize_; //size of all variables except strings | 
|---|
| [2171] | 161 | static uint8_t state_; // detemines wheter we are server (default) or client | 
|---|
| [1505] | 162 | bool backsync_; // if true the variables with mode > 1 will be synchronised to server (client -> server) | 
|---|
| [1751] | 163 | unsigned int objectFrequency_; | 
|---|
|  | 164 | int objectMode_; | 
|---|
| [2309] | 165 | static std::map<uint32_t, Synchronisable *> objectMap_; | 
|---|
|  | 166 | static std::queue<uint32_t> deletedObjects_; | 
|---|
| [1505] | 167 | }; | 
|---|
| [2485] | 168 |  | 
|---|
| [2245] | 169 | // ================= Specialisation declarations | 
|---|
| [3084] | 170 |  | 
|---|
|  | 171 | //   template <> _NetworkExport void Synchronisable::registerVariable( const std::string& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional); | 
|---|
|  | 172 | template <> _NetworkExport void Synchronisable::registerVariable( std::string& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional); | 
|---|
| [2307] | 173 | template <> _NetworkExport void Synchronisable::registerVariable( const ColourValue& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 174 | template <> _NetworkExport void Synchronisable::registerVariable( ColourValue& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 175 | template <> _NetworkExport void Synchronisable::registerVariable( const Vector2& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 176 | template <> _NetworkExport void Synchronisable::registerVariable( Vector2& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 177 | template <> _NetworkExport void Synchronisable::registerVariable( const Vector3& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 178 | template <> _NetworkExport void Synchronisable::registerVariable( Vector3& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 179 | template <> _NetworkExport void Synchronisable::registerVariable( const Vector4& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 180 | template <> _NetworkExport void Synchronisable::registerVariable( Vector4& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 181 | template <> _NetworkExport void Synchronisable::registerVariable( mbool& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 182 | template <> _NetworkExport void Synchronisable::registerVariable( const Quaternion& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
|  | 183 | template <> _NetworkExport void Synchronisable::registerVariable( Quaternion& variable, uint8_t mode, NetworkCallbackBase* cb, bool bidirectional); | 
|---|
| [3084] | 184 |  | 
|---|
|  | 185 | template <class T> void Synchronisable::registerVariable(T& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional) | 
|---|
|  | 186 | { | 
|---|
|  | 187 | if (bidirectional) | 
|---|
|  | 188 | { | 
|---|
|  | 189 | syncList.push_back(new SynchronisableVariableBidirectional<const T>(variable, mode, cb)); | 
|---|
|  | 190 | this->dataSize_ += syncList.back()->getSize(state_); | 
|---|
|  | 191 | } | 
|---|
|  | 192 | else | 
|---|
|  | 193 | { | 
|---|
|  | 194 | syncList.push_back(new SynchronisableVariable<const T>(variable, mode, cb)); | 
|---|
|  | 195 | if ( this->state_ == mode ) | 
|---|
|  | 196 | this->dataSize_ += syncList.back()->getSize(state_); | 
|---|
|  | 197 | } | 
|---|
|  | 198 | } | 
|---|
|  | 199 |  | 
|---|
|  | 200 |  | 
|---|
|  | 201 |  | 
|---|
|  | 202 | //   template <class T> void Synchronisable::unregisterVariable(T& var){ | 
|---|
|  | 203 | //     std::vector<SynchronisableVariableBase*>::iterator it = syncList.begin(); | 
|---|
|  | 204 | //     while(it!=syncList.end()){ | 
|---|
|  | 205 | //       if( ((*it)->getReference()) == &var ){ | 
|---|
|  | 206 | //         delete (*it); | 
|---|
|  | 207 | //         syncList.erase(it); | 
|---|
|  | 208 | //         return; | 
|---|
|  | 209 | //       } | 
|---|
|  | 210 | //       else | 
|---|
|  | 211 | //         it++; | 
|---|
|  | 212 | //     } | 
|---|
|  | 213 | //     bool unregistered_nonexistent_variable = false; | 
|---|
|  | 214 | //     assert(unregistered_nonexistent_variable); //if we reach this point something went wrong: | 
|---|
|  | 215 | //     // the variable has not been registered before | 
|---|
|  | 216 | //   } | 
|---|
|  | 217 |  | 
|---|
|  | 218 |  | 
|---|
| [1505] | 219 | } | 
|---|
|  | 220 |  | 
|---|
|  | 221 | #endif /* _Synchronisable_H__ */ | 
|---|