Lieber Besucher, herzlich willkommen bei: MastersForum. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.
Zitat
php
//****************************************************************************************************************
// AoM Rec Game Decoder v0.3 beta
//
// ReturnRecGameXml - opens the file and if its a valid AoM rec game returns an xml file with the information
// ParseRecGameXml - Parses the xml file into a more readable form, call a print_r() on the result to see
// how it looks like
//
// This code is distributed as is. There is no waranty that it works and no waranty that it will still work in the future.
// Use it on your on risk!!!
// special thanx go out to Aleste from the Planet Age of Mythology Forum for telling me how to read the rec game
// this PHP Code is (c) 07.2003 by R. Vornholt - You can use it freely as long as this information stays.
// If you want to contact me send me a mail to doc_santonian@die-ohne-clan.de or visit my website at
// http://www.die-ohne-clan.de. If you like the code, visit at least the website and write a few lines at the forum
// or into the guestbook.
// CHANGELOG
//
// - 30.09 - Added support for The Titans Expansion
// - 18.12 - Added support for REALCIVILIZATION attribute in array (cubensis)
//****************************************************************************************************************
//XML DESCRIPTION: (I could not determin the use of a few values, if you can tell me what these values are for, please tell me)
//
// FILENAME: name of the map
// CURRENTPLAYER: Id of the player to whom this rec belongs
// - In SinglePlayer it's always -1
// SCENARIOFILENAME:
// GAMETYPE: always 2
// FILENAMECRC: CRC
// GAMESTARTTIME Starttime of game in Seconds - can be used in PHP date function
// - In Singleplayer its always 0
// MAPVISIBILITY: 0 => Normal, 1 => Revealed
// WORLDRESOURCES: it's always 1, is there a way to change it anyway?
// MAPSIZE: 0 => Normal Map, 1 => Large Map
// RESTRICTEDPAUSES: 0 => Unlimited, else the number of pauses
// GAMEMODE: 0 => Supremacy, 1 => Conquest, 2 => Ligthning, 3 => Deathmatch
// HANDICAPMODE: 0 => No Handicap, 1 => Handicap Free, 2 => Automatic
// - I guess that if the Handicap is 2 it's a rated match
// MAPSEED The Random Seed value to use to generate the same map from the RMS
// DIFFICULTY: 0 => Easy, 1 => Moderate, 2 => Hard, 3 => Titan
// NUMPLAYERS: No. of players
//
// GAMEFLAGS: LOCKEDTEAMS, ALLOWCHEATS, TEAMSHARERESOURCES, TEAMSHAREPOPULATION
// - They have no values afak, they exist or they don't, if they exist they are switched on
//
// PLAYER:
// CLIENTID: Player ID starting with 0
// CONTROLLEDPLAYER Player ID starting with 1
// NAME: Player Name
// - If Player is AI it's the type of AI (Balanced, Boomer, ...)
// RATING: Rating of that player at gametime in that gamemode
// - in Singleplayer it's always 500 for all player
// - in LAN Games it's always 0 for all players
// TYPE: 0 => HumanPlayer, 1 => AI Player, 4 => Observer (Titans only)
// TRANSFORMCOLOR1:
// TRANSFORMCOLOR2:
// TEAM: Team Info
// - In 1vs1 Rated Games both players have 255 as team
// - 255 is Random Team!!!
// CIVILIZATION (AoM): 0 => Zeus, 1 => Poseidon, 2 => Hades,
// 3 => Isis, 4=> Ra, 5 => Set,
// 6 => Odin, 7 => Thor, 8 => Loki,
// 9 => Random All,
// 10 => Random Greek, 11=> Random Norse, 12 => Random Egyptian
//
// CIVILIZATION (Titans): 0 => Zeus, 1 => Poseidon, 2 => Hades,
// 3 => Isis, 4=> Ra, 5 => Set,
// 6 => Odin, 7 => Thor, 8 => Loki,
// 9 => Cronos, 10 => Oranos, 11 => Gaia,
// 12 => Random All, 13 => Random Greek
// 14 = > Random Norse, 15 => Random Egyptian, 16 => Random Atlantean
// AIPERSONALITY: name of Computer AI
//
//
//===============================================================================================================
//
// EXTRA INFORMATION CONTAINED IN THE RECORDED GAME FILE
// -----------------------------------------------------
//
// further down in the file there comes more information but in a binary form. This is what I found out so far:
//
// Team Information:
//
// (the xml team info is 255 for all in random team)
//
// look for the string "Team #" then it goes like this:
//
// Team #ABCCCDCCCDCCCD
//
// A -> Team number in ascii
// B -> no. of players in team in binary
// C -> null value
// D -> playerid in binary
//
// the CCCD block loops B times
//
// The other bytes in the team info I could not (yet) figure out.
//
// Civilisation:
//
// After the team info there is info about each player. Look for the name and then the 11th byte is the civ id
// in binary. If someone chose random team here is the civ he got in the end.
//****************************************************************************************************************
function ReturnRecGameXml($fileName)
{
define( "GAME_SETTINGS_BLOCKSIZE", 0x400 );
define( "GAMESETTINGSOFFSET", 0x59A );
define( "TITAN_ADDITIONAL_SETTINGS_OFFSET", 0x28 );
define( "GAME_SETTINGS_STARTTAG", ASCIItoUTF16( '<GameSettings>' ) );
define( "GAME_SETTINGS_ENDTAG", ASCIItoUTF16( '</GameSettings>' ) );
global $_REAL_CIV;
$xml="";
$xPack=0; //0-> AoM, 1->Titans
$fp = fopen($fileName, "r");
//---- Make sure the file opened
if($fp == null) return false;
//---- Check the header bytes are correct = 'l33t'
$header = fread($fp, 4); //its a 4 byte header
if($header != "l33t") return false;
//---- See how many bytes the uncompressed data will expand to
$sizeBytes = fread($fp, 4);
$size = (int) ord($sizeBytes[0]) //get original file size
+ (ord($sizeBytes[1]) <<![]()
+ (ord($sizeBytes[2]) << 16)
+ (ord($sizeBytes[3]) << 24);
$compressedData = fread($fp, filesize($fileName)-8);
$uncompressed = gzuncompress($compressedData, $size);
//---- Check to make sure the uncompressed data is valid
if($uncompressed == null) return false;
//---- See if we can extract the XML data from the random mess
$uc_nullfree = substr($uncompressed, GAMESETTINGSOFFSET);
//---- Check of this as an AoM game, or an AoT game
if(strpos($uc_nullfree, GAME_SETTINGS_STARTTAG) == 2)
$xPack = 0;
else
{
$uc_nullfree = substr($uc_nullfree, TITAN_ADDITIONAL_SETTINGS_OFFSET);
if(strpos($uc_nullfree, GAME_SETTINGS_STARTTAG) == 2)
$xPack = 1;
else
return false;
}
$final = "";
$pos = 0;
$end = strpos($uc_nullfree, GAME_SETTINGS_ENDTAG);
$skipSize = 4;
while($pos < $size)
{
$final .= substr($uc_nullfree, $pos, GAME_SETTINGS_BLOCKSIZE);
$pos += GAME_SETTINGS_BLOCKSIZE + $skipSize;
if($pos > $end) //there was a skip after the xml where no skip should be... this should work
$skipSize=0;
}
//---- Extract the XML from the data
$end = strpos($final, GAME_SETTINGS_ENDTAG);
$xml = substr($final, 2, $end-2);
//---- Convert the UTF-16 UNICODE into 8 bit ASCII
$xml = UTF16toASCII($xml);
//---- BINARY FIXES
//-- This finds the Actual Team # for the players, no 255 in here!!
$start = strpos($final, "Team #", 0);
$first_start = $start;
while($start !== false)
{
$teamstr = substr($final, $start, 100);
for($m=0; $m<ord($teamstr[7]); $m++)
{
$xml .= "\t<REALTEAM TeamId=\"".($teamstr[6]-1)."\" PlayerId=\"".(ord($teamstr[7 + (4*($m+1))])-1)."\" ></REALTEAM>\n";
}
$start = strpos($final, "Team #", $start+6);
};
//-- We can't actually extract the player names yet, until we have XML decoded
//-- so we have to store the REALCIVILIZATION memory block in a global for now
//-- Grab too much, we can refine it later.. (cubensis)
if( $first_start !== false ) $_REAL_CIV = substr( $final, $first_start, 4000 );
//---- Format the XML, with the inserted tags
$ret_xml = "<GameSettings>\n";
$ret_xml .= "\t<XPACK>".$xPack."</XPACK>\n";
$ret_xml .= substr($xml, strlen("<GameSettings>"));
$ret_xml .= "</GameSettings>";
return($ret_xml);
}
function startElementHandler($parser, $name, $attribs)
{
global $xmldata;
global $i;
global $lastName;
global $playerStart;
$lastName = $name;
if($name == "GAMEFLAGS")
$xmldata["$name"] = $attribs;
else
{
switch($name)
{
case "REALTEAM":
$xmldata[$name][$attribs["PLAYERID"]] = $attribs["TEAMID"];
break;
default:
if($name == "PLAYER")
{
$i++;
$playerStart = true;
}
if($playerStart === true)
{
if($name == "PLAYER")
$xmldata["$name"][$i] = $attribs;
else
$xmldata["$name"][$i] = 0;
}
else
$xmldata["$name"] = 0;
break;
}
}
}
function endElementHandler($parser, $name)
{
}
function cdataHandler($parser, $data)
{
global $xmldata;
global $lastName;
global $playerStart;
global $i;
if((ord($data) != 10) && (ord($data) != 9))
{
switch($lastName)
{
case "REALTEAM":
//do nothing
break;
default:
if($playerStart === true)
$xmldata["$lastName"][$i] = $data;
else
$xmldata["$lastName"] = $data;
break;
}
}
}
function ParseRecGameXml($xml)
{
if( $xml === false ) return false;
global $xmldata;
global $lastName;
global $i;
global $playerStart;
$xmldata = array();
$i = -1;
$playerStart = false;
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElementHandler", "endElementHandler");
xml_set_character_data_handler($parser, "cdataHandler");
if (!xml_parse($parser, $xml, true))
die(sprintf("XML error %d %d", xml_get_current_line_number($parser), xml_get_current_column_number($parser)));
return $xmldata;
}
//- (cubensis)
function UTF16toASCII( $unicode )
{
$data = "";
//---- Implemented a slightly cleaner way of doing this, which doesn't compress 0 value pairs
$i = -2;
$len = strlen( $unicode );
while( $i < $len ) $data .= $unicode[$i+=2];
return $data;
}
//- (cubensis)
function ASCIItoUTF16( $ascii )
{
$data = "";
$len = strlen( $ascii );
for( $i = 0; $i < $len; $i++ )
{
$data .= $ascii[$i];
$data .= chr(0);
}
return $data;
}
//- (cubensis)
function InsertRealCivsIntoArray( $array )
{
if( $array === false ) return false;
global $_REAL_CIV;
//---- For each player in the NAME block, try to extract their
//---- real civilization from the binary block
foreach( $array['NAME'] as $id => $name )
{
$name_search = ASCIItoUTF16($name);
$pos = strpos( $_REAL_CIV, $name_search );
$len = strlen( $name_search );
$offset = $pos + $len + 9;
$real_civ = ord($_REAL_CIV[$offset]);
$array['REALCIVILIZATION'][$id] = $real_civ;
}
return $array;
}
//- (cubensis)
function CivNameFromID( $id, $is_titans = false )
{
$titans = array(
0 => "Zeus", 1 => "Poseidon", 2 => "Hades",
3 => "Isis", 4 => "Ra", 5 => "Set",
6 => "Odin", 7 => "Thor", 8 => "Loki",
9 => "Cronos", 10 => "Oranos", 11 => "Gaia",
12 => "Random All", 13 => "Random Greek", 14 => "Random Norse",
15 => "Random Egyptian", 16 => "Random Atlantean" );
$aom = array(
0 => "Zeus", 1 => "Poseidon", 2 => "Hades",
3 => "Isis", 4 => "Ra", 5 => "Set",
6 => "Odin", 7 => "Thor", 8 => "Loki",
9 => "Random All", 10 => "Random Greek", 11 => "Random Norse",
12 => "Random Egyptian" );
return $is_titans ? $titans[$id] : $aom[$id];
}
/*
$file = 'C:\Documents and Settings\andy\My Documents\My Games\Age of Mythology\Savegame\Recorded Game 3.rcx';
//$file = 'C:\Games\Microsoft Games\Age of Mythology\savegame\Recorded Game 1.rec';
$xml = ReturnRecGameXml( $file );
$array = ParseRecGameXml( $xml );
$array = InsertRealCivsIntoArray( $array );
print_r($array);
*/
?>

Zitat
ps@zelos:~/development/workspace/aoe3rectool/ant/build$ java -jar aoe3rectool.jar /home/ps/tmp/3v3_faith_wischn_lat_vs_inc_hackl_sd_vision.age3rec
Map: New England
MapExt: randommaps.set
Player 0:
Player 1: -WW- Killy
Player 2:
Player 3: -WW-würmchen
Player 4:
Player 5: LClan Inc
Player 6:
Player 7: Player 7
Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »fast_tam« (15.11.2005, 17:53)
Zitat
Map: New England
MapExt: randommaps.set
Number of Players: 6
Player 1: [ Dutch ] -WW- Killy
Player 2: [ Ottomans ] CF CF_Faithhealer
Player 3: [ Portuguese ] -WW- würmchen
Player 4: [ Germans ] LClan BeN_de
Player 5: [ Ottomans ] LClan Inc
Player 6: [ French ] NoX SD_VisionSLR
Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »fast_tam« (16.11.2005, 16:16)