Skip to content

TriGalaxy (open Beta) wartet auf euch

Mir ist aufgefallen, dass es im letzten Jahr wenig Posts von mir gab. Das lag daran, dass ich äußerst beschäftigt war mit der Entwicklung von:


Das neue, kostenlose Open-World Multiplayer-Science-Fiction-Rollenspiel für Android!



Unnötig zu erwähnen, dass auch dieses neueste Spiel nicht allein von mir ist. Maßgeblich für den Client verantwortlich ist Uwe Post.

Im Moment ist das Spiel noch in der "open beta"-Phase.
Die epische Storyline wird, zusammen mit einigen anderen Funktionen (zB multiplayer-quests), erst in Version 1.0 starten.
Alles andere funktioniert aber bereits!

Es gilt eine komplette Galaxie zu erkunden!


Fremde Planeten und Raumstationen zu besuchen...


...Handel zu betreiben ...


...und Quests für, mehr oder weniger gut aussehende, Aliens zu erledigen.

JSON vs. xstream

Das diverse Tools oder Bibliotheken sich gerne nicht so gut verstehen ist nichts neues. Aber manchmal fällt schwer, zu sagen, welches davon jetzt Mist baut.
Aber von vorne: Für ein neues Projekt werden Metadaten in XML angeliefert, die in einer Datenbank gespeichert werden sollen. Nun ist das auseinander Pflücken von XML-Files ziemlich mühselig. Ganz zu schweigen davon, dass die Daten in einem anderen Schritt wieder zusammen gesetzt werden müssen.
Es bot sich also eine elegante Lösung an: die XML-Files mit xstream in ein POJO de-serialisieren, validieren und ebenfalls mit xstream in eine JSON-Repräsentation umwandeln - und ab damit in die CouchDB!
Das funktioniert auch ganz wunderbar. Auch der umgekehrte Weg - den JSON-String wieder in ein POJO de-serialisieren - klappt ohne Probleme.

Die Probleme fangen erst an, wenn man mit einer entsprechenden Library an die CouchDB geht, und ein org.json.JSONObject zurück bekommt. Denn in dem daraus de-serialisiertem POJO, war auf einmal in einer darin enthaltenen Map systematisch key und value vertauscht. Die CouchDB war als Problemquelle sehr schnell ausgeschlossen, denn mit dem von ihr zurück gelieferten JSON-String trat das Problem nicht auf. Der String jedoch, der von org.json.JSONObject.toString() geliefert wurde, unterschied sich merklich von dem, was CouchDB lieferte.

Nun ist es so, dass xstream eine Map, wie zB "Map" folgendermaßen als JSON serialisiert:
"mapObjectName": {
   "entry": [
      { 
         "string": "theKey",
         "CustomObject": { "someField": "fieldValue" }
      }
   ]
}


Von org.json.JSONObject.toString() wird aber folgendes ausgegeben:
"mapObjectName": {
   "entry": [
      { 
         "CustomObject": { "someField": "fieldValue" }
         "string": "theKey",
      }
   ]
}

Dafür gibt es zwei Gründe: zum einen schreibt JSON nicht vor, das die Daten in der richtigen Reihenfolge sein müssen. Zum anderen, versucht es das JSONObject auch gar nicht erst - das Problem tritt nämlich nicht erst beim ausgeben der Daten auf, sondern liegt bereits darin begründet, wie diese intern gespeichert werden.

Und das ist genau die Stelle, an der es schwer fällt einen schuldigen zu finden. Ist xstream schuld (bzw. der verwendete Driver für JSON), weil über die JSON-spec hinaus darauf vertraut, dass die Daten immer in der richtigen Reihenfolge sind? Könnte xstream ein Map überhaupt anders serialisieren, um das zu umgehen? Oder macht das "Feature" von JSON, Daten eben explizit unsortiert zu behandeln, mehr Probleme als es löst?

Da ich weder die Zeit noch die Lust hatte, diesen Fragen auf den Grund zu gehen, und es das Problem ohnehin nicht gelöst hätte, hab ich einfach bei der Implementierung angesetzt. Da die Java-library freie Software ist, war das die einfachste Lösung.
Es musste nur in zwei Konstuktoren von org.json.JSONOBject folgende Zeile geändert werden:
Von
this.map = new HashMap();

Zu
this.map = new LinkedHashMap();


...das "import java.util.LinkedHashMap;" fügt eine gute IDE automatisch ein ;-)

Urlaub in der Unterwelt


Gestresst von all den Katastrophen in der Welt der Lebenden?
Eröffne dein eigenes Hotel in Santa Daemonica, dem Lieblings-Urlaubsort der Unterwelt, dem Mallorca der Monster, Usedom der Untoten, Domrep der Dämonen!

