/
BirdLeon
/
ROBLOX2016
Обзор
Документация
Войти
/
BirdLeon
/
ROBLOX2016
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
Network/Streaming.h
523 строки
19 KB
PatoFlamejanteTV
full source code
19 дек 2024, 19:11
19 дек 2024, 19:11
05db15d
Код
Авторство
О чём код?
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */ #pragma once #include <string> #include "V8Tree/Instance.h" #include "Util/Velocity.h" #include "bitstream.h" #include <boost/any.hpp> #include "StreamingUtil.h" #include "Dictionary.h" #include "Util.h" #include "Network/RakNetFast.h" DYNAMIC_FASTINT(PhysicsCompressionSizeFilter) namespace RBX { namespace Network { void serializeStringCompressed(const std::string& value, RakNet::BitStream &bitStream); void deserializeStringCompressed(std::string& value, RakNet::BitStream &bitStream); template<class T> class DescriptorSender { public: struct IdContainer { uint32_t id; bool outdated; }; protected: std::map<const T*, IdContainer> descToId; int idBits; void visit(const T* desc); std::string teachName(const T* t) const; void send(RakNet::BitStream& stream, const T* value) const { unsigned int id = getId(value).id; send(stream, id); } public: DescriptorSender(); std::map<const T*, IdContainer> DescToId() const { return descToId; } IdContainer getId(const T* value) const { typename std::map<const T*, IdContainer>::const_iterator iter = descToId.find(value); if (iter != descToId.end()) { // found the desc in dictionary return iter->second; } else { IdContainer result; //Failure to send is all 1s, which will be guaranteed to be too big result.id = 0xFFFFFFFF >> (32-idBits); result.outdated = true; return result; } } void teach(RakNet::BitStream& stream, bool exchangeChecksum, bool useRakString) const { unsigned int count = descToId.size(); stream << count; for (typename std::map<const T*, IdContainer>::const_iterator iter = descToId.begin(); iter != descToId.end(); ++iter) { int i = iter->second.id; stream << i; std::string s = teachName(iter->first); if (useRakString) { RakNet::RakString rakStr = s.c_str(); stream.Write(rakStr); } else { serializeStringCompressed(s, stream); } if (exchangeChecksum) { // checksum for this item boost::crc_32_type result; uint32_t checksum = Reflection::ClassDescriptor::checksum(iter->first, result); #ifdef NETWORK_DEBUG //StandardOut::singleton()->printf(MESSAGE_INFO, "Checksum of %s: %d", s.c_str(), checksum); #endif stream << checksum; } } } void send(RakNet::BitStream& stream, uint32_t id) { stream.WriteBits((unsigned char*) &id, idBits); } }; template<class T> class DescriptorReceiver { struct DescContainer { const T* desc; bool outdated; }; std::vector<DescContainer> idToDesc; int idBits; void learnName(std::string s, int i, uint32_t checksum); public: void getValue(unsigned int id, const T*& value) const { value = idToDesc.at(id).desc; } void learn(RakNet::BitStream& stream, bool exchangeChecksum, bool useRakString) { uint32_t count; stream >> count; idToDesc.resize(count); for (size_t n=0; n<count; ++n) { int i; stream >> i; std::string s; if (useRakString) { RakNet::RakString rakStr; stream.Read(rakStr); s = rakStr.C_String(); } else { deserializeStringCompressed(s, stream); } uint32_t checksum = 0; if (exchangeChecksum) { stream >> checksum; } learnName(s, i, checksum); } idBits = Math::computeMSB(idToDesc.size())+1; } unsigned int receive(RakNet::BitStream& stream, const T*& value, bool versionCheck) const { unsigned int id = 0; readFastN( stream, id, idBits ); value = idToDesc.at(id).desc; if (value && versionCheck) { if (idToDesc.at(id).outdated) { // outdated API value = NULL; } } return id; } bool verifyChecksum(const T* value, uint32_t remoteChecksum) { if (remoteChecksum == 0) { // server will not verify the checksum because client does not send checksum to server return true; } else { // only client because only server sends client the checksum boost::crc_32_type result; uint32_t localChecksum = Reflection::ClassDescriptor::checksum(value, result); return (localChecksum == remoteChecksum); } } }; template<class T> class DescriptorDictionary : public DescriptorSender<T> , public DescriptorReceiver<T> , boost::noncopyable { }; class IdSerializer : public Instance { private: typedef Instance Super; void serializeEnumIndex(const Reflection::EnumDescriptor* desc, const size_t& index, RakNet::BitStream &bitStream, size_t enumSizeMSB = 0); void deserializeEnumIndex(const Reflection::EnumDescriptor* desc, size_t& index, RakNet::BitStream &bitStream, size_t enumSizeMSB = 0); protected: typedef SharedDictionary<RBX::Guid::Scope> SharedGuidDictionary; SharedGuidDictionary scopeNames; // Used for RBX::Guid RBX::Guid::Scope serverScope; boost::intrusive_ptr<GuidItem<Instance>::Registry> guidRegistry; // A RefProperty that is waiting for an object to be streamed in struct WaitItem { const Reflection::RefPropertyDescriptor* desc; boost::shared_ptr<Instance> instance; }; // Map of unknown ID to WaitItem typedef std::map<RBX::Guid::Data, std::vector<WaitItem> > WaitItemMap; WaitItemMap waitItems; boost::mutex waitItemsMutex; virtual void setRefValue(WaitItem& wi, Instance* instance); public: struct Id { bool valid; RBX::Guid::Data id; }; IdSerializer(); Id extractId(const Instance* instance); void sendId(RakNet::BitStream& stream, const Id& id); void serializeId(RakNet::BitStream& stream, const Instance* instance); void serializeId(RakNet::BitStream& stream, const RBX::Guid::Data& id); void serializeIdWithoutDictionary(RakNet::BitStream& stream, const Instance* instance); void serializeIdWithoutDictionary(RakNet::BitStream& stream, const RBX::Guid::Data& id); bool trySerializeId(RakNet::BitStream& stream, const Instance* instance); bool canSerializeId(const Instance* instance); void deserializeId(RakNet::BitStream& stream, RBX::Guid::Data& id); void deserializeIdWithoutDictionary(RakNet::BitStream& stream, RBX::Guid::Data& id); void resolvePendingReferences(Instance* instance, RBX::Guid::Data id); void serializeInstanceRef(const Instance* instance, RakNet::BitStream& bitStream); bool deserializeInstanceRef(RakNet::BitStream& stream, shared_ptr<Instance>& instance, RBX::Guid::Data& id); // returns false if it couldn't find the Instance bool deserializeInstanceRef(RakNet::BitStream& stream, shared_ptr<Instance>& instance) { RBX::Guid::Data dummy; return deserializeInstanceRef(stream, instance, dummy); } size_t numWaitingRefs() const { return waitItems.size(); } void addPendingRef(const Reflection::RefPropertyDescriptor* desc, boost::shared_ptr<Instance> instance, RBX::Guid::Data id); protected: void onServiceProvider(ServiceProvider* oldProvider, ServiceProvider* newProvider); }; void writeBrickVector(RakNet::BitStream& stream, const G3D::Vector3& value); void readBrickVector(RakNet::BitStream& stream, G3D::Vector3& value); template<class T> void serializeGeneric(const Reflection::Variant& value, RakNet::BitStream &bitStream) { bitStream << value.cast<T>(); } template<class T> void deserializeGeneric(Reflection::Variant& value, RakNet::BitStream &bitStream) { T inputValue; bitStream >> inputValue; value = inputValue; } template<class T> void serialize(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream) { bitStream << property.getValue<T>(); } template<class T> void deserialize(Reflection::Property& property, RakNet::BitStream &bitStream) { T value; bitStream >> value; if (property.getInstance()) property.setValue(value); } template<> void serialize<ContentId>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<ContentId>(Reflection::Property& property, RakNet::BitStream &bitStream); template<> void serialize<BrickColor>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<BrickColor>(Reflection::Property& property, RakNet::BitStream &bitStream); template<> void serialize<UDim>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<UDim>(Reflection::Property& property, RakNet::BitStream &bitStream); template<> void serialize<UDim2>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<UDim2>(Reflection::Property& property, RakNet::BitStream &bitStream); template<> void serialize<RBX::RbxRay>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<RBX::RbxRay>(Reflection::Property& property, RakNet::BitStream &bitStream); template<> void serialize<Faces>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<Faces>(Reflection::Property& property, RakNet::BitStream &bitStream); template<> void serialize<Axes>(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); template<> void deserialize<Axes>(Reflection::Property& property, RakNet::BitStream &bitStream); void serializeEnum(const Reflection::EnumDescriptor* desc, const Reflection::Variant& value, RakNet::BitStream &bitStream, size_t enumSizeMSB = 0); void deserializeEnum(const Reflection::EnumDescriptor* desc, Reflection::Variant& result, RakNet::BitStream &bitStream, size_t enumSizeMSB = 0); void serializeStringProperty(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream); void deserializeStringProperty(Reflection::Property& property, RakNet::BitStream &bitStream); void serializeGuidScope(RakNet::BitStream& stream, const RBX::Guid::Scope& value, bool canDisableCompression); void deserializeGuidScope(RakNet::BitStream& stream, RBX::Guid::Scope& value, bool canDisableCompression); void serializeEnumProperty(const Reflection::ConstProperty& property, RakNet::BitStream &bitStream, size_t enumSizeMSB = 0); void deserializeEnumProperty(Reflection::Property& property, RakNet::BitStream &bitStream, size_t enumSizeMSB = 0); namespace CustomSerializer { static const float kMinDeltaShort = 1.f/(65535.f*2); static const float kMinDeltaByte = 1.f/(255.f*2); inline void writeCompressedFloat(bool heavyCompression, const float &inVar, RakNet::BitStream &bitStream) { //| -1| 0 |+1 | // after compression //|---|---|---| //--|---|---|-- // | 0.f | // before compression (minDelta for each segment) float minDelta; if (heavyCompression) { // to byte minDelta = kMinDeltaByte; } else { // to short minDelta = kMinDeltaShort; } RakAssert(inVar > -1.f-minDelta/2 && inVar < 1.f+minDelta/2); bool isNegative = inVar < 0; bitStream.Write(isNegative); float absValue = fabs(inVar); if (absValue > 1.0f) absValue=1.0f; if (heavyCompression) { unsigned char compressedValue = (unsigned char)((absValue+minDelta)*255.f); bitStream.Write(compressedValue); } else { unsigned short compressedValue = (unsigned short)((absValue+minDelta)*32767.f); bitStream.Write(compressedValue); } } inline bool readCompressedFloat(bool heavyCompression, float &outVar, RakNet::BitStream &bitStream) { bool isNegative; bitStream.Read(isNegative); float absValue; if (heavyCompression) { unsigned char compressedFloat; if (bitStream.Read(compressedFloat)) { absValue = ((float)compressedFloat / 255.f - kMinDeltaByte); } else { return false; } } else { unsigned short compressedFloat; if (bitStream.Read(compressedFloat)) { absValue = ((float)compressedFloat / 32767.f - kMinDeltaShort); } else { return false; } } if (isNegative) { outVar = -absValue; } else { outVar = absValue; } return true; } inline void writeVector(bool heavilyCompressed, const float &x, const float &y, const float &z, RakNet::BitStream &bitStream) { float magnitude = sqrt(x * x + y * y + z * z); // Let's check if we really want to compress the vector heavily if (heavilyCompressed && magnitude > (float)(DFInt::PhysicsCompressionSizeFilter)) { // when magnitude is too large, heavy lossy compression could cause noticeable desyncs heavilyCompressed = false; } bitStream.Write(heavilyCompressed); bitStream.Write(magnitude); float minDelta; if (heavilyCompressed) { minDelta = kMinDeltaByte; } else { minDelta = kMinDeltaShort; } if (magnitude > minDelta) { writeCompressedFloat(heavilyCompressed, x/magnitude, bitStream); writeCompressedFloat(heavilyCompressed, y/magnitude, bitStream); // we will re-construct z from x and y bitStream.Write((bool)(z>0.f)); // remember the sign of z } } inline bool readVector( float &x, float &y, float &z, RakNet::BitStream &bitStream ) { bool heavilyCompressed; bitStream.Read(heavilyCompressed); float magnitude; if (!bitStream.Read(magnitude)) return false; bool hasValues; if (heavilyCompressed) { hasValues = magnitude>kMinDeltaByte; } else { hasValues = magnitude>kMinDeltaShort; } if (hasValues) { readCompressedFloat(heavilyCompressed, x, bitStream); readCompressedFloat(heavilyCompressed, y, bitStream); // calculate z bool zSign; bitStream.Read(zSign); float difference = 1.0f - x*x - y*y; if (difference < 0.0f) difference=0.0f; z = sqrt(difference); if (zSign == false) { z=-z; } x*=magnitude; y*=magnitude; z*=magnitude; } else { x=0.0; y=0.0; z=0.0; } return true; } inline void writeNormQuat(bool heavilyCompressed, const float &w, const float &x, const float &y, const float &z, RakNet::BitStream &bitStream) { bitStream.Write(heavilyCompressed); bitStream.Write((bool)(w<0.0)); writeCompressedFloat(heavilyCompressed, x, bitStream); writeCompressedFloat(heavilyCompressed, y, bitStream); writeCompressedFloat(heavilyCompressed, z, bitStream); // we will re-construct w from x,y,z } inline bool readNormQuat(float &w, float &x, float &y, float &z, RakNet::BitStream &bitStream) { bool heavilyCompressed; bool cwNeg=false; bitStream.Read(heavilyCompressed); bitStream.Read(cwNeg); readCompressedFloat(heavilyCompressed, x, bitStream); readCompressedFloat(heavilyCompressed, y, bitStream); readCompressedFloat(heavilyCompressed, z, bitStream); // Calculate w from x,y,z float difference = 1.0f - x*x - y*y - z*z; if (difference < 0.0f) difference=0.0f; w = sqrt(difference); if (cwNeg) w=-w; return true; } } } }