A "deserialize" method is a method that can take a stream of data that was serialized from an object and recreate the original object from it.
In the BaseStorage case I used a deserialize constructor (a method that creates an object from a serialized data stream "reader").
This means that you are correct, the constructor you referred to is the deserializing method in the BaseStorage case.
This however reveals the real issue with the system.
Lets go back to StorageDeed.cs.
In there you will find:
Code:
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
Storage.Serialize(writer);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Storage = new BaseStorage(reader);
}
As you can see above when I deserialize the storage I create a new "BaseStorage" regardless of the real storage class.
This is where the real fix should be implemented instead of the work-around I suggested before.
We need to change the serialization to serialize the Storage type name first and than use Activator.CreateInstance to create an instance of the storage using the "reader" as an argument for the constructor.
The serialization should look like this:
Code:
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1); //note version is 1 now
writer.Write(this.GetType().FullName); //serialize the type of the real storage
Storage.Serialize(writer);
}
The deserialization should look something like this (not tested):
Code:
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if ( version >= 1 )
{
string typeName = reader.ReadString(); //read the storage type name
if ( !string.IsNullOrEmpty(typeName) ) //make sure we have a name
{
Type storageType = ScriptCompiler.FindTypeByFullName(typeName); //get the storage type
if ( storageType != null ) //make sure we have a type
{
Storage = Activator.CreateInstance( storageType, new object[]{ reader } ); //create a storage from the type we saved with the data stream we have
}
}
}
else
{
Storage = new BaseStorage(reader); //old behavior so we can load a save file from old server
}
if ( Storage == null )
{
//something went wrong and we can't load the storage deed correctly, change the name so the GM/Admin can replace it with a new one.
this.Name="This deed is broken, please return it to a GM for replacement!!!";
}
}
When you get the above code to compile please test it with both old and new storage deeds.
See if it can work correctly with new storage deeds and make sure it can't recover old storage deeds (because the information we need wasn't saved).
On a side note:
There is a way to actually recover the old deeds.
It involves in using the type of the storagedeed to determine what is the type of the storage itself.
I chose not to do it because I don't have the time.
If you want to tackle this than you can wait for the server to load completely and than execute a command (that you'll have to write) which:
1. loops through all the StorageDeed's in the world.
2. If the Storage is BaseStorage than replace the Storage with a new Storage that matches the StorageDeed real type.
For example:
Code:
//you already know how to get all the items in the world from specific type
foreach ( storageDeed in allStorageDeedsInTheWorld )
{
switch ( storageDeed.GetType() )
{
case typeof(BardStorageDeed):
storageDeed.Storage = BardStorage.Storage;
break;
case typeof(ToolStorageDeed):
storageDeed.Storage = ToolStorage.Storage;
break;
//and so forth
}
}