Ein Android-handy ist dafür allerdings schon nötig. Und auch eine Internet-flat für selbiges sollte vorhanden sein, denn es handelt sich um einen "Multiplayer Hotel Manager From Hell".
Und um etwaigen Fragen zuvor zu kommen: nein, das Spiel nicht nicht allein von mir - aber ich hab einen nicht unerheblichen Teil dazu beigetragen.
Es ist vielleicht nicht mega umfangreich, aber ein netter Zeitvertreib für Zwischendurch.

Also auf nach Santa Daemonica!

Das tolle an "Standards" ist, dass es so viele davon gibt

So zum Beispiel, was die Formatierung von Datums- und Zeitangaben angeht.

In Java's DateFormat wird für das spezifizieren eines Zeitoffset der RFC 822 unterstützt, wo man einfach mit dem Zeichen "z" diesen Offset im Format "+HHmm" parsen kann.
Hätte man also einen Datums-String, der folgendermaßen aussieht:
2011-03-23T22:15:00.000+0100

kann man das mit zB SimpleDateFormat mit folgendem Format-String parsen:
yyyy-MM-dd'T'HH:mm:ss.SSSz


Soweit, so schön. Problematisch wird es allerdings, wenn man solche Angaben in XML-Dokumenten haben möchte.
Die XSD-Spezifikation stellt einen Typ "xs:dateTime" bereit, der einen String erwartet, der dem oben angegebenen "ähnlich" sieht. ähnlich, weil ein kleines Detail eben doch anders sein muss: im Offset, müssen Stunden und Minuten durch einen Doppelpunkt getrennt werden! Damit würde der String also so aussehen:
2011-03-23T22:15:00.000+01:00

...und der SimpleDateFormater würde das nicht als valide Datumsangabe ansehen, gemäß dem oben stehenden FormatString! Denn der RFC 822 sieht an dieser Stelle keinen Doppelpunkt vor. An den hält sich XSD auch gar nicht, sondern an RFC 3339 (und auch das nur partiell - RFC 3339 erlaubt einige Dinge, die xs:dateTime nicht akzeptiert. zB ein Leerzeichen statt dem "T" in der Mitte zu benutzen).

Der geneigte Entwickler möchte vermutlich bereits an dieser Stelle den Kopf auf die Tischplatte knallen. Nun das war zumindest meine erste Reaktion. Die Zweite war: "da gibts doch bestimmt was von Ratiopharm... äh, ich meine Apache (Commons)." Die haben ja sonst auch für alle gängigen Probleme "schon mal etwas vorbereitet". Bei der Suche stieß ich dann darauf, dass es sogar schon etwas in Java eingebautes gibt!
Man soll es nicht für möglich halten: "javax.xml.bind.DatatypeConverter" stellt eine Methode "parseDateTime" bereit, die einen "lexicalXSDDateTime"-String erwartet. ...natürlich, da hätte man ja drauf kommen können, dass eine Datumsangabe ein Datentyp ist

Was hat man früher ohne mobiles Internet gemacht?

Also abgesehen davon, dem Wahnsinn anheim zu fallen?
Ich musste mal wieder fest stellen, dass so eine Zugfahrt sehr viel entspannter ist, wenn man Internet hat. Mit einem Andoid-handy sowie einem passenden Datentarif (bei O2 schon für 10€ pro Monat) ist das sehr einfach machbar - wenn man von den Funklöchern absieht! Ich hab mir auch sagen lassen, dass iPhone-user diesbezüglich in die Röhre gucken... also was das Benutzen des Handy als Modem für den Schleppie angeht.

Jedenfalls kann man dann nämlich nicht nur die fehlenden Libraries nachladen, die man braucht um unterwegs am neuesten Projekt weiter zu basteln - nein, man kann sich auch youtube-videos anschauen. Oder noch besser: seine Mitreisenden damit unterhalten. Zum Beispiel, wenn der Zug, der durch eine eingefrohrene Weiche oder eine defekte Signalanlage bereits 40 Minuten verspätung hatte, auf einmal wegen eines "Personenschadens" auf offener Strecke hält, und nach einem Umweg plötzlich 3 Stunden Verspätung hat! Dann bietet sich nämlich folgendes Video an: Bodo Wartke - Reisetagebuch!!!

Wenn man jetzt noch in Betracht zieht, dass die Bahn selbst, wegen der Wetterlage vom Reisen mit der Bahn ab rät, dann erscheint einem der Beitrag von Bodo gar nicht mehr so übertrieben.
Aber hey, wenigstens funktioniert die Heizung! Nachdem ja im Sommer da reihenweise die Klimaanlagen ausgefallen waren, weil die Bahn ja nicht damit rechnen konnte, dass es im Sommer auch mal warm wird, hatte ich schon befürchtet, dass die auch nicht damit rechnen, dass es im Winter kalt wird.

Der berüchtigte "Lockschaden" ist zwar ausgeblieben - aber am Zielort angekommen ist der Zug dennoch nicht. Denn aufgrund der hohen Verspätung, wurde einfach schon 2 Stunden vor erreichen des Zielorts Feierabend gemacht. Wie man von da aus weiter kommt? Tja, dass wusste der Zugführer auch nicht.