Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[RGSS3] Is there a way to do finalizers or dtors?

Usually I'd use;
Ruby:
ObjectSpace.define_finalizer( self, proc { STUFF_TO_DO_HERE } )
But RGSS3 doesn't have that.

I think the general idea is if you rely on finalizers in your RGSS then you are doing something wrong, but this sort of breaks down when you're using Win32 libraries.

Why I want a finalizer;
I've tried moving as much as I can to my DLL's DLL_PROCESS_DETACH call, but I'm doing some pretty crazy stuff that requires the RPG Maker Game.exe context to be alive for me to be able to clean up the memory I want to deal with and apparently the RGSS runtime will call the Win32API's FreeLibrary() AFTER it kills its own context (Wtf?).


So is there an RGSS class or point that I can attach to for my clean-up code to be called when the game is shutdown? Or is there a callback that I can attach?

EDIT:
I may have solved this myself:
Ruby:
module SceneManager_XI

  

  def self.exit

    STUFF_TO_DO_HERE # Cleanup library

    super

  end

  

  SceneManager.module_eval { include SceneManager_XI }

  

end
Is this bad practise?

If it's a good idea and doesn't cause any problems I might write my own finalizer system that utilises this.
 

Zeriab

Sponsor

The big question is what happens under exceptional circumstances.

Seemingly trying to rescue SystemExit doesn't seem to work. Nor does ensure really ensure the code is run.
Neither of the following two examples work (nor with Exception => ex instead of SystemExit)
[rgss]begin
  rgss_main { SceneManager.run }
rescue SystemExit => ex
  save_data("Exception: #{ex}", 'exception.txt')
ensure
  save_data("Save ensured", 'ensure.txt')
end
[/rgss]

[rgss]rgss_main do
  begin
    SceneManager.run
  rescue SystemExit => ex
    save_data("Exception: #{ex}", 'exception.txt')
  ensure
    save_data("Save ensured", 'ensure.txt')
  end
end
[/rgss]

Alt+F4 does not trigger the saves. Exiting normally, and pressing F12 does.
 
If you store your Win32API objets in constants or global variables, the RGSS will never call the "free_function" of DL (Win32API) so the FreeLibrary won't be called until the RGSS kills itself.

By the way, the RGSS3 do have the ObjectSpace.define_finalizer but like the bitmap or sprites, it's not immedialty called when the objects are lost... unless you call GC.start.
 
Yeah no clean exit means my tidy up isn't called.

Windows doesn't call FreeLibrary when the host process crashes, does it? It just discards all the library memory in one go with the rest of the process memory. My problem is GPU objects being alive and needing the driver to clean up (Which isn't too much of a problem, crashing is exceptional behaviour)

Maybe I'm too worried
 
I don't know what Windows do.
I could make you try this :
320-48ba291.png

but it won't work with the RGSS3 that doesn't look like to raise an Exception when we press the close button so you can overwrite the WNDProc of the RGSS3 window :
Code:
 

    SetClassLong($HWND,GCL_WNDPROC,(long)Window_Manager::WndProc);

    SetWindowLong($HWND,GWL_WNDPROC,(long)Window_Manager::WndProc);

 
Window_Manager::WndProc is my personnal WndProc and $HWND is the handle to the RGSSWindow.

In Ruby I get the HWND of the main window like this :
Code:
def get_handle()

    unless($HWND)

      hwnd=FindWindowA.call("RGSS Player",nil);

      spid="\x00\x00\x00\x00";

      GetWindowThreadProcessId.call(hwnd,spid);

      gpid=spid.unpack('i')[0];

      pid=Process::pid();

      if(gpid==pid)

        $HWND=hwnd;

      else

        hwnd=GetForegroundWindow.call();

        GetWindowThreadProcessId.call(hwnd,spid);

        gpid=spid.unpack('i')[0];

        if(gpid==pid)

          $HWND=hwnd;

        else

          GetPrivateProfileString.call("Game","Title","",title="\x00"*256,256,".//Game.ini");

          hwnd=FindWindowA.call("RGSS Player",title.delete("\x00"));

          GetWindowThreadProcessId.call(hwnd,spid);

          gpid=spid.unpack('i')[0];

          if(gpid==pid)

            $HWND=hwnd;

          else

            $HWND=0;

            print("Impossible d'obtenir l'handle de la fenêtre de jeu...");

          end

        end

      end

    end

    return $HWND

  end
You can do the same in C++, it's basicly calling the different Windows function that help me to get what I want :p

By overwriting the WndProc you'll lose the F1, F2 and Alt+Enter functions but you'll be able to receive the WM_CLOSE or WM_DESTROY event to make your clean up and exiting the RGSS by calling RGSSEval("exit(0)");
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top