Jump to content
  • entries
    12
  • comments
    47
  • views
    1,748

Entry 00B: Ramsey and a problem I just discovered

PhoenixSoul

147 views

Okay, so I've mostly been working on mapping, and getting art assets taken care of, among other things, but I've come to realize that somewhere down the line...

Saving is no longer working, and that's going to be a huge problem for v.1.0. Right now, saving isn't needed to enjoy the demo, but I intend to have the first chapter of the game story done by the first non-demo version, and in that regard, I need saving to work properly. Thing is, I don't know why it doesn't work. So, I will need help with this, and hopefully, @Kayzee can find time between sessions of that new Switch game (that I'll likely never play due to my wealth privilege level being lower), to aid me. If not...hmmm...

Well, I'll cross that bridge when I get there I guess. I'm still waiting on one thing from one artist, who finally has their laptop all setup, and that's great.

I actually am curious about setting system functions like saving to game switches, if that breaks them. I mean, I set the menu command to a switch is all; it won't appear if the switch is off but I wouldn't of thought that would disable the functionality. Hmmm...

Eh. I've a lot on my mind and it is difficult to focus on gamedev, and fuck, even on gaming. I barely can do much of anything without being distracted by this or that, and it's too damn much! I need help here, but I'm most certainly not getting it! Yeah! I need help here!!!! (and asking for it from people offline gets me a 'fuck-you-but-I-won't-actually-say-it' response)

I love the story I have come up with and I want to deliver it; so can I get some damn help here!? Is that too much to ask!?!?!?!?!?!?!!??



24 Comments


Recommended Comments

When saving no longer woks it's usually because there is some script is using an unsavable object somewhere it shouldn't be. A classic example is khas awesome light effects will refuse to save while the light effects are being used (though I can't remember if it clears stuff properly when switching scenes, and if so it's usually not a problem because most games switch to the menu scene first. Autosave scripts and such still refuse to save though).

 

I made a script just for debugging problems with saving the game:

 

Spoiler

#========================================================================
# ** Save Debugger, by: Kayzee
#------------------------------------------------------------------------
# Will print messages to the console detailing any problems when saving.
# Mostly good for finding scripts that use undumpable objects in places
# where they shouldn't.
#========================================================================

module DataManager
  
  #--------------------------------------------------------------------------
  # * Execute Save (No Exception Processing)
  #--------------------------------------------------------------------------
  def self.save_game_without_rescue(index)
    $game_system.on_before_save
    c = make_save_contents
    c.each_pair do |key, value|
      begin 
        Marshal.dump(value)
      rescue Exception => e
        puts "Save game has encountered errors:"
        puts "Dump error detected in: " + key.to_s
        puts "Error message: " + e.message
        check_object_dump(key, value)
        return false
      end
    end
    File.open(make_filename(index), "wb") do |file|
      Marshal.dump(make_save_header, file)
      Marshal.dump(c, file)
      @last_savefile_index = index
    end
    return true
  end
  
  def self.check_object_dump(key, obj, depth = 0)
    obj.instance_variables.each do |var|
      getvar = obj.instance_variable_get(var)
      begin
        Marshal.dump(getvar)
      rescue Exception => e
        puts "Dump error detected in: " + key.to_s + " " + var.to_s
        puts "Error message: " + e.message
        if depth < 20
          check_object_dump(key.to_s + " " + var.to_s, getvar, depth + 1)
          if getvar.is_a?(Hash)
            getvar.each_pair do |k, v|
              check_object_dump(key.to_s + " " + var.to_s + '[' + k.to_s + ']', v, depth + 1)
            end
          elsif getvar.is_a?(Enumerable)
            getvar.each_with_index do |o, i|
              check_object_dump(key.to_s + " " + var.to_s + '[' + i.to_s + ']', o, depth + 1)
            end
          end
        end
        #puts "Error object dump: " + getvar.inspect
      end
    end
  end
  
end

 

 

Make sure the console is tuned on and try to save in game and the script should find the problem and print details to the console.

 

 

Share this comment


Link to comment

It's best if it's after every other save related script. And if it prints nothing, then it didn't find any undumpable objects or other errors. Note: This is only really useful if the game is actually failing to save, aka when tying to save the game will buzz at you and refuse to save. I assumed that's what you meant by saving not working.

Share this comment


Link to comment

Also: I just made a new version of the save debugger that should catch more problems. So try this out if the old one still reports nothing:

 

Spoiler

#========================================================================
# ** Save Debugger, by: Kayzee
#------------------------------------------------------------------------
# Will print messages to the console detailing any problems when saving.
# Mostly good for finding scripts that use undumpable objects in places
# where they shouldn't.
#========================================================================

