EXIF-TSO

EXIF-TSO

Inoffizielle Taktikkarten-Meta-Datenbank
 

Links

Introduction

EXIF-TSO is a proposal for storing details of tactical information for The Settlers Online adventures within the graphical files used for laying out tactics.

Technologies

Tactical maps are usually provided in the form of JPEG images.

The JPEG file format allows to store EXIF information, which is ususally used by cameras to store information about used lens and more, but has custom fields.

JSON should be used to represent the data because it is a lightweight both human and machine readable format.

Definition

The following is my proposal for a first version of JSON data to represent the tactical information within a file, stored in the Comments EXIF field. Supported fields should be:

TSOMetaDataVersion
number (mandatory): currently 1.
TMUID
string (mandatory): GUID of map, a unique identifier, see example, but do not reuse the example one!
ReplacesTMUID
string (optional): GUID of map this map is intended to replace.
AdventureID
number (mandatory): one of these:
  • 55: Opening Match / (26+)
  • 56: Opening Match / (36+)
  • 2: Old Friends / Alte Bekannte (32+)
  • 26: Old Ruins / Alte Ruinen (26+)
  • 37: / Arktische Explosion (0+)
  • 3: Stealing from the Rich / Beutelschneider (26+)
  • 32: The Betrayed Little Tailor / Das betrogene Schneiderlein (42+)
  • 4: The End Of The World / Das Ende der Welt (26+)
  • 34: The Heroic Little Tailor / Das heldenhafte Schneiderlein (42+)
  • 33: The Clever Little Tailor / Das kluge Schneiderlein (42+)
  • 5: Bandit Nest / Das Räubernest (36+)
  • 31: The Valiant Little Tailor / Das tapfere Schneiderlein (42+)
  • 75: / Der gestohlene Schlitten (0+)
  • 25: The Shaman / Der Schamane (26+)
  • 29: The Sleeping Vulcano / Der schlafende Vulkan (26+)
  • 6: / Der verschollene Schädel (26+)
  • 77: The Siege / Die Belagerung (26+)
  • 59: Match Three / Die dritte Begegnung (26+)
  • 60: Match Three / Die dritte Begegnung (36+)
  • 8: The Dark Brotherhood / Die dunkle Bruderschaft (42+)
  • 49: Easter Eggs Hunt Begins / Die Eierjagd beginnt (17+)
  • 52: Continued Easter Eggs Hunt / Die Eierjagd geht weiter (17+)
  • 65: Final Match / Die finale Begegnung (26+)
  • 66: Final Match / Die finale Begegnung (36+)
  • 78: The Buccaneer Roundup / Die Freibeuter-Razzia (26+)
  • 63: Match Five / Die fünfte Begegnung (26+)
  • 64: Match Five / Die fünfte Begegnung (36+)
  • 38: / Die Gefängnisinsel (0+)
  • 14: The Island of the Pirates / Die Insel der Freibeuter (26+)
  • 48: Cousins Island / Die Insel des Cousins (17+)
  • 36: The Invasion of the Nords / Die Invasion der Nordmänner (36+)
  • 45: Jester Island / Die Karte des Narren (1+)
  • 71: / Die letzte Insel (0+)
  • 9: / Die Nordmänner (36+)
  • 10: The Dark Priests / Die schwarzen Priester (42+)
  • 11: The Black Knights / Die schwarzen Ritter (42+)
  • 35: The Sons Of The Little Tailor / Die Söhne des Schneiderleins (42+)
  • 70: / Die Suche dauert (0+)
  • 61: Match Four / Die vierte Begegnung (26+)
  • 62: Match Four / Die vierte Begegnung (36+)
  • 12: / Die wilde Waltraut (36+)
  • 57: Match Two / Die zweite Begegnung (26+)
  • 58: Match Two / Die zweite Begegnung (36+)
  • 50: Hunting For Easter Eggs / Eierjagd (17+)
  • 51: New Easter Eggs Hunt / Eine neue Eierjagd (17+)
  • 43: New Experience / Eine neue Erfahrung (1+)
  • 13: Secluded Experiments / Einsame Experimente (42+)
  • 54: Picasso / Fast ein Picasso (17+)
  • 84: / Garrun der Fallensteller (0+)
  • 79: Tomb Raiders / Grabräuber (36+)
  • 73: / Heimatinsel (0+)
  • 46: Hero needed immediately / Held gesucht (1+)
  • 81: Raiding The Raiders / Jagd auf die Jäger (36+)
  • 15: Bounty Hunter / Kopfgeldjäger (26+)
  • 74: / Mehr einsame Experimente (0+)
  • 16: Mother Love / Mutterliebe (36+)
  • 42: Nothing Special / Nichts Besonderes (1+)
  • 72: / Ostereier in den Bergen (0+)
  • 28: Pirate Life / Piratenleben (26+)
  • 17: Roaring Bull / Rasender Bulle (42+)
  • 18: Outlaws / Räuberbande (36+)
  • 44: Retro Style / Retro Stil (1+)
  • 40: Save The Christmas Feat / Rettet das Weihnachtsfest (26+)
  • 41: Save The Christmas Feat / Rettet das Weihnachtsfest (36+)
  • 76: Save The Christmas Feat / Rettet das Weihnachtsfest (0+)
  • 83: / Rückkehr ins Räubernest (26+)
  • 47: Sabotage / Sabotage (17+)
  • 1: Horseback / Sattelfest (26+)
  • 24: Gunpowder / Schießpulver (36+)
  • 30: Sleepy Reef / Schlummerndes Riff (26+)
  • 67: / Schnitzeljagd - Erste Stufe (0+)
  • 69: / Schnitzeljagd - Letzte Stufe (0+)
  • 68: / Schnitzeljagd - Zweite Stufe (0+)
  • 80: Lakeside Treasure / Seeufer-Schatz (36+)
  • 20: Sons of the Veld / Söhne der Steppe (36+)
  • 39: / Steinmetz, Fischer, Jäger, Späher (0+)
  • 19: Witch of the Swamp / Sumpfhexe (26+)
  • 21: Tropical Sun / Tropensonne (26+)
  • 7: Suprise Attack / Überraschungsangriff (36+)
  • 53: Lost Easter Eggs / Verlorene Ostereier (17+)
  • 22: Traitors / Verräter (26+)
  • 23: Victor the Vicious / Viktor der Verschlagene (32+)
  • 82: Whirlwind / Wirbelwind (46+)
