Chaos Project

RPG Maker => RPG Maker Scripts => Topic started by: Fantasist on August 20, 2008, 03:13:37 pm

Title: Crash-proof saving questions
Post by: Fantasist on August 20, 2008, 03:13:37 pm
I had this idea, but I finally decided to actually implement it. Normally, game data is stored in the files in a particular order. If the order is changed or new data is added, the savegame can't load, or the game will crash eventually. But if I use a loop and check for the loaded objects' class in each iteration and assign them to the respected global variable, data will be loaded properly no matter how badly the order is changed. After the loop, if any globals are still 'nil', I create a new instance and assign it. Basically, the read_save_data method will be something like this:


def read_save_data(file)
 
  characters = frame_count = $game_system = $game_switches = $game_variables = nil
  $game_self_switches = $game_screen = $game_actors = $game_party = nil
  $game_troop = $game_map = $game_player = nil
 
  data = [characters, frame_count, $game_system, $game_switches,
  $game_variables, $game_self_switches, $game_screen, $game_actors,
  $game_party, $game_troop, $game_map, $game_player]
 
  # Checking each loaded object's class and assigning accordingly
  while !data.any? {|obj| obj == nil}
    stuff = Marshal.load(file)
    if stuff.is_a?(Array)
      characters = stuff
    elsif stuff.is_a?(Numeric)
      frame_count = stuff
    elsif stuff.is_a?(Game_System)
      $game_system        = stuff
    end
    #
    #and so on..
    #
    Graphics.frame_count = frame_count
  end
 
  #Creating new instances of extra objects
  $ams = AMS.new if $ams == nil
  $item_bag = Item_Bag.new if $item_bag = nil
  #
  #and so on..
  #
end


The only catch is that data of same classes can't be recognised (like arrays and numbers). Even that can be corrected by checking the arrays, but numbers...

So... discuss :)
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 20, 2008, 03:57:35 pm
Why not use begin-rescue-end like I do in DREAM for the Save script? The code is easier to read and faster in processing.
Title: Re: Crash-proof saving questions
Post by: Fantasist on August 21, 2008, 06:24:47 am
Of course, but I want to make a script that people can use without having to dump their saves. Sometimes, nothing will go wrong while loading but only when the game actually begins (like itembag and ams).
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 21, 2008, 06:35:43 am
You'll have to iterate through all possible instance variables of the classes with OBJ.instance_variables. Or you could create a new object and copy the existing values to the new objects.

Other than that I don't recommend doing that. It will turn out complicated and it will not cover all existing scripts.
Title: Re: Crash-proof saving questions
Post by: Fantasist on August 21, 2008, 07:00:48 am
QuoteYou'll have to iterate through all possible instance variables of the classes with OBJ.instance_variables. Or you could create a new object and copy the existing values to the new objects.


Good point... Well, I guess I won't be doing this right now.
Title: Re: Crash-proof saving questions
Post by: Zeriab on August 21, 2008, 10:21:04 am
When were are talking about saving here is something interesting I have made :3
It's a string buffer where you can marshal objects into as if it was a file. I am sure Blizz can see its uses.
class StringBuffer < IO
   MODE_STRING = 1
   MODE_FILE_MARSHAL = 2
   MODE_FILE_BINMODE = 3
   ##
   # Initialization of the String Buffer
   # The mode can be MODE_STRING, MODE_FILE_MARSHAL or MODE_FILE_BINMODE
   #
   def initialize(data = nil, mode = MODE_FILE_MARSHAL, compressed = true)
     if data.nil?
       @data = ''
     else
       # Check which type the data is
       case mode
       when MODE_STRING
         @data = data
       when MODE_FILE_MARSHAL
         begin
           @data = load_data(data)
         rescue
           @data = ''
         end
       when MODE_FILE_BINMODE
         if FileTest.exists?(data)
           f = File.open(data, 'rb')
           f.binmode
           @data = f.read
           f.close
         end
       end
       # Decompress the data if it is compressed
       if compressed
         @data = Zlib::Inflate.inflate(@data)
       end
     end
   end
 
   ##
   # Save to file
   # The mode can be MODE_FILE_MARSHAL or MODE_FILE_BINMODE
   #
   def save(filename, mode = MODE_FILE_MARSHAL, compress = true)
     # Check whether the data should be compressed
     if compress
       data = Zlib::Deflate.deflate(@data)
     else
       data = @data
     end
     # Check whether to save in binary or marshal mode
     case mode
     when MODE_FILE_MARSHAL
       save_data(data, filename)
     when MODE_FILE_BINMODE
       f = File.open(filename, 'w+')
       f.binmode
       f.print data
       f.close
     end
   end

   ##
   # Get data
   #
   def data
     return @data
   end
 
   ##
   # Binary mode
   #
   def binmode
     # Do nothing
   end
 
   ##
   # Write data
   #
   def write(data)
     @data += data
   end
 
   ##
   # Get char
   #
   def getc
     return @data.slice!(0)
   end
 
   ##
   # Read an amount of bytes
   #
   def read(amount)
     return @data.slice!(0...amount)
   end
