ID:2082525
 
Ever need to do something before the world initializes?

Here's a simple pattern to do it:

var/pre_init/pre_init = new()

pre_init
New()
//do whatever you need here. The map isn't loaded yet. Only global variables.


But one thing about this I never liked was the fact that I didn't like leaving all these global variables hanging around.

Here's a macro-based solution (Credit to the SS13 guys for making me aware of more of the C-style preprocessor semantics) that makes sure no matter how many initialization events you have, you only use one global object:

#define HOOK_EVENT(evname) /init_event/##evname/New();
#define INIT_EVENT(evname) /init_event/New(){..();new/init_event/##evname()};HOOK_EVENT(##evname)

var
init_event/__init_event = new()
initialized = 0
list/__post_init

init_event
New()
__post_init = list(src)
proc
PostInit()
__init_event = null

/*
Extend post-initialization to atoms if you need:

atom
var
tmp/post_init = 0

New()
if(initialized)
post_init&&PostInit()
else if(post_init) __post_init[src] = 1
proc
PostInit() //entire map is guaranteed to be loaded when this is called
*/


world
New()
..()
PostInit()
proc
PostInit()
if(!initialized)
initialized = 1
for(var/d in __post_init)
d:PostInit()
__post_init = null


The above little bit of code creates two macros that make the semantics for working with pre-initialization events a little bit less ugly.

INIT_EVENT(some_initialization_step)
//do something here


This will automatically create a new /init_event subtype called /init_event/some_initialization_step as well as create an override of /init_event/New():

/init_event/New()
..()
new/init_event/some_initialization_step()


The code you put below the INIT_EVENT() macro will be part of the subtype you created's New() function by default.

This means that you don't actually need to store the some_initialization_step object in a global variable to hook the New() function to do things before the world starts up.

If you want to do something else with the same initialization step later on in the code, you can use the second preprocessor macro, HOOK_EVENT:

HOOK_EVENT(some_initialization_step)
..() //supercall if you don't want to override the default behavior
//do additional stuff here


I know, everyone says BOO! MACROS!

I like them. They make ugly patterns pretty.
Digging this.