hailstone, I noticed you're doing work on code to validate the XML and give you a list of programs rather than the 1st one, an oft-requested feature. I wanted to first make you aware of the
new Checksums class in the network branch. This is designed to say more than "your files differ" in a network game. Instead, it will be able to tell you which files differ. I think this will only help when messing with mods that are in the development stages and haven't been officially released, but since you were touching that code, I thought I would mention it to you.
Next, the way you went about it is very copy-pastey and bloated. Actual bloat of generated code isn't that big of a deal in this part of the code because it's only run when a game starts, so that part doesn't bother me. However, I would prefer the copy & paste part to be encapsulated in some type of macro. I'm even not opposed to constructs that some would call butt-ugly like this:
#define DONT_DIE(x) try{ (x); } catch (runtime_error e) {Logger::getErrorLog().addXmlError ( path, e.what() ); loadOk = false;}
This allows you to call potentially exception-throwing functions like this:
DONT_DIE(ProducibleType::load(parametersNode, dir, techTree, factionType));
Really though, don't use the name DONT_DIE, that part's a bad example. =) Encapsulating it in a macro also gives us the ability to compile it out by changing the macro with some pre-processor directive. For blocks where you can't make them a one-liner, you can have a start and end macro something like this:
#define DONT_DIE(x) try{ (x); } catch (runtime_error e) {Logger::getErrorLog().addXmlError ( path, e.what() ); loadOk = false;}
#define DONT_DIE_START try{
#define DONT_DIE_END } catch (runtime_error e) {Logger::getErrorLog().addXmlError ( path, e.what() ); loadOk = false;}
Were this something that would easily be broken into separate function calls (for each potentially throw-able operation) I would prefer the Inversion Of Control pattern, but I think that macro-izing what you've already done is a descent solution to this problem.
oops! I just noticed that sometimes you do need to bail, so maybe add a parameter that specifies rather or not to bail on failure?
#define DONT_DIE(a, b) try{ (a); } catch (runtime_error e) {Logger::getErrorLog().addXmlError ( path, e.what() ); loadOk = false; if(b) return false;}
#define DONT_DIE_START try{
#define DONT_DIE_END(a) } catch (runtime_error e) {Logger::getErrorLog().addXmlError ( path, e.what() ); loadOk = false; if(a) return false;}
So other than the copy & paste, it looks like good work