function DisplayModSelection($compare = 0, $type = 'theater') { $fields = array('mod', 'version', $type); $fieldname = $ext = $type; $suffix = $compare ? '_compare' : ''; $js = $vars = $data = array(); $path = array("{$type}s"); foreach ($fields as $field) { switch ($field) { case 'theater': $fieldname = 'theaterfile'; array_unshift($path, 'scripts'); break; case 'map': $path = array('resource', 'overviews'); default: $fieldname = $field; } $data[$field] = $suffix ? $GLOBALS["{$fieldname}{$suffix}"] == $GLOBALS[$fieldname] ? '-' : $GLOBALS["{$fieldname}{$suffix}"] : $GLOBALS[$fieldname]; echo "{$field}: <select name='{$field}{$suffix}' id='{$field}{$suffix}'></select>\n"; $vars[$field] = $data[$field]; $jsf = $field == $type ? 'item' : $field; $js[] = "var select_{$jsf}{$suffix} = \$('#{$field}{$suffix}');"; $js[] = "var cur_{$jsf}{$suffix} = '{$vars[$field]}';"; } // If showing comparison options, put in blank as first entry to denote no comparison if ($compare) { $vars['data']['-']['-']['-'] = '-'; } // Populate data hash foreach ($GLOBALS['mods'] as $mname => $mdata) { foreach ($mdata as $vname => $vdata) { foreach ($path as $key) { if (!isset($vdata[$key])) { continue 2; } $vdata =& $vdata[$key]; } foreach ($vdata as $tname => $tpath) { $bn = preg_replace('/\\.[^\\.]+$/', '', basename($tname)); if ($type == 'map') { if (!GetDataFile("maps/parsed/{$bn}.json")) { continue; } } $vars['data'][$mname][$vname][$bn] = $bn; } } } ?> <script type="text/javascript"> jQuery(function($) { var data = <?php echo prettyPrint(json_encode($vars['data'])); ?> ; <?php echo implode("\n\t", $js) . "\n"; ?> $(select_mod).change(function () { var mod = $(this).val(), vers = data[mod] || []; var html = $.map(Object.keys(vers).sort().reverse(), function(ver){ return '<option value="' + ver + '">' + ver + '</option>' }).join(''); select_version.html(html); select_version.change(); }); $(select_version).change(function () { var version = $(this).val(), mod = $(select_mod).val(), values = data[mod][version] || []; var html = $.map(Object.keys(values), function(item){ return '<option value="' + item + '">' + item + '</option>' }).join(''); select_item.html(html); select_item.change(); }); var html = $.map(Object.keys(data), function(mod){ return '<option value="' + mod + '">' + mod + '</option>' }).join(''); select_mod.html(html); select_mod.val(cur_mod); select_mod.change(); select_version.val(cur_version); select_version.change(); select_item.val(cur_item); select_item.change(); }); </script> <?php }
function ParseMap($mapname, $force = 0) { global $datapath, $linebreak, $gametypelist, $mapdata_version; $entities_key = 'entities'; $points_key = 'points'; $controlpoints = array(); $map_objects = array(); $map = array(); $reader = new KVReader(); $dstfile = GetDataFile("maps/parsed/{$mapname}.json", null, null, -2); if (file_exists($dstfile)) { $dstdata = json_decode(file_get_contents($dstfile), true); } $srcfiles = array("CPSetup" => GetDataFile("maps/{$mapname}.txt"), "Overview" => GetDataFile("resource/overviews/{$mapname}.txt"), "VMF Source" => GetDataFile("maps/src/{$mapname}_d.vmf")); foreach ($srcfiles as $name => $file) { if (!file_exists($file)) { echo "FAIL: Missing {$name} \"{$file}\"!{$linebreak}"; return; } // Get MD5 of source file $map['source_files'][$name] = md5_file($file); } $map['mapdata_version'] = $mapdata_version; // TODO: Proper KeyValues parser!!! // Load cpsetup.txt //echo "loading cpsetup\n"; $data = $reader->read(strtolower(file_get_contents($srcfiles["CPSetup"]))); //echo "done loading cpsetup\n"; // Merge in bases foreach ($data as $name => $item) { if ($name == "#base") { //echo "found bases\n"; if (!is_array($item)) { $item = array($item); } foreach ($item as $base) { //echo "merging {$base}\n"; $data = array_merge_recursive($reader->read(strtolower(file_get_contents(GetDataFile("maps/{$base}")))), $data); } unset($data[$name]); } } //var_dump($data); // Process all nodes foreach ($data as $name => $item) { if (is_array($item)) { foreach ($item as $key => $val) { if (in_array($key, array_keys($gametypelist))) { $map['gametypes'][$key] = $val; } else { $map['CPSetup'][$key] = $val; } } } } //var_dump($map); // Load Overview //echo "starting load overview\n"; //Get overview information (file, position, scale) $lines = file($srcfiles["Overview"], FILE_IGNORE_NEW_LINES); foreach ($lines as $line) { $data = explode("\t", preg_replace('/\\s+/', "\t", str_replace('"', '', trim($line)))); if (isset($data[1])) { $map['overview'][$data[0]] = is_numeric($data[1]) ? (double) $data[1] : $data[1]; } } //echo "done load overview\n"; // Load VMF Source //Parse the decompiled VMF file if (file_exists($srcfiles["VMF Source"])) { //echo "start load vmf source\n"; // Remove non-printable characters to make processing easier // Change to lowercase to make array indexing simpler $data = preg_replace('/[\\x00-\\x08\\x14-\\x1f]+/', '', strtolower(file_get_contents($srcfiles["VMF Source"]))); // Quote all unquoted keys $data = preg_replace('/(\\s*)([a-zA-Z0-9]+)(\\s*{)/', '${1}"${2}"${3}', $data); // Get all nested objects preg_match_all('~[^{}]+ { ( (?>[^{}]+) | (?R) )* } ~x', $data, $matches); // Process entities //echo "start process entities\n"; //var_dump($matches[0]); foreach ($matches[0] as $rawent) { // Read in KV $object = $reader->read($rawent); $type = implode('', array_keys($object)); if ($type == "entity") { $entity = $object[$type]; } else { continue; } //Only interested in certain entities $classnames = array("trigger_capture_zone", "point_controlpoint", "obj_weapon_cache", "ins_spawnzone", "ins_blockzone"); if (in_array($entity['classname'], $classnames) !== false) { //echo "start processing {$entity['classname']} {$entity['id']}\n"; //Special processing for capture zone /* if ($entity['classname'] == "trigger_capture_zone") { // continue; $entity['targetname'] = $entity['controlpoint']; $entity['classname'] = 'point_controlpoint'; } */ // Create data structure for point $point = CreatePoint($entity, $map); $entname = $point['pos_name']; //if (!isset($point['pos_name'])) { //var_dump($point); //} //(isset($entity['controlpoint'])) ? $entity['controlpoint'] : $entity['targetname']; if (isset($entity['solid'])) { if (isset($entity['solid']['is_multiple_array'])) { $entity['solid'] = $entity['solid'][0]; //Temp hack for complex zones } $point['pos_type'] = 'area'; //This is silly, but I add together all the coordinates and average them to get the actual location on the map. // I think a better way is to actually calculate the difference and average that way. // TODO: Send all coord numbers into array, then sort and get min/max to average that way $path = array(); foreach ($entity['solid']['side'] as $side) { if (isset($side['plane'])) { preg_match_all('#\\(([^)]+)\\)#', $side['plane'], $coord); //Add coordinate to collection foreach ($coord[1] as $xyz) { $xyz = explode(' ', $xyz); $vector = round(abs(($xyz[0] - $map['overview']['pos_x']) / $map['overview']['scale'])) . ',' . round(abs(($xyz[1] - $map['overview']['pos_y']) / $map['overview']['scale'])); //.','.round($xyz[2]/$map['overview']['scale']); $path[$vector] = $vector; } } } //This is terrible logic that loops through the path points and calculates the high/low points for shape if (count($path)) { $min = array(0 => -1, 1 => -1); $max = array(0 => -1, 1 => -1); foreach ($path as $coord) { $vector = explode(',', $coord); $min[0] = $vector[0] < $min[0] || !isset($min[0]) || $min[0] < 0 ? $vector[0] : $min[0]; $min[1] = $vector[1] < $min[1] || !isset($min[1]) || $min[1] < 0 ? $vector[1] : $min[1]; $max[0] = $vector[0] > $max[0] || !isset($max[0]) ? $vector[0] : $max[0]; $max[1] = $vector[1] > $max[1] || !isset($max[1]) ? $vector[1] : $max[1]; } // Count the sides to see if this is a square or not. if (count($path) == 4) { $point['pos_x'] = (int) $min[0]; $point['pos_y'] = (int) $min[1]; $point['pos_width'] = (int) ($max[0] - $min[0]); $point['pos_height'] = (int) ($max[1] - $min[1]); $point['pos_shape'] = 'rect'; } else { $point['pos_shape'] = 'poly'; if ($point['pos_x'] < 1) { unset($path["{$min[0]},{$min[1]}"]); $point['pos_x'] = (int) $min[0]; $point['pos_y'] = (int) $min[1]; } $point['pos_points'] = implode(' ', $path); } } //echo "done processing {$entity['classname']} {$entity['id']}\n"; } //Hackly logic to allow merging of cache/control point data gracefully no matter what order the entities come in foreach ($point as $key => $val) { if (!isset($map[$points_key][$entname][$key])) { $map[$points_key][$entname][$key] = $val; } } } //echo "done process entities\n"; } //echo "done parse vmf\n"; } // Process combined data //Process game type data for this map foreach ($map['gametypes'] as $gtname => $gtdata) { //echo "start process gametypes\n"; //Create an array called cps with the names of all the control points for this mode if (!isset($gtdata['controlpoint'])) { continue; } if (!is_array($gtdata['controlpoint'])) { $map['gametypes'][$gtname]['controlpoint'] = array($gtdata['controlpoint']); } $cps = $map['gametypes'][$gtname]['controlpoint']; //Process any entities in the gamedata text file. $entlist = array(); if (!isset($gtdata[$entities_key])) { continue; } foreach ($gtdata[$entities_key] as $entname => $entity) { //var_dump($entname,$entity); //KV reader now handles multiple like-named resources by creating a numerically indexed array //When doing that, the is_multiple_array flag is set if (isset($entity['is_multiple_array'])) { //If multiple items, send each to the array foreach ($entity as $subent) { if (is_array($subent)) { $subent['classname'] = $entname; $entlist[] = CreatePoint($subent, $map); } } } else { //Otherwise, pack the single item $entity['classname'] = $entname; $entlist[] = CreatePoint($entity, $map); } } //Process all gamedata entities that are referenced by the controlpoints list foreach ($entlist as $id => $entity) { if (!isset($entity['pos_name'])) { continue; } $cp = $entity['pos_name']; //(isset($entity['controlpoint'])) ? $entity['controlpoint'] : $entity['targetname']; foreach ($entity as $key => $val) { if (!isset($map['gametypes'][$gtname][$points_key][$cp][$key]) || @$entity['targetname'] == $cp && $key != 'classname' || @$entity['targetname'] != $cp && $key == 'classname') { $map['gametypes'][$gtname][$points_key][$cp][$key] = $val; } } } /* //chr 65 is uppercase A. This lets me 'increment' letters $chr = 65; // Loop through control points and name them foreach ($cps as $idx => $cp) { $cpname = chr($chr); unset($map['gametypes'][$gtname]['controlpoint'][$idx]); $map['gametypes'][$gtname]['controlpoint'][$cpname] = (isset($map['gametypes'][$gtname][$points_key][$cp])) ? $map['gametypes'][$gtname][$points_key][$cp] : $map[$points_key][$cp]; //Set point name to the letter of the objective //$map['gametypes'][$gtname][$points_key][$cp] $map['gametypes'][$gtname]['controlpoint'][$cpname]['pos_name'] = $cpname; if (isset($gtdata['attackingteam'])) { $map['gametypes'][$gtname]['controlpoint'][$cpname]['pos_team'] = ($gtdata['attackingteam'] == 'security') ? 3 : 2; } $chr++; } */ //Bullshit to add teams to points, Skirmish game logic does it instead of saving it in the maps. if ($gtname == 'skirmish') { $map['gametypes'][$gtname]['controlpoint']['B']['pos_team'] = 2; $map['gametypes'][$gtname]['controlpoint']['D']['pos_team'] = 3; } //Same deal for Firefight if ($gtname == 'firefight') { $map['gametypes'][$gtname]['controlpoint']['A']['pos_team'] = 2; $map['gametypes'][$gtname]['controlpoint']['C']['pos_team'] = 3; } /* //Parse spawn zones. This is tricky because there will usually be two zones with the same targetname // but different teamnum. This is to allow spawning to move as the game changes I believe. if (isset($gtdata['spawnzones'])) { foreach ($gtdata['spawnzones'] as $szid => $szname) { if (is_numeric($szid)) { unset($map['gametypes'][$gtname]['spawnzones'][$szid]); $sz = array(); foreach (array('_team2','_team3') as $suffix) { if (isset($map[$points_key]["{$szname}{$suffix}"])) $sz["{$szname}{$suffix}"] = $map[$points_key]["{$szname}{$suffix}"]; } $map['gametypes'][$gtname]['spawnzones'][$szname] = $sz; } } } // Remove the points and entities sections from the finished data structure. We no longer need them. if (@is_array($map['gametypes'][$gtname][$points_key])) { unset($map['gametypes'][$gtname][$points_key]); } if (@is_array($map['gametypes'][$gtname][$entities_key])) { unset($map['gametypes'][$gtname][$entities_key]); } */ //echo "done parse gametypes\n"; } recur_ksort($map); $json = prettyPrint(json_encode($map)); file_put_contents($dstfile, $json); echo "OK: Parsed {$mapname}{$linebreak}"; // var_dump(array_merge_recursive($srcfiles,$map['source_files'])); }
function GetMaterial($name, $type = 'img', $path = '') { // This is shit path munging, fix it $pathparts = array_filter(array_merge(explode("/", preg_replace('/\\.(vmt|vtf|png)$/', '', "{$path}/{$name}")))); if ($pathparts[0] != 'materials') { array_unshift($pathparts, 'materials'); } $filepath = implode("/", $pathparts); // If we have a PNG, just send it if (file_exists(GetDataFile("{$filepath}.png"))) { return GetDataURL("{$filepath}.png"); } // Try to use VMT to get image if (file_exists(GetDataFile("{$filepath}.vmt"))) { $vmt = file_get_contents(GetDataFile("{$filepath}.vmt")); preg_match_all('/basetexture[" ]+([^"\\s]*)/', $vmt, $matches); return GetMaterial($matches[1][0], $type); /* if (file_exists(GetDataFile("{$matches[1][0]}.png"))) { return GetDataURL("{$$matches[1][0]}.png"); } */ } // No hope return ''; }
foreach ($mapfiles as $mapfile) { $mapname = basename($mapfile, ".txt"); if (in_array($mapname, $excludemaps)) { continue; } $mapdir = dirname($mapfile); $mapver = basename(dirname($mapdir)); $mapmod = basename(dirname(dirname($mapdir))); $mapdata = parseKeyValues(strtolower(file_get_contents($mapfile))); foreach ($mapdata as $name => $item) { if ($name == "#base") { if (!is_array($item)) { $item = array($item); } foreach ($item as $base) { $mapdata = array_merge_recursive(parseKeyValues(strtolower(file_get_contents(GetDataFile("maps/{$base}", $mapmod, $mapver)))), $mapdata); } unset($mapdata[$name]); } } $maplist[$mapname] = 1; $maps[$mapname]['dir'] = $mapdir; $maps[$mapname]['mod'] = $mapmod; $maps[$mapname]['version'] = $mapver; $maps[$mapname]['cpsetup'] = array_shift(array_values($mapdata)); } $gametypes = isset($_REQUEST["gametypes"]) ? $_REQUEST["gametypes"] : array('checkpoint', 'hunt'); $mc .= ""; foreach ($maps as $mapname => $mapdata) { if (in_array($mapname, $excludemaps)) { unset($maplist[$mapname]);