end


On a side note I would most definitely recommend having the save file in a specific order. It simplifies matters greatly.
As for dumping objects in saves. For the majority of scripts just having the data in Game_System would suffice.
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 21, 2008, 10:48:03 am
That's true. But Game_Actor is also often being used in scripts.

I especially like the compression. >:3 <3

EDIT: Isn't it "f.write data" instead of "f.print data"? O.o;
Title: Re: Crash-proof saving questions
Post by: Zeriab on August 21, 2008, 11:05:26 am
Game_Actor or Game_System. It's really the same deal. Sometimes you can also have compatibility with old saves by using defensive programming.

I am glad you like the StringBuffer :3
You can use both f.write and f.print. I believe they do the same thing, but I haven't researched it.
Wait no, they are different. The syntax is f.write(aString) while it is f.print(objects*)
It probably just converts each object to a string and uses the write operation on them in order the arguments are inputted.
Since I only use one argument f.write would probably be better although I don't know.

Anyway maybe you could consider building onto the string buffer and also allow it to save data encrypted :3
Or first compress and then encrypt it. That would be awesome ^^
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 21, 2008, 11:08:45 am
Or: DREAM_encrypt -> compress -> other_encrypt -> compress again

You just gave me the idea I need for DREAM 5. ^_^
Title: Re: Crash-proof saving questions
Post by: Zeriab on August 21, 2008, 11:16:24 am
That indeed my motivation >:3
I you might want to compress first because it might be able to compress much better before than after the encryption. I don't know though, this would require some testing.
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 21, 2008, 11:20:32 am
I was going to test it first anyway. I want to get a minimal filesize, lol.
Title: Re: Crash-proof saving questions
Post by: Zeriab on August 21, 2008, 11:41:34 am
In that case it could be interesting of you to know that I on average got a decrease of file size with about a factor 4. ;)
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 21, 2008, 11:45:07 am
Nice, 25% save file size sounds good. I can't wait to try it out. Right after CP has reached beta status and probably before Blizz-ABS 2.0. >:3
Title: Re: Crash-proof saving questions
Post by: Zeriab on August 21, 2008, 01:59:11 pm
Indeed :3
This was with a pretty much blank project though so the validity is questionable. ^^
Title: Re: Crash-proof saving questions
Post by: Blizzard on August 21, 2008, 02:05:00 pm
When you said "Blank Project", you remembered me of Zerizzacon... <_<;
Title: Re: Crash-proof saving questions
Post by: Fantasist on August 22, 2008, 04:36:14 am
Quote
It's a string buffer where you can marshal objects into as if it was a file. I am sure Blizz can see its uses.


I don't see anything yet :'(
I'll paste the code in RMXP and look hard O_O
Thanks Zeriab :)

*powers up Bliz and Zeriab b/c I feel their awesomeness <3*
Title: Re: Crash-proof saving questions
Post by: Zeriab on August 22, 2008, 07:37:05 am
To help you I would suggest you try making a StringBuffer.new instead of a File.open(filename, 'wb') in Scene_Save.
Look at what happens. It would be and idea to make many prints ;)
Title: Re: Crash-proof saving questions
Post by: Fantasist on August 22, 2008, 12:18:06 pm
Okay, except the print thing, I think this simply tries to compress the data. I need to look up the f.print command.