AuthorName
string (mandatory)
AuthorGuild
string (optional)
AuthorWorld
string (optional): one of these:
  • de-01: Grünland
  • de-02: Windfeuertal
  • de-03: Bernsteingarten
  • de-04: Steppenwald
  • de-05: Goldenau
  • de-06: Mittsommerstadt
  • de-07: Apfehain
  • de-08: Funkelberg
  • de-09: Schneefeuer
  • de-10: Tuxingen
  • de-11: Morgentau
  • de-12: Andosia
  • de-13: Wildblumental
  • de-14: Glitzerstadt
AuthorContact
string (optional): url where author can be contacted (e.g. official forum profile address)
CreationDate
number (mandatory): Windows integer file time (NOT Linux file time) formatted date.
Strategies
array (optional): an array of objects.
Strategies[].Difficulty
number (optional): describes, on a scale from 0 to 10, with 10 being most difficult, how difficult the author rates this strategy.
Strategies[].RequiredGenerals270
number (optional): Number of required "Generalmajor" (carrying 270 troups) generals; if not specified, 0 is assumed.
Strategies[].RequiredGenerals250
number (optional): Number of required "Veteran" (carrying 250 troups) generals; if not specified, 0 is assumed.
Strategies[].RequiredGenerals220
number (optional): Number of required "???" (carrying 220 troups) generals; if not specified, 0 is assumed.
Strategies[].RequiredGeneralsMdK
number (optional): Number of required "Meister der Kampfkunst" (carrying 220 troups) generals; if not specified, 0 is assumed.
Strategies[].RequiredGenerals200
number (optional): Number of required "Tavernengeneral" (carrying 200 troups) generals; if not specified, 0 is assumed.
Strategies[].RequiredGenerals200Fast
number (optional): Number of required "Schneller General" (carrying 200 troups) generals; if not specified, 0 is assumed.
Strategies[].Recruits
Strategies[].Bows
Strategies[].Militia
Strategies[].Cavalry
Strategies[].Longbows
Strategies[].Soldiers
Strategies[].Crossbows
Strategies[].EliteSoldiers
Strategies[].Canoniers
array (mandatory): specifies required units and expected losses.
Strategies[].(unit).Required
number (mandatory): Number of units of given type that are needed.
Strategies[].(unit).MinLosses
number (optional): Minimum number of units lost following this strategy.
Strategies[].(unit).AvgLosses
number (optional): Average number of units lost following this strategy.
Strategies[].(unit).MaxLosses
number (optional): Maximum Number of units lost following this strategy.
Strategies[].Blocks
bool (mandatory): whether blocks are needed with this strategy.
Strategies[].Locks
bool (mandatory): whether locks are needed with this strategy.

Example

{
  "TSOMetaDataVersion":1,
  "TMUID": "{413B2D52-2228-4961-901E-80AA4B9F096F}",
  "AdventureID":84,
  "AuthorName":"Schmat",
  "AuthorGuild":"",
  "AuthorWorld":"de-12",
  "AuthorContact":"http://forum.diesiedleronline.de/members/1124269-Schmat",
  "CreationDate":1147356755,
  "Strategies":[
    {
      "Difficulty":8,
      "RequiredGenerals270":0,
      "RequiredGenerals250":1,
      "RequiredGenerals220":0,
      "RequiredGenerals200":4,
      "RequiredGenerals200Fast":0,
      "Recruits":{
        "Required":452,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":452
      },
      "Bows":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Militia":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Cavalry":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Longbows":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Soldiers":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Crossbows":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "EliteSoldiers":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Canoniers":{
        "Required":0,
        "MinLosses":0,
        "AvgLosses":0,
        "MaxLosses":0
      },
      "Blocks":false,
      "Locks":false
    }
  ]
}

Software

I do provide a sample implementation in form of a Windows executable TSOEXIFEditor.exe that opens images, offers forms for defining the meta data, and saving again.

Download v0.5

Server-sided processing (PHP)

For server-sided processing of meta data in tactical maps, I provide EXIFTSOReader.php, or you could simply use this snippet:

function read_exif_tso_information($AFilename)
{
  if (!file_exists($AFilename))
  {
    throw new Exception('Missing file!');
  }
  $aEXIF = exif_read_data($AFilename, 'ANY_TAG', true);
  $sComments = $aEXIF['IFD0']['Comments'];
  $sComments = trim(mb_convert_encoding($sComments, 'UTF-8', 'UTF-16LE'));
  $jsonMetaData = json_decode($sComments, true);
  return $jsonMetaData;
}