Game Development Community

ReadPacketData/writePacketData

by Guimo · in Torque Game Engine · 10/15/2006 (10:28 pm) · 5 replies

Hi,
I really hope someone more experienced can help me a little. Im having a problem changing the flyingVehicle networking code.
Basically Im trying to add an attribute to the flyingVehicle called speedBonus. The idea is that one ship can pick a powerup wich gines the player a speed upgrade.

To that end I add two attributes to flyingVehicle.h (just after te mCeilingFactor attribute)
bool bUpdateSpeedBonus;
S32 mSpeedBonus;

then I create the get/set functions:
void FlyingVehicle::setSpeedBonus(S32 val)
{ mSpeedBonus = val;
bUpdateSpeedBonus = true;
}

S32 FlyingVehicle::getSpeedBonus()
{ return mSpeedBonus;
}

I expose them to the console so I can call them from a script. That way each time I get a pickup the bUpdateBonus flag is set to true and the value is sent to clients (thtats the way it works?).

So I change the readPacketData/writePacketData this way:
void FlyingVehicle::writePacketData(GameConnection *connection, BitStream *stream)
{
Parent::writePacketData(connection, stream);

//Write the flag and write the new value if must be updated
stream->writeFlag(bUpdateSpeedBonus);
if(bUpdateSpeedBonus)
stream->write(mSpeedBonus);
bUpdateSpeedBonus = false;
}

void FlyingVehicle::readPacketData(GameConnection *connection, BitStream *stream)
{
Parent::readPacketData(connection, stream);

//Read the flag and the new value if must be updated
bUpdateSpeedBonus = stream->readFlag();
if (bUpdateSpeedBonus)
stream->read(&mSpeedBonus);
bUpdateSpeedBonus = false;

setPosition(mRigid.linPosition,mRigid.angPosition);
mDelta.pos = mRigid.linPosition;
mDelta.rot[1] = mRigid.angPosition;
}


But the problem here is that when I write the bUpdateSpeedBonus flag, the writeFlag method keeps telling me the numBit I write is the 538 and then I write the speed bonus value to the stream, thats ok. The problem is that when I read back the data the readFlag is executed on the flag 629!!!!!! So the method always fails and I cant senf the data. Notice that my lines execute just after the packet reading/writing. This should be working right?

I have read the tdn information but I just dont know whi the readPacketData just gets out of sync with the writePacketData. Please somebody help me.

Luck!
Guimo

#1
10/15/2006 (11:05 pm)
Hi,
I dont know if this has something to do but in the Vehicle class the readPacketData/writePacketData looks like:
void Vehicle::writePacketData(GameConnection *connection, BitStream *stream)
{
Parent::writePacketData(connection, stream);
mathWrite(*stream, mSteering);

mathWrite(*stream, mRigid.linPosition);
mathWrite(*stream, mRigid.angPosition);
mathWrite(*stream, mRigid.linMomentum);
mathWrite(*stream, mRigid.angMomentum);
stream->writeFlag(mRigid.atRest);
stream->writeFlag(mContacts.count == 0);

stream->writeFlag(mDisableMove);
stream->setCompressionPoint(mRigid.linPosition);
}

void Vehicle::readPacketData(GameConnection *connection, BitStream *stream)
{
Parent::readPacketData(connection, stream);
mathRead(*stream, &mSteering);

mathRead(*stream, &mRigid.linPosition);
mathRead(*stream, &mRigid.angPosition);
mathRead(*stream, &mRigid.linMomentum);
mathRead(*stream, &mRigid.angMomentum);
mRigid.atRest = stream->readFlag();
if (stream->readFlag())
mContacts.count = 0;

// Update the rigid state based on the new information
mRigid.updateInertialTensor();
mRigid.updateVelocity();
mRigid.updateCenterOfMass();

mDisableMove = stream->readFlag();
stream->setCompressionPoint(mRigid.linPosition);
}

Now... why is the function setting the compression point in both cases... can this be the problem?
#2
10/16/2006 (1:02 am)
I finally solved using the packUpdate/unpackU'pdate but still not sure about the difference of both methods. Also not sure when an attribute should be packed after or before the controlling client conditional in these methods.

It works now but I hope anyone may suggest some additional reading please.

Luck!
Guimo
#3
10/16/2006 (2:00 am)
Remember to populate the same changes in packUpdate or else other clients will not be seeing the power boost and you will get interpolation errors.
#4
10/16/2006 (4:37 am)
Quote:I finally solved using the packUpdate/unpackU'pdate but still not sure about the difference of both methods. Also not sure when an attribute should be packed after or before the controlling client conditional in these methods.

Afaik writePacketData and readPacketData are only used for the control object. So if you have a player A controlled by clientA the server will call writePacketData for playerA only for sending to clientA. playerB will not receive data that way. The writePacketData method only sends data if it detects the client side predicted simulation is out of sync with the server (there's some kind of crc test involved somewhere), if it is it resends a full update if not no changes are sent.

data written in packUpdate however will be transmit to every client for which the object is in scope. But there is a catch. If you want to send speedUpdate to all clients including the client controlling the player, you need to add it before the

if(stream->writeFlag(getControllingClient() == con && !(mask & InitialUpdateMask)))
  return retmask;

statement. Since except for an initial update, anything below this will already be handled via write/read packetdata for the controlling client so sending it here would be duplication. However, every other client will receive updates on position for this object here as they never see the write/read packet calls.

Another catch is that pack/unpackUpdate can be called quite often so it's usful to wrap updates with readFlag / writeFlag calls to ensure you only send more data when you really need to.

In the case of your speed bonus, you'd simply need to add somewhere above the previous if statement

// in packupdate
if (stream->writeFlag(mask & speedEventMask))
   stream->write(mSpeedBonus);

// in readUpdate
//Read the flag and the new value if must be updated
if ( stream->readFlag() )
   stream->read(&mSpeedBonus);

Assuming you add a new mask in the header called speedEventMaks and set it via setMaskBits(speedEventMask) or you could slot your mSpeedBonus read/write in with one of the other masks if you feel they will generally change at the same time the speed bonus does. The setMaskBits call would be placed anywhere you change the mSpeedBonus eg in setSpeedBonus.
#5
10/16/2006 (1:28 pm)
@Stefan
Thanks... I've updated both and tested in a network. It works fine.

@Gary
Thank you very much for the explanation. It's clear now. You should write this on the TDN.

Luck!
Guimo