diff --git a/src/AIModel/AIMultiplayer.cxx b/src/AIModel/AIMultiplayer.cxx index e7a3abd47..dc9d7e923 100755 --- a/src/AIModel/AIMultiplayer.cxx +++ b/src/AIModel/AIMultiplayer.cxx @@ -187,15 +187,44 @@ void FGAIMultiplayer::update(double dt) ecOrient = firstIt->second.orientation; speed = norm(firstIt->second.linearVel) * SG_METER_TO_NM * 3600.0; - std::vector<FGFloatPropertyData>::const_iterator firstPropIt; - std::vector<FGFloatPropertyData>::const_iterator firstPropItEnd; + std::vector<FGPropertyData*>::const_iterator firstPropIt; + std::vector<FGPropertyData*>::const_iterator firstPropItEnd; firstPropIt = firstIt->second.properties.begin(); firstPropItEnd = firstIt->second.properties.end(); while (firstPropIt != firstPropItEnd) { - float val = firstPropIt->value; - PropertyMap::iterator pIt = mPropertyMap.find(firstPropIt->id); + //cout << " Setting property..." << (*firstPropIt)->id; + PropertyMap::iterator pIt = mPropertyMap.find((*firstPropIt)->id); if (pIt != mPropertyMap.end()) - pIt->second->setFloatValue(val); + { + //cout << "Found " << pIt->second->getPath() << ":"; + switch ((*firstPropIt)->type) { + case SGPropertyNode::INT: + case SGPropertyNode::BOOL: + case SGPropertyNode::LONG: + pIt->second->setIntValue((*firstPropIt)->int_value); + //cout << "Int: " << (*firstPropIt)->int_value << "\n"; + break; + case SGPropertyNode::FLOAT: + case SGPropertyNode::DOUBLE: + pIt->second->setFloatValue((*firstPropIt)->float_value); + //cout << "Flo: " << (*firstPropIt)->float_value << "\n"; + break; + case SGPropertyNode::STRING: + case SGPropertyNode::UNSPECIFIED: + pIt->second->setStringValue((*firstPropIt)->string_value); + //cout << "Str: " << (*firstPropIt)->string_value << "\n"; + break; + default: + // FIXME - currently defaults to float values + pIt->second->setFloatValue((*firstPropIt)->float_value); + //cout << "Unknown: " << (*firstPropIt)->float_value << "\n"; + break; + } + } + else + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Unable to find property: " << (*firstPropIt)->id << "\n"); + } ++firstPropIt; } @@ -224,27 +253,90 @@ void FGAIMultiplayer::update(double dt) if (prevIt->second.properties.size() == nextIt->second.properties.size()) { - std::vector<FGFloatPropertyData>::const_iterator prevPropIt; - std::vector<FGFloatPropertyData>::const_iterator prevPropItEnd; - std::vector<FGFloatPropertyData>::const_iterator nextPropIt; - std::vector<FGFloatPropertyData>::const_iterator nextPropItEnd; + std::vector<FGPropertyData*>::const_iterator prevPropIt; + std::vector<FGPropertyData*>::const_iterator prevPropItEnd; + std::vector<FGPropertyData*>::const_iterator nextPropIt; + std::vector<FGPropertyData*>::const_iterator nextPropItEnd; prevPropIt = prevIt->second.properties.begin(); prevPropItEnd = prevIt->second.properties.end(); nextPropIt = nextIt->second.properties.begin(); nextPropItEnd = nextIt->second.properties.end(); while (prevPropIt != prevPropItEnd) { - float val = (1-tau)*prevPropIt->value + tau*nextPropIt->value; - PropertyMap::iterator pIt = mPropertyMap.find(prevPropIt->id); + PropertyMap::iterator pIt = mPropertyMap.find((*prevPropIt)->id); + //cout << " Setting property..." << (*prevPropIt)->id; + if (pIt != mPropertyMap.end()) - pIt->second->setFloatValue(val); + { + //cout << "Found " << pIt->second->getPath() << ":"; + + int ival; + float val; + switch ((*prevPropIt)->type) { + case SGPropertyNode::INT: + case SGPropertyNode::BOOL: + case SGPropertyNode::LONG: + ival = (int) (1-tau)*((double) (*prevPropIt)->int_value) + + tau*((double) (*nextPropIt)->int_value); + pIt->second->setIntValue(ival); + //cout << "Int: " << ival << "\n"; + break; + case SGPropertyNode::FLOAT: + case SGPropertyNode::DOUBLE: + val = (1-tau)*(*prevPropIt)->float_value + + tau*(*nextPropIt)->float_value; + //cout << "Flo: " << val << "\n"; + pIt->second->setFloatValue(val); + break; + case SGPropertyNode::STRING: + case SGPropertyNode::UNSPECIFIED: + //cout << "Str: " << (*nextPropIt)->string_value << "\n"; + pIt->second->setStringValue((*nextPropIt)->string_value); + break; + default: + // FIXME - currently defaults to float values + val = (1-tau)*(*prevPropIt)->float_value + + tau*(*nextPropIt)->float_value; + //cout << "Unk: " << val << "\n"; + pIt->second->setFloatValue(val); + break; + } + } + else + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Unable to find property: " << (*prevPropIt)->id << "\n"); + } + ++prevPropIt; ++nextPropIt; } } // Now throw away too old data - if (prevIt != mMotionInfo.begin()) { + if (prevIt != mMotionInfo.begin()) + { --prevIt; + + MotionInfo::iterator delIt; + delIt = mMotionInfo.begin(); + + while (delIt != prevIt) + { + std::vector<FGPropertyData*>::const_iterator propIt; + std::vector<FGPropertyData*>::const_iterator propItEnd; + propIt = delIt->second.properties.begin(); + propItEnd = delIt->second.properties.end(); + + //cout << "Deleting data\n"; + + while (propIt != propItEnd) + { + delete *propIt; + propIt++; + } + + delIt++; + } + mMotionInfo.erase(mMotionInfo.begin(), prevIt); } } @@ -281,17 +373,46 @@ void FGAIMultiplayer::update(double dt) t -= h; } + std::vector<FGPropertyData*>::const_iterator firstPropIt; + std::vector<FGPropertyData*>::const_iterator firstPropItEnd; speed = norm(linearVel) * SG_METER_TO_NM * 3600.0; - - std::vector<FGFloatPropertyData>::const_iterator firstPropIt; - std::vector<FGFloatPropertyData>::const_iterator firstPropItEnd; firstPropIt = it->second.properties.begin(); firstPropItEnd = it->second.properties.end(); while (firstPropIt != firstPropItEnd) { - float val = firstPropIt->value; - PropertyMap::iterator pIt = mPropertyMap.find(firstPropIt->id); + PropertyMap::iterator pIt = mPropertyMap.find((*firstPropIt)->id); + //cout << " Setting property..." << (*firstPropIt)->id; + if (pIt != mPropertyMap.end()) - pIt->second->setFloatValue(val); + { + switch ((*firstPropIt)->type) { + case SGPropertyNode::INT: + case SGPropertyNode::BOOL: + case SGPropertyNode::LONG: + pIt->second->setIntValue((*firstPropIt)->int_value); + //cout << "Int: " << (*firstPropIt)->int_value << "\n"; + break; + case SGPropertyNode::FLOAT: + case SGPropertyNode::DOUBLE: + pIt->second->setFloatValue((*firstPropIt)->float_value); + //cout << "Flo: " << (*firstPropIt)->float_value << "\n"; + break; + case SGPropertyNode::STRING: + case SGPropertyNode::UNSPECIFIED: + pIt->second->setStringValue((*firstPropIt)->string_value); + //cout << "Str: " << (*firstPropIt)->string_value << "\n"; + break; + default: + // FIXME - currently defaults to float values + pIt->second->setFloatValue((*firstPropIt)->float_value); + //cout << "Unk: " << (*firstPropIt)->float_value << "\n"; + break; + } + } + else + { + SG_LOG(SG_GENERAL, SG_DEBUG, "Unable to find property: " << (*firstPropIt)->id << "\n"); + } + ++firstPropIt; } } @@ -359,4 +480,3 @@ FGAIMultiplayer::setDoubleProperty(const std::string& prop, double val) SGPropertyNode* pNode = props->getChild(prop.c_str(), true); pNode->setDoubleValue(val); } - diff --git a/src/MultiPlayer/mpmessages.hxx b/src/MultiPlayer/mpmessages.hxx index a210e48c9..12655a0ce 100644 --- a/src/MultiPlayer/mpmessages.hxx +++ b/src/MultiPlayer/mpmessages.hxx @@ -39,6 +39,7 @@ #include <plib/sg.h> #include <simgear/compiler.h> +#include <simgear/props/props.hxx> #include <simgear/math/SGMath.hxx> #include "tiny_xdr.hxx" @@ -109,16 +110,26 @@ struct T_PositionMsg { xdr_data_t angularAccel[3]; }; -// Property message -struct T_PropertyMsg { - xdr_data_t id; - xdr_data_t value; +struct FGPropertyData { + unsigned id; + + // While the type isn't transmitted, it is needed for the destructor + SGPropertyNode::Type type; + union { + int int_value; + float float_value; + char* string_value; + }; + + ~FGPropertyData() { + if ((type == SGPropertyNode::STRING) || (type == SGPropertyNode::UNSPECIFIED)) + { + delete [] string_value; + } + } }; -struct FGFloatPropertyData { - unsigned id; - float value; -}; + // Position message struct FGExternalMotionData { @@ -149,7 +160,7 @@ struct FGExternalMotionData { SGVec3f angularAccel; // The set of properties recieved for this timeslot - std::vector<FGFloatPropertyData> properties; + std::vector<FGPropertyData*> properties; }; #endif diff --git a/src/MultiPlayer/multiplaymgr.cxx b/src/MultiPlayer/multiplaymgr.cxx index b87662b43..53a6e1666 100644 --- a/src/MultiPlayer/multiplaymgr.cxx +++ b/src/MultiPlayer/multiplaymgr.cxx @@ -33,16 +33,18 @@ #include <plib/netSocket.h> +#include <simgear/misc/stdint.hxx> #include <simgear/timing/timestamp.hxx> #include <simgear/debug/logstream.hxx> +#include <simgear/props/props.hxx> #include <AIModel/AIManager.hxx> #include <Main/fg_props.hxx> - #include "multiplaymgr.hxx" #include "mpmessages.hxx" #define MAX_PACKET_SIZE 1200 +#define MAX_TEXT_SIZE 128 // These constants are provided so that the ident // command can list file versions @@ -54,77 +56,80 @@ const char sMULTIPLAYMGR_HID[] = MULTIPLAYTXMGR_HID; // For now only that static list FGMultiplayMgr::IdPropertyList FGMultiplayMgr::sIdPropertyList[] = { - {100, "surface-positions/left-aileron-pos-norm"}, - {101, "surface-positions/right-aileron-pos-norm"}, - {102, "surface-positions/elevator-pos-norm"}, - {103, "surface-positions/rudder-pos-norm"}, - {104, "surface-positions/flap-pos-norm"}, - {105, "surface-positions/speedbrake-pos-norm"}, - {106, "gear/tailhook/position-norm"}, + {100, "surface-positions/left-aileron-pos-norm", SGPropertyNode::FLOAT}, + {101, "surface-positions/right-aileron-pos-norm", SGPropertyNode::FLOAT}, + {102, "surface-positions/elevator-pos-norm", SGPropertyNode::FLOAT}, + {103, "surface-positions/rudder-pos-norm", SGPropertyNode::FLOAT}, + {104, "surface-positions/flap-pos-norm", SGPropertyNode::FLOAT}, + {105, "surface-positions/speedbrake-pos-norm", SGPropertyNode::FLOAT}, + {106, "gear/tailhook/position-norm", SGPropertyNode::FLOAT}, - {200, "gear/gear[0]/compression-norm"}, - {201, "gear/gear[0]/position-norm"}, - {210, "gear/gear[1]/compression-norm"}, - {211, "gear/gear[1]/position-norm"}, - {220, "gear/gear[2]/compression-norm"}, - {221, "gear/gear[2]/position-norm"}, - {230, "gear/gear[3]/compression-norm"}, - {231, "gear/gear[3]/position-norm"}, - {240, "gear/gear[4]/compression-norm"}, - {241, "gear/gear[4]/position-norm"}, + {200, "gear/gear[0]/compression-norm", SGPropertyNode::FLOAT}, + {201, "gear/gear[0]/position-norm", SGPropertyNode::FLOAT}, + {210, "gear/gear[1]/compression-norm", SGPropertyNode::FLOAT}, + {211, "gear/gear[1]/position-norm", SGPropertyNode::FLOAT}, + {220, "gear/gear[2]/compression-norm", SGPropertyNode::FLOAT}, + {221, "gear/gear[2]/position-norm", SGPropertyNode::FLOAT}, + {230, "gear/gear[3]/compression-norm", SGPropertyNode::FLOAT}, + {231, "gear/gear[3]/position-norm", SGPropertyNode::FLOAT}, + {240, "gear/gear[4]/compression-norm", SGPropertyNode::FLOAT}, + {241, "gear/gear[4]/position-norm", SGPropertyNode::FLOAT}, - {300, "engines/engine[0]/n1"}, - {301, "engines/engine[0]/n2"}, - {302, "engines/engine[0]/rpm"}, - {310, "engines/engine[1]/n1"}, - {311, "engines/engine[1]/n2"}, - {312, "engines/engine[1]/rpm"}, - {320, "engines/engine[2]/n1"}, - {321, "engines/engine[2]/n2"}, - {322, "engines/engine[2]/rpm"}, - {330, "engines/engine[3]/n1"}, - {331, "engines/engine[3]/n2"}, - {332, "engines/engine[3]/rpm"}, - {340, "engines/engine[4]/n1"}, - {341, "engines/engine[4]/n2"}, - {342, "engines/engine[4]/rpm"}, - {350, "engines/engine[5]/n1"}, - {351, "engines/engine[5]/n2"}, - {352, "engines/engine[5]/rpm"}, - {360, "engines/engine[6]/n1"}, - {361, "engines/engine[6]/n2"}, - {362, "engines/engine[6]/rpm"}, - {370, "engines/engine[7]/n1"}, - {371, "engines/engine[7]/n2"}, - {372, "engines/engine[7]/rpm"}, - {380, "engines/engine[8]/n1"}, - {381, "engines/engine[8]/n2"}, - {382, "engines/engine[8]/rpm"}, - {390, "engines/engine[9]/n1"}, - {391, "engines/engine[9]/n2"}, - {392, "engines/engine[9]/rpm"}, + {300, "engines/engine[0]/n1", SGPropertyNode::FLOAT}, + {301, "engines/engine[0]/n2", SGPropertyNode::FLOAT}, + {302, "engines/engine[0]/rpm", SGPropertyNode::FLOAT}, + {310, "engines/engine[1]/n1", SGPropertyNode::FLOAT}, + {311, "engines/engine[1]/n2", SGPropertyNode::FLOAT}, + {312, "engines/engine[1]/rpm", SGPropertyNode::FLOAT}, + {320, "engines/engine[2]/n1", SGPropertyNode::FLOAT}, + {321, "engines/engine[2]/n2", SGPropertyNode::FLOAT}, + {322, "engines/engine[2]/rpm", SGPropertyNode::FLOAT}, + {330, "engines/engine[3]/n1", SGPropertyNode::FLOAT}, + {331, "engines/engine[3]/n2", SGPropertyNode::FLOAT}, + {332, "engines/engine[3]/rpm", SGPropertyNode::FLOAT}, + {340, "engines/engine[4]/n1", SGPropertyNode::FLOAT}, + {341, "engines/engine[4]/n2", SGPropertyNode::FLOAT}, + {342, "engines/engine[4]/rpm", SGPropertyNode::FLOAT}, + {350, "engines/engine[5]/n1", SGPropertyNode::FLOAT}, + {351, "engines/engine[5]/n2", SGPropertyNode::FLOAT}, + {352, "engines/engine[5]/rpm", SGPropertyNode::FLOAT}, + {360, "engines/engine[6]/n1", SGPropertyNode::FLOAT}, + {361, "engines/engine[6]/n2", SGPropertyNode::FLOAT}, + {362, "engines/engine[6]/rpm", SGPropertyNode::FLOAT}, + {370, "engines/engine[7]/n1", SGPropertyNode::FLOAT}, + {371, "engines/engine[7]/n2", SGPropertyNode::FLOAT}, + {372, "engines/engine[7]/rpm", SGPropertyNode::FLOAT}, + {380, "engines/engine[8]/n1", SGPropertyNode::FLOAT}, + {381, "engines/engine[8]/n2", SGPropertyNode::FLOAT}, + {382, "engines/engine[8]/rpm", SGPropertyNode::FLOAT}, + {390, "engines/engine[9]/n1", SGPropertyNode::FLOAT}, + {391, "engines/engine[9]/n2", SGPropertyNode::FLOAT}, + {392, "engines/engine[9]/rpm", SGPropertyNode::FLOAT}, - {800, "rotors/main/rpm"}, - {801, "rotors/tail/rpm"}, - {810, "rotors/main/blade1_pos"}, - {811, "rotors/main/blade2_pos"}, - {812, "rotors/main/blade3_pos"}, - {813, "rotors/main/blade4_pos"}, - {820, "rotors/main/blade1_flap"}, - {821, "rotors/main/blade2_flap"}, - {822, "rotors/main/blade3_flap"}, - {823, "rotors/main/blade4_flap"}, - {830, "rotors/tail/blade1_pos"}, - {831, "rotors/tail/blade2_pos"}, + {800, "rotors/main/rpm", SGPropertyNode::FLOAT}, + {801, "rotors/tail/rpm", SGPropertyNode::FLOAT}, + {810, "rotors/main/blade1_pos", SGPropertyNode::FLOAT}, + {811, "rotors/main/blade2_pos", SGPropertyNode::FLOAT}, + {812, "rotors/main/blade3_pos", SGPropertyNode::FLOAT}, + {813, "rotors/main/blade4_pos", SGPropertyNode::FLOAT}, + {820, "rotors/main/blade1_flap", SGPropertyNode::FLOAT}, + {821, "rotors/main/blade2_flap", SGPropertyNode::FLOAT}, + {822, "rotors/main/blade3_flap", SGPropertyNode::FLOAT}, + {823, "rotors/main/blade4_flap", SGPropertyNode::FLOAT}, + {830, "rotors/tail/blade1_pos", SGPropertyNode::FLOAT}, + {831, "rotors/tail/blade2_pos", SGPropertyNode::FLOAT}, - {1001, "controls/flight/slats"}, - {1002, "controls/flight/speedbrake"}, - {1003, "controls/flight/spoilers"}, - {1004, "controls/gear/gear-down"}, - {1005, "controls/lighting/nav-lights"}, + {1001, "controls/flight/slats", SGPropertyNode::FLOAT}, + {1002, "controls/flight/speedbrake", SGPropertyNode::FLOAT}, + {1003, "controls/flight/spoilers", SGPropertyNode::FLOAT}, + {1004, "controls/gear/gear-down", SGPropertyNode::FLOAT}, + {1005, "controls/lighting/nav-lights", SGPropertyNode::FLOAT}, + + {10001, "sim/multiplay/transmission-freq-hz", SGPropertyNode::STRING}, + {10002, "sim/multiplay/chat", SGPropertyNode::STRING}, /// termination - {0, 0} + {0, 0, SGPropertyNode::UNSPECIFIED} }; ////////////////////////////////////////////////////////////////////// @@ -271,15 +276,103 @@ FGMultiplayMgr::SendMyPosition(const FGExternalMotionData& motionInfo) memcpy(Msg + sizeof(T_MsgHdr), &PosMsg, sizeof(T_PositionMsg)); char* ptr = Msg + sizeof(T_MsgHdr) + sizeof(T_PositionMsg); - std::vector<FGFloatPropertyData>::const_iterator it; + std::vector<FGPropertyData*>::const_iterator it; it = motionInfo.properties.begin(); + //cout << "OUTPUT PROPERTIES\n"; while (it != motionInfo.properties.end() - && ptr < (Msg + MAX_PACKET_SIZE - sizeof(T_PropertyMsg))) { - T_PropertyMsg pMsg; - pMsg.id = XDR_encode_uint32(it->id); - pMsg.value = XDR_encode_float(it->value); - memcpy(ptr, &pMsg, sizeof(T_PropertyMsg)); - ptr += sizeof(T_PropertyMsg); + && ptr < (Msg + MAX_PACKET_SIZE - sizeof(xdr_data_t))) { + + // First elements is the ID + xdr_data_t xdr = XDR_encode_uint32((*it)->id); + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + + // The actual data representation depends on the type + switch ((*it)->type) { + case SGPropertyNode::INT: + case SGPropertyNode::BOOL: + case SGPropertyNode::LONG: + xdr = XDR_encode_uint32((*it)->int_value); + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + //cout << "Prop:" << (*it)->id << " " << (*it)->type << " "<< (*it)->int_value << "\n"; + break; + case SGPropertyNode::FLOAT: + case SGPropertyNode::DOUBLE: + xdr = XDR_encode_float((*it)->float_value);; + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + //cout << "Prop:" << (*it)->id << " " << (*it)->type << " "<< (*it)->float_value << "\n"; + break; + case SGPropertyNode::STRING: + case SGPropertyNode::UNSPECIFIED: + { + // String is complicated. It consists of + // The length of the string + // The string itself + // Padding to the nearest 4-bytes. + const char* lcharptr = (*it)->string_value; + + if (lcharptr != 0) + { + // Add the length + ////cout << "String length: " << strlen(lcharptr) << "\n"; + uint32_t len = strlen(lcharptr); + //cout << "String length unint32: " << len << "\n"; + xdr = XDR_encode_uint32(len); + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + + if (len != 0) + { + + // Now the text itself + int lcount = 0; + while ((*lcharptr != '\0') && (lcount < MAX_TEXT_SIZE)) + { + xdr = XDR_encode_int8(*lcharptr); + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + lcharptr++; + lcount++; + } + + //cout << "Prop:" << (*it)->id << " " << (*it)->type << " " << len << " " << (*it)->string_value; + + // Now pad if required + while ((lcount % 4) != 0) + { + xdr = XDR_encode_int8(0); + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + lcount++; + //cout << "0"; + } + + //cout << "\n"; + } + } + else + { + // Nothing to encode + xdr = XDR_encode_uint32(0); + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + //cout << "Prop:" << (*it)->id << " " << (*it)->type << " 0\n"; + } + + } + break; + + default: + //cout << " Unknown Type: " << (*it)->type << "\n"; + xdr = XDR_encode_float((*it)->float_value);; + memcpy(ptr, &xdr, sizeof(xdr_data_t)); + ptr += sizeof(xdr_data_t); + //cout << "Prop:" << (*it)->id << " " << (*it)->type << " "<< (*it)->float_value << "\n"; + break; + } + ++it; } @@ -314,6 +407,7 @@ FGMultiplayMgr::SendTextMessage(const string &MsgText) ////////////////////////////////////////////////// unsigned iNextBlockPosition = 0; T_ChatMsg ChatMsg; + char Msg[sizeof(T_MsgHdr) + sizeof(T_ChatMsg)]; while (iNextBlockPosition < MsgText.length()) { strncpy (ChatMsg.Text, @@ -324,7 +418,10 @@ FGMultiplayMgr::SendTextMessage(const string &MsgText) memcpy (Msg + sizeof(T_MsgHdr), &ChatMsg, sizeof(T_ChatMsg)); mSocket->sendto (Msg, sizeof(T_MsgHdr) + sizeof(T_ChatMsg), 0, &mServer); iNextBlockPosition += MAX_CHAT_MSG_LEN - 1; + } + + } // FGMultiplayMgr::SendTextMessage () ////////////////////////////////////////////////////////////////////// @@ -464,14 +561,107 @@ FGMultiplayMgr::ProcessPosMsg(const char *Msg, netAddress & SenderAddress, for (unsigned i = 0; i < 3; ++i) motionInfo.angularAccel(i) = XDR_decode_float(PosMsg->angularAccel[i]); - T_PropertyMsg* PropMsg - = (T_PropertyMsg*)(Msg + sizeof(T_MsgHdr) + sizeof(T_PositionMsg)); - while ((char*)PropMsg < Msg + len) { - FGFloatPropertyData pData; - pData.id = XDR_decode_uint32(PropMsg->id); - pData.value = XDR_decode_float(PropMsg->value); - motionInfo.properties.push_back(pData); - ++PropMsg; + + //cout << "INPUT MESSAGE\n"; + xdr_data_t* xdr = (xdr_data_t*) + (Msg + sizeof(T_MsgHdr) + sizeof(T_PositionMsg)); + while ((char*)xdr < Msg + len) { + FGPropertyData* pData = new FGPropertyData; + SGPropertyNode::Type type = SGPropertyNode::UNSPECIFIED; + + // First element is always the ID + pData->id = XDR_decode_uint32(*xdr); + //cout << pData->id << " "; + xdr++; + + // Check the ID actually exists and get the type + unsigned i = 0; + bool found = false; + while (FGMultiplayMgr::sIdPropertyList[i].name) + { + if (sIdPropertyList[i].id == pData->id) + { + found = true; + pData->type = sIdPropertyList[i].type; + } + + i++; + } + + if (found == true) + { + // How we decode the remainder of the property depends on the type + switch (pData->type) { + case SGPropertyNode::INT: + case SGPropertyNode::BOOL: + case SGPropertyNode::LONG: + pData->int_value = XDR_decode_uint32(*xdr); + xdr++; + //cout << pData->int_value << "\n"; + break; + case SGPropertyNode::FLOAT: + case SGPropertyNode::DOUBLE: + pData->float_value = XDR_decode_float(*xdr); + xdr++; + //cout << pData->float_value << "\n"; + break; + case SGPropertyNode::STRING: + case SGPropertyNode::UNSPECIFIED: + { + // String is complicated. It consists of + // The length of the string + // The string itself + // Padding to the nearest 4-bytes. + uint32_t length = XDR_decode_uint32(*xdr); + xdr++; + //cout << length << " "; + + if ((length > 0) && (length < MAX_TEXT_SIZE)) + { + pData->string_value = new char[length + 1]; + //cout << " String: "; + + for (int i = 0; i < length; i++) + { + pData->string_value[i] = (char) XDR_decode_int8(*xdr); + xdr++; + //cout << pData->string_value[i]; + } + + pData->string_value[length] = '\0'; + + // Now handle the padding + while ((length % 4) != 0) + { + xdr++; + length++; + //cout << "0"; + } + } + else + { + pData->string_value = new char[1]; + pData->string_value[0] = '\0'; + } + + //cout << "\n"; + } + break; + + default: + pData->float_value = XDR_decode_float(*xdr); + cerr << "Unknown Prop type " << pData->id << " " << pData->type << "\n"; + xdr++; + break; + } + + motionInfo.properties.push_back(pData); + } + else + { + // We failed to find the property. We'll try the next packet immediately. + //cout << " Unknown\n"; + } } FGAIMultiplayer* mp = getMultiplayer(MsgHdr->Callsign); @@ -505,6 +695,7 @@ FGMultiplayMgr::ProcessChatMsg(const char *Msg, netAddress& SenderAddress) T_ChatMsg* ChatMsg = (T_ChatMsg *)(Msg + sizeof(T_MsgHdr)); SG_LOG ( SG_NETWORK, SG_ALERT, "Chat [" << MsgHdr->Callsign << "]" << " " << MsgBuf << endl); + delete [] MsgBuf; } // FGMultiplayMgr::ProcessChatMsg () ////////////////////////////////////////////////////////////////////// diff --git a/src/MultiPlayer/multiplaymgr.hxx b/src/MultiPlayer/multiplaymgr.hxx index ae9bee238..ca9072e40 100644 --- a/src/MultiPlayer/multiplaymgr.hxx +++ b/src/MultiPlayer/multiplaymgr.hxx @@ -54,9 +54,11 @@ struct FGExternalMotionInfo; class FGMultiplayMgr { public: + struct IdPropertyList { unsigned id; const char* name; + SGPropertyNode::Type type; }; static IdPropertyList sIdPropertyList[]; diff --git a/src/Network/multiplay.cxx b/src/Network/multiplay.cxx index 4db3fb11e..4f5c62656 100644 --- a/src/Network/multiplay.cxx +++ b/src/Network/multiplay.cxx @@ -198,14 +198,68 @@ bool FGMultiplay::process() { // now send the properties PropertyMap::iterator it; for (it = mPropertyMap.begin(); it != mPropertyMap.end(); ++it) { - FGFloatPropertyData pData; - pData.id = it->first; - pData.value = it->second->getFloatValue(); + FGPropertyData* pData = new FGPropertyData; + pData->id = it->first; + pData->type = it->second->getType(); + + switch (pData->type) { + case SGPropertyNode::INT: + case SGPropertyNode::LONG: + case SGPropertyNode::BOOL: + pData->int_value = it->second->getIntValue(); + break; + case SGPropertyNode::FLOAT: + case SGPropertyNode::DOUBLE: + pData->float_value = it->second->getFloatValue(); + break; + case SGPropertyNode::STRING: + case SGPropertyNode::UNSPECIFIED: + { + // FIXME: We assume unspecified are strings for the moment. + + const char* cstr = it->second->getStringValue(); + int len = strlen(cstr); + + if (len > 0) + { + pData->string_value = new char[len + 1]; + strcpy(pData->string_value, cstr); + } + else + { + // Size 0 - ignore + pData->string_value = 0; + } + + //cout << " Sending property " << pData->id << " " << pData->type << " " << pData->string_value << "\n"; + break; + } + default: + // FIXME Currently default to a float. + //cout << "Unknown type when iterating through props: " << pData->type << "\n"; + pData->float_value = it->second->getFloatValue(); + break; + } + motionInfo.properties.push_back(pData); } FGMultiplayMgr* mpmgr = globals->get_multiplayer_mgr(); mpmgr->SendMyPosition(motionInfo); + + // Now remove the data + std::vector<FGPropertyData*>::const_iterator propIt; + std::vector<FGPropertyData*>::const_iterator propItEnd; + propIt = motionInfo.properties.begin(); + propItEnd = motionInfo.properties.end(); + + //cout << "Deleting data\n"; + + while (propIt != propItEnd) + { + delete *propIt; + propIt++; + } } return true;