Game Development Community

Loading arrays from datablocks?

by Josh Albrecht · in Torque Game Engine · 03/08/2002 (6:30 pm) · 9 replies

I am attempting to read initialize an array of Point3Fs in the PlayerData class in the function where everything is read from the datablock (unpackData). How do I load an unknown number of Point3F classes from the datablock, to the code? Same questions with strings instead of Point3Fs, but I bet the same idea applies.

I can get a single Point3F to load fine, but the array has my stumped. I would be VERY thankful for any help. :)

#1
03/08/2002 (6:41 pm)
Data sent from script to c++ is in a string form. I Don't know how arrays are transferred, but I think it'd be safe to think it's just one long string.

So an array of 5 integers might look like....

"1 3 5 6 8"

You'll have to parse that string into 5 different integers, and ther are functions given just for that purpose (look in script functions defined in the c++)
#2
03/08/2002 (8:51 pm)
First you need an array in your class such as:

Point3F myPoints[ARRAY_SIZE];

You can define ARRAY_SIZE to whatever you want.

Then create the datablock field in initPersistFields(). For an array, it should look something like this:

addField("myPoints", TypePoint3F, Offset(myPoints, PlayerData), ARRAY_SIZE);

The key is to add ARRAY_SIZE to the end to turn the field into an array.

Then in packData() you send the array to the client:
for (U32 i = 0; i < ARRAY_SIZE; i++) {
   mathWrite(*stream, myPoints[i]);
}

Then in unpackData() just receive the data the same way:
for (U32 i = 0; i < ARRAY_SIZE; i++) {
   mathRead(*stream, &myPoints[i]);
}

Don't worry about having to send a whole array since datablocks are sent only once and ARRAY_SIZE shouldn't have to be that big.

To send a string, just use writeString() and readString() instead of mathWrite(), mathRead(). (And use TypeString instead of TypePoint3F in the addField())

Also it would be a good idea to initialize your array first and fill it with zeros or something. Btw, I haven't really tested the above so I'm not sure if everything's correct.
#3
03/10/2002 (9:15 am)
Wow, that was EXACTLY what I needed! I didnt ever think about adding the array size to the function call. Thank you very much! :)
#4
03/10/2002 (11:35 am)
mathWrite and mathRead are not real functions... What did you mean?
#5
03/10/2002 (1:13 pm)
mathread() and mathwrite() are in mathIO.h. Maybe the file needs to #include "math/mathIO.h" ?

The function just sends the xyz of the point.

inline bool mathWrite(Stream& stream, const Point3F& p)
{
bool success = stream.write(p.x);
success &= stream.write(p.y);
success &= stream.write(p.z);
return success;
}

If you dont want to use mathwrite and mathread just replace it with normal stream->write/read in your packdata() unpackdata():

stream->write(myPoint[i].x);
stream->write(myPoint[i].y);
stream->write(myPoint[i].z);

stream->read(&myPoint[i].x);
stream->read(&myPoint[i].y);
stream->read(&myPoint[i].z);
#6
03/10/2002 (2:03 pm)
Ahh, I had thought they had all the read/write functions in bitstream. Thanks! :)
#7
03/11/2002 (3:59 pm)
This still isnt over... :)

What if I want the datablock to be able to contain any number between 0 and the maximum number of array elements? As it stands now, I loop through and load all 20. If there are not 20 defined in the datablock, then it just keeps reading, messing up the later variables. how can I ONLY load as many array elements as are defined in the function?
#8
03/11/2002 (4:38 pm)
Well, if you initialize the array with zeros, then maybe can assume the data isn't used if the values = 0. Or just send the number of elements before you send the array like:

in packdata()...

stream->write(numPoints);
for (i = 0; i < numPoints; numPoints++) {
mathWrite(*stream, myPoints[i]);
}

then unpack...

stream->read(&numPoints);
for (i = 0; i < numPoints; numPoints++) {
mathRead(*stream, &myPoints[i]);
}

where numPoints is just another field in your datablock that you have to set.
#9
03/11/2002 (4:57 pm)
That second suggestion would be best. Thank you. :)