RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

How to Roll Back Serialization/Deserialization

Lokai

Knight
How to Roll Back Serialization/Deserialization

The way Serialization works is this:
- values are written to the save file when the world saves
- the world loads, and values are read from the file

This may sound like an over-simplification, but it is not.

The beauty of this is you CAN usually undo changes made to your system when it blows up,
even changes made on something complex like PlayerMobile. The exception to this is when your
Deserialization code tries to deserialize something else. In that case, you open a can of
worms if you try to load, and in most cases, mistakes will require you to wipe all of that type.

Here is an example: ( For this example, assume this is PlayerMobile, and we are just looking at a
snippet of the code. Also, assume everything works as is in the first part of the example.)

Code:
//Serialization:
writer.Write((int)28); //original version before edits

//version 28
writer.Write((bool)my_bool_value_28);
writer.Write((int)my_int_value_28);
for (int x=0;x < my_int_value_28; x++)
{
    writer.Write((bool)my_bool_array_28[x]);
}

//version 27
//...
//version 26
//... etc.
Now, let's assume we add a system that modifies our PlayerMobile.
To get the new system to work, we increment our version, and add the new variables:

Code:
//Serialization:
writer.Write((int)29); //new version after edits

//version 29

writer.Write((int)my_int_value_29);
for (int x=0;x < my_int_value_29; x++)
{
    writer.Write((int)my_int_array_29[x]);
}
writer.Write((bool)my_bool_value_29);
writer.Write((double)my_double_value_29);

//version 28 <========<==========<===========this was the old version===<======
writer.Write((bool)my_bool_value_28);
writer.Write((int)my_int_value_28);
for (int x=0;x < my_int_value_28; x++)
{
    writer.Write((bool)my_bool_array_28[x]);
}

//version 27
//...
//version 26
//... etc.
Whether or not we loaded the values right the first time, as soon as we save the world, we are going to
put these new values into the save file. From now on, when we load the world, it will try to fill these
values into all PlayerMobile types. But let's say something goes wrong. Let's say we tried this, and we
tried that, and nothing will work. Here is what we have to remember:

WHAT WAS THE CONDITION OF PLAYERMOBILE DURING THE LAST SUCCESSFUL "SAVE"?

If we know the answer to this one question, then we can backtrack and fix it.
Here's how.

First, we need to decide what we want to use. Let's assume we have the original script (version 28)
and we want to use that in the end. We can't just slap that back in and start using it, because the
variables will not load correctly. First, we must DESERIALIZE the changes we made. We do that by editing
the script we want to use -- ONLY THE DESERIALIZE PORTION -- to read in the saved data. This is the part
that confuses people, we actually don't care what happens to the data we read in, the important thing is
to SAVE the file correctly, but to do that we need to load something - even if that something is garbage.

Here is what the Deserialization code will look like:

Code:
//Deserialization:

int version = reader.ReadInt(); //

//version 29
if (version == 29)
{
    int DUMMY_READER_INT = 0;

    int my_DUMMY_int_value_29 = reader.ReadInt();
    for (int x=0;x < my_DUMMY_int_value_29; x++)
    {
        DUMMY_READER_INT = reader.ReadInt();
    }

    bool DUMMY_READER_BOOL = reader.ReadBool();
    double DUMMY_READER_DOUBLE = reader.ReadDouble();
}
//version 28 
//... etc.
If you line up this Deserialization code with the Serialization code, you will see the connection.
By reading these values in to DUMMY variables that will never get used, we are basically saying
that we need to get the PlayerMobile to load, but we don't care about those old values any more.

Now that the PlayerMobile will load (and it will) we can save the world, and delete or ignore this code.
It should not be used again anyway, so it should probably be deleted after you save and shut down.
 
Top