1, * 'x' => 5, // Try negative values... you will see them adjust and always return * 'y' => 5, // The correct box bounds (defined by length_x and length_y) * 'length_x' => 10, * 'length_y' => 9, // Doesn't have to be exactly square! * 'tile_content' => TRUE // True/false on whether to load tile content or not. * ); * $maps['single_tile'] = array( * 'mid' => 1, * 'x' => 5, * 'y' => 5, * 'length_x' => 10, * 'length_y' => 9, * 'tile_content' => TRUE, * ); * @endcode * * @todo * cache the maps loaded, since it can be expensive */ function mapapi_load($maps) { // This is the array in which maps are stored. // The keys are the same as those of $maps // But the content is the tiles. $mapapi_array = array(); // Loop through each map, because $maps // is an array of maps, not a single map foreach($maps as $mapapi_name => $map) { // Load the map, and insert it into $mapapi_array // with the same key as $maps $mapapi_array[$mapapi_name] = _mapapi_load($map); } // Return the array of maps return $mapapi_array; } /* * Loads a single map. * Internal usage only. Use mapapi_load instead. * This function does all limit / boundary * calculation, as well as fetching the tiles. */ function _mapapi_load($map) { // We need to get the limits of the map // to make sure that the map array passed in's // area is not more than itself's area. // This needs to be done to eleminate errors // and such. if ($mapapi_limits_query = db_query("SELECT mid, name, limit_x, limit_y FROM {mapapi_map_definition} WHERE mid = %d", $map['mid'])) { // The upper limits of the map $mapapi_limits = db_fetch_array($mapapi_limits_query); // Build the dimentions of the map, respecting the limits // of the map defnition. $limits = _mapapi_make_dimentions($map, $mapapi_limits); } // If that query failed, we need to silently return null // and not execute the rest of the function, because // it would be pointless. else { return NULL; } $check_query_args = array(); $query = "SELECT tid, coord_x, coord_y, description FROM {mapapi_tile_definition} WHERE "; // We need to respect the upper limits of the map // in both x and y. // If we don't do this, the query can go wacko $query .= "coord_y <= %d AND "; $check_query_args[] = $mapapi_limits['limit_y']; $query .= "coord_x <= %d AND "; $check_query_args[] = $mapapi_limits['limit_x']; // We need to (quite obviously) follow the upper limits // of the map requested. // We need to follow both X and Y $query .= "coord_y <= %d AND "; $check_query_args[] = $limits['y']['high']; $query .= "coord_x <= %d AND "; $check_query_args[] = $limits['x']['high']; // Ditto, but for lower limits this time $query .= "coord_y >= %d AND "; $check_query_args[] = $limits['y']['low']; $query .= "coord_x >= %d AND "; $check_query_args[] = $limit['x']['low']; // Make sure we select from the proper map (!!!) $query .= "mid = %d"; $check_query_args[] = $map['mid']; // Execute the query if ($result = db_query($query, $check_query_args)) { // Return some basic information about the map, // might be helpful in some circumstances $selection = array('map_info' => $mapapi_limits, 'dimentions' => $limits); $tiles = array(); while($row = db_fetch_array($result)){ // Eventually, this will be the tile content, but for now, it is not $row['content'] = array(); // Since the description can be an array, we serialize it $row['description'] = unserialize($row['description']); // We need the coordinates of the tile, to know where in the array to put them $coord_y = $row['coord_y']; $coord_x = $row['coord_x']; // However, the array of tiles does not need them, because it's keys are already it's coordinates. unset($row['coord_y']); unset($row['coord_x']); // Insert the row into the tiles array $tiles[$coord_x][$coord_y] = $row; } $selection['map_tiles'] = $tiles; return $selection; } // If no tiles were found or the query failed, then return an empty array. else { return array(); } } /** * Figure out dimentions of a map, around the x and y. */ function _mapapi_make_dimentions($map, $limits) { // Determine number of tiles to go to // each direction away from the center. // Up and down should be equal length // as well as left and right $x_spacer = floor($map['length_x'] / 2); $y_spacer = floor($map['length_y'] / 2); // Determine X boundaries $x_low = $map['x'] - $x_spacer; $x_high = $map['x'] + $x_spacer; // Determine Y boundaries $y_low = $map['y'] - $y_spacer; $y_high = $map['y'] + $y_spacer; // If the map's left boundary // is below 0, then something // needs to be done! // The whole map needs to move // right, so the width stays the // same. if ($x_low < 0) { // Increase $x_high by the // amount below 0 $x_low is // So as an example // if $x_low is -3 // and $x_high is 5 // then the height of the // map is 8. // So $x_low becomes 0 // and $x_high becomes 8. // We also need to compensate // for if the height of the // new $x_high is higher than // the limit of the map. $x_high = min($x_high - $x_low, $limits['limit_x']); $x_low = 0; } // Even if the boundaries are above 0 // we still need to make sure that the // upper boundaries don't exceed the // upper boundaries of the map. if ($x_high > $limits['limit_x']) { // This still needs to be above 0. // That is why the max function is used $x_low = max($x_low - ($x_high - $limits['limit_x']), 0); $x_high = $limits['limit_x']; } // If the map's left boundary // is below 0, then something // needs to be done! // The whole map needs to move // right, so the width stays the // same. if ($y_low < 0) { // Increase $y_high by the // amount below 0 $y_low is // So as an example // if $y_low is -3 // and $y_high is 5 // then the height of the // map is 8. // So $y_low becomes 0 // and $y_high becomes 8. // We also need to compensate // for if the height of the // new $y_high is higher than // the limit of the map. $y_high = min($y_high - $y_low, $limits['limit_y']); $y_low = 0; } // Even if the boundaries are above 0 // we still need to make sure that the // upper boundaries don't exceed the // upper boundaries of the map. if ($y_high > $limits['limit_y']) { // This still needs to be above 0. // That is why the may function is used $y_low = max($y_low - ($y_high - $limits['limit_y']), 0); $y_high = $limits['limit_y']; } $dimentions = array(); $dimentions['x'] = array('low' => $x_low , 'high' => $x_high); $dimentions['y'] = array('low' => $y_low , 'high' => $y_high); return $dimentions; } /* * Wrapper function * Call mapapi_save('tile', $data) * to save a tile, mapapi_save('map', $data), * etc. * Use this function to save stuff, don't * call the mapapi_*_save function individually. * However, that is where the documentation for * the format is is. * It returns an array of the status. * The elements are $status['function'] * which refers to the function name, * $status['overall'], which is either true * or false, depending on the success of the function * and $status['message'], which can give information * about different errors. * Functions can also define additional elements * to add to the array, like the success of * different elements. */ function mapapi_save($type, $data) { if(function_exists("mapapi_$type"."_save")) { return call_user_func("mapapi_$type"."_save", $data); } else { return false; } } /** * Internal usage only. Use mapapi_save('tile', $data); * This function saves tiles. $args has no practical use now, it is reserved for later addons. * * Usage * @code * $save_format = array( * 'mid' => 1, * 'tid' => 1, * 'coord_x' => '5', * 'coord_y' => '7', * 'description' => array(), * 'content' => array(), * ); * @endcode * * @param $data * @param $args * @return mixed */ function mapapi_tile_save($data, $args = array()) { // We return this at the end of the function execution. // It must be an array because we are saving tiles and then content, // and the coder may want a status marker on both of those. // There is also the overall value, to check if both succeded. // this may be easier to test for, however, the individual // ones may be easier for debugging. The overall does not // include if there is a message. // There is also the message. This is for things like // "mid is not valid" or "not all parameters were passed in." // This is also useful for deveopers. // The last one is the function, which notes what function // the error came from (if there is an error) // Default false values will be changed to true later on, // if the function succeds. $status['tile'] = FALSE; $status['content'] = FALSE; $status['message'] = ""; $status['function'] = "mapapi_tile_save"; $status['overall'] = FALSE; // Check if we have all required data // We need to check the map ID, the x // coordinate, and the y coordinate if (!isset($data['mid']) || !isset($data['coord_x']) || !isset($data['coord_y'])) { // The status is still all false, so return it. // We need to set the message to "not enough parameters," // indicating not enough data was passed in. $status['message'] = "Not enough parameters. Parameters sent in were
". $data .""; $status['message'] .= "You need to pass in the mid of the map to be saved to, "; $status['message'] .= "and the x and y coordinates of the tile to save."; return $status; } // If the x or y coordinates are less than 0, which // is not allowed, throw an error else if ($data['coord_x'] < 0 || $data['coord_y'] < 0) { // Set a very descriptive status message. // We need to alert the user on if both // or one, and we need to include which one, // of the parameters were lower than 0 if ($data['coord_x'] < 0 && $data['coord_y'] < 0) { $status['message'] = "Both the x and y coordinates passed into the function were"; $status['message'] .= "less than 0, which is not allowed."; } else if ($data['coord_x'] < 0) { $status['message'] = "The x coordinate passed into the function were"; $status['message'] .= "less than 0, which is not allowed."; } else if ($data['coord_y'] < 0) { $status['message'] = "The y coordinate passed into the function were"; $status['message'] .= "less than 0, which is not allowed."; } return $status; } // Now we must test if mid is valid. $test_mid_query = "SELECT mid FROM mapapi_map_definition WHERE mid = %d"; if ($result = db_query($test_mid_query, $data['mid'])){ if (db_num_rows($result) > 0){ // The map is valid so we don't do anything } else { $status['message'] = "The mid is invalid"; // Not valid map! We musn't save anything return $status; } } // Check if tile exists $query = "SELECT tid FROM {mapapi_tile_definition} WHERE "; $query_args = array(); $query .= "coord_x = %d "; $query_args[] = $data['coord_x']; $query .= "AND coord_y = %d "; $query_args[] = $data['coord_y']; $query .= "AND mid = %d "; $query_args[] = $data['mid']; // If it exists, we update the tile instead of // saving it. if ($result = db_query($query, $query_args)) { if (db_num_rows($result) > 0) { $status['message'] = 'Tile found. Updating it. '; $tid = db_fetch_array($result); // Maybe tid was already passed, but we dont care beacuse $tid is guaranteed to always be more correct $data['tid'] = $tid['tid']; // No need to see if data definition or data content are set! That check is done inside the tile and content functions // Update the tile _mapapi_tile_update($data, $status); // The tile content must also be saved mapapi_content_save($data, $status); } else { $status['message'] = 'Tile not found. Adding a new one. '; // If this is a new tile then tid should not be set! // In the admin UI there will be no way to set tid. $data['tid'] = db_next_id("mapapi_tile_tid"); // No need to see if data definition or data content are set! That check is done inside the tile and content functions // Insert the tile // If it succeeds, save the content as well. if(_mapapi_tile_insert($data, $status)){ mapapi_content_save($data, $status); } } } else { $status['message'] = "The query to check of the tile is updated failed!"; } return $status; } function _mapapi_tile_insert($data, &$status){ // We check if the tid and description are set. // The other items are checked by mapapi_tile_save if (!isset($data['tid']) || !isset($data['description'])) { // We don't need to alter $status, because // it is set to false by default. // However, we do need to return false, // so the if statement in mapapi_tile_save // won't go through return FALSE; } // This is the big query. $query = "INSERT INTO {mapapi_tile_definition} (mid, tid, coord_x, coord_y, description) VALUES (%d, %d, %d, %d, '%s')"; $query_args = array(); $query_args[] = $data['mid']; $query_args[] = $data['tid']; $query_args[] = $data['coord_x']; $query_args[] = $data['coord_y']; // The description is serialized, because // it can contain lots of information, // like the terrain. $query_args[] = serialize($data['description']); if (db_query($query, $query_args)) { $status['tile'] = TRUE; return TRUE; } // The status does not need to be set to false, // because it is false by default. return FALSE; } // Updates tile description only! (because to update X or Y means that we just insert a new tile and should use _mapapi_tile_insert function _mapapi_tile_update($data, &$status) { // Check if the description is set. // The other items are checked by mapapi_tile_save if (!isset($data['description'])) { // We don't need to alter $status['tile'], // because it is set to false by default. // $status['message'] does need to be // set to something more descriptive. // At this point, $status['message'] // needs to be appended to, because // it already has some information // in it. // $status['function'] needs to be // set to _mapapi_tile_update to // alert the user that the error // occered here. // We need to return false, // so the if statement in mapapi_tile_save // won't go through. $status['message'] .= "Not enough parameters. Parameters sent in were
". print_r($data, 1) .""; $status['message'] .= "You need to pass in the mid of the map to be saved to, "; $status['message'] .= "and the x and y coordinates of the tile to save."; $status['function'] = '_mapapi_tile_update'; return FALSE; } // The query itself... $update_query = "UPDATE {mapapi_tile_definition} SET description = '%s' WHERE tid = %d"; if (db_query($update_query, serialize($data['description']), $data['tid'])) { $status['tile'] = TRUE; return TRUE; } else { return FALSE; } } function mapapi_tile_delete($tid) { // The status vairable is an array, // indecating the different status // items. // It is a keyed array containing // information about the success // of the query, any debug messages, // this function name $status['query'] = FALSE; $status['message'] = ""; $status['function'] = "mapapi_tile_save"; $status['overall'] = FALSE; $del_tile_content_query = "DELETE FROM {mapapi_tile_content} WHERE tid = %d"; if(!db_query($del_tile_content_query, $tid)){ //do something because deleting tile failed! $query_status = false; } $del_tile_definition_query = "DELETE FROM {mapapi_tile_definition} WHERE tid = %d"; if(!db_query($del_tile_definition_query, $tid)){ //handle failed query $query_status = false; } return $query_status; } /** * inserts tile content * * @param $data * @param $status * * $content_format = array( * 'tid' => 1, * 'data' => array() * ); * @return bool */ function mapapi_content_save($data, &$status){ // Check if the content is set. // The other items are checked by mapapi_tile_save if(!isset($data['content'])) { return FALSE; } $content_query = "REPLACE INTO {mapapi_tile_content} (tid, mid, content) VALUES (%d, %d, '%s')"; $content_args[] = $data['tid']; $content_args[] = $data['mid']; $content_args[] = serialize($data['content']); if(db_query($content_query, $content_args)){ return true; } return false; } function mapapi_content_delete($tid){ $content_query = "DELETE FROM {mapapi_tile_content} WHERE tid = %d"; if(db_query($content_query,$tid)){ return true; } return false; } /** * Saves map data. $args has no practical use now, reserved for later addons * @example * $map_format = array( * 'mid' => 1, //optional * 'limit_x' => '6', * 'limit_y' => '7', * 'name' => 'New map name', //optional * ); * * @param array $data * @param array $args */ function mapapi_map_save($data,$args = array()){ if(!isset($data['mid']) && isset($data['name'])){ //find the mid by map name $query = "SELECT mid FROM {mapapi_map_definition} WHERE name LIKE ('%s')"; $query_arg[] = db_escape_string($data['name']); $success = false; if($result = db_query($query, $query_arg)){ $success = true; } if($success && db_num_rows($result) > 0){ $mid = db_fetch_array($result); $data['mid'] = $mid['mid']; } else { $data['mid'] = db_next_id("mapapi_map_definition"); } } else { $data['mid'] = db_next_id("mapapi_map_definition"); } return _mapapi_map_save($data,$args); } function _mapapi_map_save($data,$args = array()) { //make sure $data is of correct format if(!isset($data['mid']) || !isset($data['limit_x']) || !isset($data['limit_y']) || !isset($data['name'])){ return false; } $insert_query = "REPLACE INTO {mapapi_map_definition} (mid, limit_x, limit_y, name) VALUES (%d, %d, %d, '%s')"; $insert_query_args = array(); $insert_query_args[] = $data['mid']; $insert_query_args[] = $data['limit_x']; $insert_query_args[] = $data['limit_y']; $insert_query_args[] = db_escape_string($data['name']); if(db_query($insert_query,$insert_query_args)){ return true; //successful insert } else { return false; // unsuccessful insert } } function mapapi_map_delete($mid){ $query_status = true; //return at the end of the function, This is not very descriptive at which stage this was set to false //delete tile contents $content_query = "DELETE FROM {mapapi_tile_content} WHERE {mapapi_tile_content}.mid = %d"; if(!db_query($content_query,$mid)){ $query_status = false; } // delete tiles $tiles_query = "DELETE FROM {mapapi_tile_definition} WHERE mid = %d"; if(!db_query($tiles_query,$mid)){ $query_status = false; } //delete map $map_query = "DELETE FROM {mapapi_map_definition} WHERE mid = %d"; if(!db_query($map_query,$mid)){ $query_status = false; } return $query_status; //all data from this particular $mid was deleted }