/** * vim: set ts=4 : * ============================================================================= * Map Workshop Functions * A few stocks for dealing with workshop map paths and such * * Map Workshop Functions (C)2014 Powerlord (Ross Bemrose). All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . * * As a special exception, AlliedModders LLC gives you permission to link the * code of this program (as well as its derivative works) to "Half-Life 2," the * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software * by the Valve Corporation. You must obey the GNU General Public License in * all respects for all other code used. Additionally, AlliedModders LLC grants * this exception to all derivative works. AlliedModders LLC defines further * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * or . * * Version: 1.1.1 */ #if defined _map_workshop_functions_included_ #endinput #endif #define _map_workshop_functions_included_ /** * Copy a substring from source to destination * * @param source String to copy from * @param start position to start at, 0 numbered. Negative means to start that many characters from the end. * @param len number of characters to copy. Negative means to not copy that many characters from the end. * @param destination String to copy to * @param maxlen Length of destination string. Must be 1 or greater. * * @return True on success, false if number of characters copied would be negative. * NOTE: There is no mechanism to get the remaining characters of a string. * Instead, use strcopy with source[start] for that. */ stock bool:SubString(const String:source[], start, len, String:destination[], maxlen) { if (maxlen < 1) { ThrowError("Destination size must be 1 or greater, but was %d", maxlen); } // optimization if (len == 0) { destination[0] = '\0'; return true; } if (start < 0) { // strlen doesn't count the null terminator, so don't -1 on it. start = strlen(source) + start; if (start < 0) start = 0; } if (len < 0) { len = strlen(source) + len - start; // If length is still less than 0, that'd be an error. if (len < 0) return false; } // Check to make sure destination is large enough to hold the len, or truncate it. // len + 1 because second arg to strcopy counts 1 for the null terminator new realLength = len + 1 < maxlen ? len + 1 : maxlen; strcopy(destination, realLength, source[start]); return true; } /** * Remove the path from the map name * This was intended to remove workshop paths. * Used internally by MapEqual and FindMapStringInArray. * * @param map Map name * @param destination String to copy map name to * @param maxlen Length of destination string * * @return True if path was removed, false if map and destination are the same */ stock bool:RemoveMapPath(const String:map[], String:destination[], maxlen) { if (strlen(map) < 1) { ThrowError("Bad map name: %s", map); } // UNIX paths new pos = FindCharInString(map, '/', true); if (pos == -1) { // Windows paths pos = FindCharInString(map, '\\', true); if (pos == -1) { //destination[0] = '\0'; strcopy(destination, maxlen, map); return false; } } // strlen is last + 1 new len = strlen(map) - 1 - pos; // pos + 1 is because pos is the last / or \ location and we want to start one char further SubString(map, pos + 1, len, destination, maxlen); return true; } /** * Check if two maps are the same map. * Takes workshop paths into account. * * @param map First map * @param map2 Second map * * @return true if they're the same map, false if not. */ stock bool:MapEqual(const String:map[], const String:map2[]) { new bPathless; new bPathless2; new String:pathlessMap[PLATFORM_MAX_PATH]; new String:pathlessMap2[PLATFORM_MAX_PATH]; bPathless = RemoveMapPath(map, pathlessMap, sizeof(pathlessMap)); bPathless2 = RemoveMapPath(map2, pathlessMap2, sizeof(pathlessMap2)); if (StrEqual(map, map2) || (bPathless && !bPathless2 && StrEqual(pathlessMap, map2)) || (!bPathless && bPathless2 && StrEqual(map, pathlessMap2)) || (bPathless && bPathless2 && StrEqual(pathlessMap, pathlessMap2))) { return true; } return false; } /** * Returns the index for the first occurence of the provided map. If the map cannot be located, -1 will be returned. * Takes workshop maps into account. * * @param array Array Handle. * @param map Map to search for * * @return Array index, or -1 on failure */ stock FindMapStringInMapArray(Handle:array, const String:map[]) { new arrayLen = GetArraySize(array); for (new i = 0; i < arrayLen; i++) { new String:arrayMap[PLATFORM_MAX_PATH]; GetArrayString(array, i, arrayMap, sizeof(arrayMap)); if (MapEqual(arrayMap, map)) { return i; } } return -1; }