Re: Adding to player structure.

From: Daniel A. Koepke (dkoepke@california.com)
Date: 11/11/99


On Thu, 11 Nov 1999, Emil Nilimaa wrote:

> Now what i want to know is:

Please read the comments above and inside of player_special_data_saved.

> I been trying to change some stuff in there, since i first added races
> as "byte race;", but now want to change it to "int race;". Anyways if
> i put "int race" in one place, the game crashes, if i move it to
> another it goes just fine...shrug.

This problem is almost undoubtedly due to you using binary player files
and changing the size of the record (as is the case if you move from
'byte' to 'int' -- where 'byte' is sized at 1 byte and 'int' is sized at 4
bytes).  If you do this you MUST either convert or delete the player file.
Why?  Let's look at an example.

Our structure looks like,

    struct binary_record {
        char buf[10];
        int a;
    };

and we've written four of these out to a file.  Our file looks like:


    abcdefghi____1 jklmnopqr____0 stuvwxyz!____2 abcdefghi_1000

The undescores (_) stand for a \0 and the spaces are just a visual aid to
indicate the end of one record and the beginning of the next.  Now, of
course, this isn't exactly accurate.  A real binary file wouldn't have the
numbers in any discernable format.  A one would not be represented by the
byte '1', since that byte, as per ASCII, has the value 49 and not 1.  I
could use hexidecimal to attempt to demonstrate, but it'd really draw out
and confuse a rather simple example.  Okay, so we've written this out and
we can read the records just fine.  But then we decide that we don't
really need to use an integer (4 bytes) for the value in 'a'.  We can get
by using a short, which 2 bytes.  Our new structure looks like:

    struct binary_record {
        char buf[10];
        short a;
    };

Next time we try to read the file, we encounter a problem.  In the below,
the 'v' indicates the file position after we have read one record:

                v
    abcdefghi____1

Note that we did not read in the entire record.  Why not?  Because that's
not a record, anymore.  We changed the length of our record, so instead of
being 14 bytes overall (10 chars and one integer), it is now 12 bytes.
This means that our old file, with four records, now looks like this to
the reading code:

    abcdefghi___ _1jklmnopqr_ ___0stuvwxyz !____2abcdef ghi_1000

You can see that just reading in the first record wrong causes all of the
other records to get more and more incorrect.  If we tried to write this
out to the file as it has been read, we corrupt the file.  Note that the
third record doesn't even have a proper string ending, the second and
third records have invalid numbers, and there's now garbage at the end of
the file.  With meaningful data, such as a character's name and level we
can see the imapct:

    NAME............ LVL
    Bubba              5
    James              2
    Rogers           122
    Admin            255

Which is saved in the format:

    Bubba___________0x05 James___________0x02 Rogers__________0x7A
    Admin___________0xFF

Again, spaces and line breaks are just viewer conveniences, and not
actually included in the file.  We then decide we want more than just 255
levels, so we change LVL to be short integer (from 1 byte to 2 bytes).
Here comes trouble, because we read in the J of the second record's name
as part of Bubba's level.  We'll see:

    Bubba___________0x05 0x4A

as Bubba's record.

I hope that provides some insight into your problem, the way to solve it,
etc.  If not, ask me in private e-mail and I'll try to explain it better.

-dak


     +------------------------------------------------------------+
     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |
     +------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/15/00 PST