1
0
Fork 0

Modified Files:

src/AIModel/AIMultiplayer.cxx src/MultiPlayer/mpmessages.hxx
	src/MultiPlayer/multiplaymgr.cxx
	src/MultiPlayer/multiplaymgr.hxx src/Network/multiplay.cxx
	Apply Stuart Buchanan's multiplayer property/chat patch.
This commit is contained in:
frohlich 2006-10-10 05:17:07 +00:00
parent ae614fa4b8
commit 8a67faaf5a
5 changed files with 491 additions and 113 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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 ()
//////////////////////////////////////////////////////////////////////

View file

@ -54,9 +54,11 @@ struct FGExternalMotionInfo;
class FGMultiplayMgr
{
public:
struct IdPropertyList {
unsigned id;
const char* name;
SGPropertyNode::Type type;
};
static IdPropertyList sIdPropertyList[];

View file

@ -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;