module DataManager
  
  #--------------------------------------------------------------------------
  # * Execute Save (No Exception Processing)
  #--------------------------------------------------------------------------
  def self.save_game_without_rescue(index)
    begin
      $game_system.on_before_save
    rescue
      puts "Error with $game_system.on_before_save!"
      puts "Error message: " + e.message
    end

    h = dump_block("header") { make_save_header }
    c = dump_block("contents") { make_save_contents }

    File.open(make_filename(index), "wb") do |file|
      file.write(h)
      file.write(c)
      @last_savefile_index = index
    end
    return true
  end
  
  def self.dump_block(name, &block)
    begin 
      result = block.call
    rescue Exception => e
      puts "Error creating save "+name+"!"
      puts "Error message: " + e.message
      return false
    end
    
    begin
      return Marshal.dump(result)
    rescue Exception => e
      puts "Cannot dump save "+name+"!"
      result.each_pair do |key, value|
        begin 
          Marshal.dump(value)
        rescue Exception => e
          puts "Dump error detected in: " + key.to_s
          puts "Error message: " + e.message
          check_object_dump(key, value)
        end
      end
      return nil
    end
  end
  
  def self.check_object_dump(key, obj, depth = 0)
    obj.instance_variables.each do |var|
      getvar = obj.instance_variable_get(var)
      begin
        Marshal.dump(getvar)
      rescue Exception => e
        puts "Dump error detected in: " + key.to_s + " " + var.to_s
        puts "Error message: " + e.message
        if depth < 20
          check_object_dump(key.to_s + " " + var.to_s, getvar, depth + 1)
          if getvar.is_a?(Hash)
            getvar.each_pair do |k, v|
              check_object_dump(key.to_s + " " + var.to_s + '[' + k.to_s + ']', v, depth + 1)
            end
          elsif getvar.is_a?(Enumerable)
            getvar.each_with_index do |o, i|
              check_object_dump(key.to_s + " " + var.to_s + '[' + i.to_s + ']', o, depth + 1)
            end
          end
        end
      end
    end
  end
  
end

 

 

 

Share this comment


Link to comment
Spoiler

