Crash-proof saving questions

Started by Fantasist, August 20, 2008, 03:13:37 pm

Previous topic - Next topic

Fantasist

August 20, 2008, 03:13:37 pm Last Edit: August 20, 2008, 03:16:40 pm by Fantasist
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 :)
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews




Blizzard

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.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Fantasist

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).
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews




Blizzard

August 21, 2008, 06:35:43 am #3 Last Edit: August 21, 2008, 06:36:59 am by Blizzard
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.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Fantasist

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.
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews




Zeriab

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.

Blizzard

August 21, 2008, 10:48:03 am #6 Last Edit: August 21, 2008, 10:49:44 am by Blizzard
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;
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Zeriab

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 ^^

Blizzard

Or: DREAM_encrypt -> compress -> other_encrypt -> compress again

You just gave me the idea I need for DREAM 5. ^_^
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Zeriab

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.

Blizzard

I was going to test it first anyway. I want to get a minimal filesize, lol.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Zeriab

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. ;)

Blizzard

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
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Zeriab

Indeed :3
This was with a pretty much blank project though so the validity is questionable. ^^

Blizzard

When you said "Blank Project", you remembered me of Zerizzacon... <_<;
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Fantasist

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*
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews




Zeriab

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 ;)

Fantasist

Okay, except the print thing, I think this simply tries to compress the data. I need to look up the f.print command.
Do you like ambient/electronic music? Then you should promote a talented artist! Help out here. (I'm serious. Just listen to his work at least!)


The best of freeware reviews: Gizmo's Freeware Reviews