Going multi-platform, part 3 : First throwback

Last weekend I worked on getting the lazarus / free pascal build of “Phase 2” to look and play exactly the same as the delphi build. I had to change some small things here and there, but after a few hours you can now no longer distinguish between the two builds, maybe except for performance. It looks that some stuff that’s pretty fast with delphi is kinda slow with fpc, for example accessing stringlists and stuff. But that’s nothing that can’t be easily optimized, so the first goal of getting the different compiler builds on par is done. This also means that the game is fully playable under linux.

But during my playtestings on linux (I ditched my ubuntu installation with it’s horrible ubuntu one interface btw., and now use mint) I noticed that all descriptions of nations, units, technologies, etc. were missng, as well as the whole credits text. And after hours of debugging, checking encodings, creating test applications, etc. I found out that NativeXml is not able to load text contained within XML nodes on linux. So a node like this :

[xml] This is a test description [/xml]

Will return an empty node value on Linux. No matter what I tried, accessing it directly, via the first childnode, etc. it was always empty. At first I thought I’d be doing it wrong (though it worked fine on windows), but then I did a very simple test that failed : I loaded up the XML with NativeXml and directly saved it to disk afterwards. And guess what? All texts within the xml nodes were removed by the library!

So it seems that I can’t use NativeXml for linux due to this severe bug. Their forums seem dead (registered there the weekend, but haven’t even been unlocked there so I couldn’t post the problem), and finding people that use it for linux is almost impossible. So all the thousands of lines of code I replaced to get the xml stuff to work on windows were just a waste of time, and I’ll have to remove this library again. I took a look at other xml libraries, but most either only supported delphi or were too bloated (dozens of units, huge source files, different dependencies, etc.). But well, that’s part of the learning process that makes programming so much fun (and sometimes so frustrating), and for the next external library I’m going to use (I prefer to write most of the stuff myself anyway) I’ll first check and see if it works on all my intented platforms.

And what now? Is the linux port in danger? No, rest assured, it’s not! Instead of relying on an external library for loading and saving xml I have written my own xmlwrapper that abstracts free pascal’s and delphi’s different xml interfaces into a single structure that I can use in my game (and coming projects). So now I load up an xml document via my own wrapper and compiler directives control wether delphi’s xml interface or free pascal’s DOM is used to fill this dynamic xml structure from the given file. The syntax is leaned towards the style of delphi’s xml implementation and parts of the game have already been changed to use my new xmlwrapper. So in my code it looks like this to get values from the xmlwrapper :

[delphi]VFS.LoadXML(‘data\xml\nationinfo.xml’, TmpXML); for i := 0 to High(Nation) do begin Nation[i].History := TmpXML.Root.NodesByIndex[i].Nodes[‘history’].NodeValue; for j := 0 to LocalizationDB.LangID.Count-1 do Nation[i].Name[j] := TmpXML.Root.NodesByIndex[i].Attributes[’name_’+LowerCase(LocalizationDB.LangID[j])].AsString; Nation[i].Stronghold := TmpXML.Root.NodesByIndex[i].Attributes[‘stronghold’].AsInteger; with TmpXML.Root.NodesByIndex[i].Nodes[‘basefactor’] do begin Nation[i].BaseFactor.Growth := Attributes[‘growth’].AsSingle; Nation[i].BaseFactor.Loyality := Attributes[’loyality’].AsSingle; Nation[i].BaseFactor.Ressources := Attributes[‘ressources’].AsSingle; … [/delphi]

So much for an open source xml library that was supposed to work with linux. So I guess this weekend will pretty much look like the second last one with me replacing lots of lines of xml-related code :(