Error creating save contents!
Error message: undefined method `each' for nil:NilClass

 


That's all it printed to the console; it left an unloadable save file.
Unnn...

This is not good, @Kayzee, mi amour.

Edited by PhoenixSoul

Share this comment


Link to comment

Now that's interesting... Okay I know you use my little error backtrace replacement for 'main' (btw the other day I made a version of that that doesn't replace main and works like a normal script), so let me make a version that can call the backtrace code... Try this and see what happens!

 

#========================================================================
# ** Save Debugger, by: Kayzee
#------------------------------------------------------------------------
# Will print messages to the console detailing any problems when saving.
# Mostly good for finding scripts that use undumpable objects in places
# where they shouldn't.
#========================================================================

module DataManager
  
  #--------------------------------------------------------------------------
  # * Execute Save (No Exception Processing)
  #--------------------------------------------------------------------------
  def self.save_game_without_rescue(index)
    begin
      $game_system.on_before_save
    rescue
      puts "Error with $game_system.on_before_save!"
      puts_error(e)
    end

    h = dump_block("header") { make_save_header }
    c = dump_block("contents") { make_save_contents }

    File.open(make_filename(index), "wb") do |file|
      file.write(h)
      file.write(c)
      @last_savefile_index = index
    end
    return true
  end
  
  def self.dump_block(name, &block)
    begin 
      result = block.call
    rescue Exception => e
      puts "Error creating save "+name+"!"
      puts_error(e)
      return false
    end
    
    begin
      return Marshal.dump(result)
    rescue Exception => e
      puts "Cannot dump save "+name+"!"
      result.each_pair do |key, value|
        begin 
          Marshal.dump(value)
        rescue Exception => e
          puts "Dump error detected in: " + key.to_s
          puts_error(e)
          check_object_dump(key, value)
        end
      end
      return nil
    end
  end
  
  def self.check_object_dump(key, obj, depth = 0)
    obj.instance_variables.each do |var|
      getvar = obj.instance_variable_get(var)
      begin
        Marshal.dump(getvar)
      rescue Exception => e
        puts "Dump error detected in: " + key.to_s + " " + var.to_s
        puts_error(e)
        if depth < 20
          check_object_dump(key.to_s + " " + var.to_s, getvar, depth + 1)
          if getvar.is_a?(Hash)
            getvar.each_pair do |k, v|
              check_object_dump(key.to_s + " " + var.to_s + '[' + k.to_s + ']', v, depth + 1)
            end
          elsif getvar.is_a?(Enumerable)
            getvar.each_with_index do |o, i|
              check_object_dump(key.to_s + " " + var.to_s + '[' + i.to_s + ']', o, depth + 1)
            end
          end
        end
      end
    end
  end
  
  def puts_error(e)
    puts "Error message: " + e.message
    return unless defined? Error_Handler
    trace = Error_Handler.do_backtrace(e)
    puts(trace)
  end
  
end

 

Share this comment


Link to comment

Leave it in... or if you rather, use my new one:

 

Spoiler

#==============================================================================
# * Error handling functions.
#==============================================================================

module Error_Handler
  
  def self.script_names
    unless @script_names
      @script_names = load_data('Data/Scripts.rvdata2')
      @script_names.collect! {|script|  script[1]  }
    end
    @script_names
  end
  
  def self.do_backtrace(error)
    backtrace = self.parse_trace(error.backtrace)
    error_line = backtrace.first
    backtrace[0] = ''
    return error_line + ": " + error.message + " (#{error.class})" + backtrace.join("\n\tfrom ") + "\n"
  end
  
  def self.parse_trace(trace)
    out = []
    trace.each_with_index do |line,i|
      if line =~ /{(.*)}(.*)/
        out << (script_names[$1.to_i] + $2)
      elsif line.start_with?(':1:')
        break
      else
        out << line
      end
    end
    out
  end
  
  def trace_me
    begin
      raise
    rescue => exception
      puts trace = Error_Handler.do_backtrace(exception)
    end
  end
  
end

alias rgss_main_without_rescue rgss_main

def rgss_main(&block)
  begin
    rgss_main_without_rescue do
      begin
        block.call
      rescue SystemExit
        exit
      rescue Exception => error
        trace = Error_Handler.do_backtrace(error)
        print(trace)
        raise(error.class, trace, [error.backtrace.first])
      end
    end
  end

end

 

 

If you use the new one remember it no longer replaces the 'Main' script and you can add it like any other script.

Edited by Kayzee

Share this comment


Link to comment
On 4/25/2020 at 7:24 PM, PhoenixSoul said:

Error creating save contents!

@Kayzee, that's literally all it says.

On a side note, I made an event that checks via conditional branch...
$game_system.save_disabled?
with an 'else' branch if it returned false.

It returns false. So, I dunno. Brick wall here. Get out your wand, Rubeus, and do that magic tap to make it open, LMAO

Share this comment


Link to comment

Even with my new one and error checker? Only thing I can think of is a conflict with the old version of the error checker. But I don't think it should have one?

Edited by Kayzee

Share this comment


Link to comment

I don't know.
If I disable script after script, maybe then I'll figure it out, but I don't have enough free time. I barely have enough to get caught up, if that.

Share this comment


Link to comment

It's okay, love. I got further in development than I ever had before, so I suppose that will suffice.

I am an artist, forced to wear the suit of a taskmaster. I suppose, this is my punishment for whatever I did wrong.

I thank you for all you've done for me...

Share this comment


Link to comment

OOOppps... I noticed I made a mistake with the debugger script. No wonder it wasn't working right! It should be:

 

Spoiler

#========================================================================
# ** Save Debugger, by: Kayzee
#------------------------------------------------------------------------
# Will print messages to the console detailing any problems when saving.
# Mostly good for finding scripts that use undumpable objects in places
# where they shouldn't.
#========================================================================

module DataManager
  
  #--------------------------------------------------------------------------
  # * Execute Save (No Exception Processing)
  #--------------------------------------------------------------------------
  def self.save_game_without_rescue(index)
    begin
      $game_system.on_before_save
    rescue
      puts "Error with $game_system.on_before_save!"
      puts_error(e)
    end

    h = dump_block("header") { make_save_header }
    c = dump_block("contents") { make_save_contents }

    File.open(make_filename(index), "wb") do |file|
      file.write(h)
      file.write(c)
      @last_savefile_index = index
    end
    return true
  end
  
  def self.dump_block(name, &block)
    begin 
      result = block.call
    rescue Exception => e
      puts "Error creating save "+name+"!"
      puts_error(e)
      return false
    end
    
    begin
      return Marshal.dump(result)
    rescue Exception => e
      puts "Cannot dump save "+name+"!"
      result.each_pair do |key, value|
        begin 
          Marshal.dump(value)
        rescue Exception => e
          puts "Dump error detected in: " + key.to_s
          puts_error(e)
          check_object_dump(key, value)
        end
      end
      return nil
    end
  end
  
  def self.check_object_dump(key, obj, depth = 0)
    obj.instance_variables.each do |var|
      getvar = obj.instance_variable_get(var)
      begin
        Marshal.dump(getvar)
      rescue Exception => e
        puts "Dump error detected in: " + key.to_s + " " + var.to_s
        puts_error(e)
        if depth < 20
          check_object_dump(key.to_s + " " + var.to_s, getvar, depth + 1)
          if getvar.is_a?(Hash)
            getvar.each_pair do |k, v|
              check_object_dump(key.to_s + " " + var.to_s + '[' + k.to_s + ']', v, depth + 1)
            end
          elsif getvar.is_a?(Enumerable)
            getvar.each_with_index do |o, i|
              check_object_dump(key.to_s + " " + var.to_s + '[' + i.to_s + ']', o, depth + 1)
            end
          end
        end
      end
    end
  end
  
  def self.puts_error(e)
    puts "Error message: " + e.message
    return unless defined? Error_Handler
    trace = Error_Handler.do_backtrace(e)
    puts(trace)
  end
  
end

 

 

 

Share this comment


Link to comment

I tested it out by undoing part of the fix and yes, the debugger showed where the problem was, down the section.

98% precision should be more than enough for powerful debugging; I suggest putting this in your script archives. 👍

Share this comment


Link to comment
×