// Load a world folder int Level::LoadWorld(const STRING & p) { if (cancel) return LVL_ERR_CANCEL; Reset(); state = DIRECTORY; STRING path = p; STRING search; { char t[] = {"*"}; search.assign(t, t+strlen(t)); } // Find files FileSearch fs = FileSearch(); fs.path = path; fs.amount = &total; fs.exclude.push_back(STR("DIM-1")); if (!ListFiles(&fs)) return LVL_ERR_LISTING; files = fs.files; if (cancel) return LVL_ERR_CANCEL; total = files.size(); work = 0; result = 0; done = 0; prefs.logging = !prefs.log.empty(); if (prefs.version == BETA) total *= 1024; state = PROCESSING; // Limit threads if (prefs.threads > files.size()) prefs.threads = files.size(); // More threads than the computer can handle is no good for you unsigned long i = 0; if (prefs.threads > (i = Computer::GetLogicalCores())) prefs.threads = i & 0xFF; // Multithreaded program if (prefs.threads >= 2) { LoadMultiple(); } else { LoadSingle(); } // Fastest way to clear a stack while (!files.empty()) files.pop(); if (cancel) return LVL_ERR_CANCEL; return LVL_OK; }
// Get save folder where minecraft store its saves STRING PixelMap::GetSaveFolder() { #ifdef WIN32 STRING appdata = Port::GetEnv("APPDATA"); #elif defined(UNIX) STRING appdata = Port::GetEnv("HOME"); #endif appdata.assign(appdata.c_str() + STR("\\.minecraft\\saves")); return appdata; }
// Load level information int Level::LoadLevel(const STRING & path) { STRING file; file.assign(path.c_str()); STRING name = Port::FileName(file); file.append(Port::ReplacePath(STR("\\level.dat"))); NBT_Reader read = NBT_Reader(); read.Load(file); bool valid = false; NBTTag tag = read.ReadData(); // Read first compound while ((tag = read.ReadData()) != TAG_Unknown) { const NBTData * data = read.GetData(); if (!data) continue; if (!valid) { if (data->tag != TAG_Compound) continue; if (!data->name) continue; if (!StringCheck(data->name, "Data")) continue; valid = true; } switch (data->tag) { case TAG_Int: if (StringCheck(data->name, "version")) { info.version = data->i; } break; case TAG_Long: if (StringCheck(data->name, "RandomSeed")) { info.seed = data->l; } break; case TAG_String: if (StringCheck(data->name, "LevelName")) { info.name.assign((char *)data->bas, (char *)data->bas+data->size); } break; } } // Alpha if (info.name.empty()) info.name = name; return valid; }
// 抛出字符串形式异常 VOID tThrowStringException(LPCTSTR szFmt, ...) { va_list argList; va_start(argList, szFmt); UINT nSize = _vsctprintf(szFmt, argList); STRING strMessage; strMessage.assign(nSize+1, _T(' ')); _vstprintf((LPTSTR)&(strMessage[0]), szFmt, argList); va_end(argList); throw std::exception(strMessage.c_str()); }
VOID tThrowAssertException(LPCTSTR szFileName, INT nFileLine, LPCTSTR pExpr) { const char *szAssertFmt = _T("Assert \r\n") _T("\r\n") _T("File: %s\r\n") _T("Line: %d\r\n") _T("Expr: %s\r\n"); UINT nSize = _sctprintf(szAssertFmt, szFileName, nFileLine, pExpr); STRING strMessage; strMessage.assign(nSize+1, _T(' ')); _stprintf((LPTSTR)&(strMessage[0]), szAssertFmt, szFileName, nFileLine, pExpr); throw std::exception(strMessage.c_str()); }
void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory ) throw( IO_ERROR ) { PN_ITER end = aCategory.size() ? partnames.lower_bound( aCategory + char( '/' + 1 ) ) : partnames.end(); PN_ITER it = aCategory.size() ? partnames.upper_bound( aCategory + "/" ) : partnames.begin(); aResults->clear(); if( useVersioning ) { STRING partName; while( it != end ) { const char* rev = endsWithRev( *it ); // all cached partnames have a rev string in useVersioning mode assert( rev ); // partName is substring which omits the rev AND the rev separator partName.assign( *it, 0, rev - it->c_str() - 1 ); aResults->push_back( partName ); // skip over all other versions of the same partName. it = partnames.lower_bound( partName + char( '/' + 1 ) ); } } else { while( it != end ) aResults->push_back( *it++ ); } }
STRING Port::GetEnv(const char * var) { STRING env; #ifdef WIN32 size_t tLen = 0; #ifdef UNICODE wchar_t path[80]; wchar_t var2[256] = {0}; int size = strlen(var)+1; mbstowcs_s(&tLen, var2, size, var, size); _wgetenv_s(&tLen, path, 80, var2); #else char path[80]; getenv_s(&tLen, path, 80, var); #endif env = path; #elif defined(UNIX) char * temp = getenv(var); env.assign(temp, temp+strlen(temp)); #endif return env; }
void DIR_LIB_SOURCE::GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) { aResults->clear(); if( useVersioning ) { STRING partName; const char* rev = endsWithRev( aPartName ); if( rev ) // partName is substring which omits the rev and the separator partName.assign( aPartName, 0, rev - aPartName.c_str() - 1 ); else partName = aPartName; PN_ITER it = partnames.upper_bound( partName +'/' ); PN_ITER end = partnames.lower_bound( partName + char( '/' +1 ) ); for( ; it != end; ++it ) { const char* rev = endsWithRev( *it ); assert( rev ); aResults->push_back( it->substr( rev - it->c_str() ) ); } } else { // In non-version mode, there were no revisions read in, only part // files without a revision. But clients higher up expect to see // at least one revision in order for the API to work, so we return // a revision "" aResults->push_back( "" ); } }
// Prepare arguments void PixelMap::PrepareArgs() { using namespace std; // Add parameters LevelPrefs prefs = LevelPrefs(); // Init block colors if (texture.empty()) DataValues::MakeColor(); else { STRING t; t.assign(texture.begin(), texture.end()); DataValues::MakeColor(t); } // Pick world version prefs.version = worldVersion; STRINGSTREAM str; // Slice if (slice.size() && slice.front() != -1) { prefs.z = (BYTE)slice.front(); str << STR("-slice") << (int)prefs.z; if (slice.size() == 2 && slice.back() != 0) { prefs.flags |= CHUNKP_SINGLESLICE; str << STR("S"); } } // Line heightmap if (height > 0) { prefs.h = (BYTE)height; str << STR("-height") << height; } // Gray heightmap else if (height == -1) { prefs.flags |= CHUNKP_GRAY; str << STR("-gray"); } // Color heightmap else if (height == -2) { prefs.flags |= CHUNKP_COLOR; str << STR("-color"); } // Solid heightmap else if (height == -3) { prefs.flags |= CHUNKP_SOLID; str << STR("-solid"); } // Night if (night) { prefs.flags |= CHUNKP_NIGHT; str << STR("-night"); } // Cavemode if (caveMode) { prefs.flags |= CHUNKP_CAVE; str << STR("-cave"); } // Nether if (nether) { // Cave is only because nether is below surface prefs.flags |= CHUNKP_CAVE; str << STR("-nether"); folder.append(STR("\\DIM-1")); } // Rotation if (rotation != 0) { prefs.rotation = rotation; str << STR("-rot") << rotation; } // No rendering if (noRender) prefs.flags |= CHUNKP_NORENDER; prefs.threads = (BYTE)threads; // Add log file prefs.log.assign(logFile.begin(), logFile.end()); prefs.log = Port::ReplacePath(prefs.log); // Add cache folder prefs.cache.assign(cache.begin(), cache.end()); // Use only these blocks if (!only.empty()) { memset(prefs.block, false, DATAVALUES_AMOUNT); for (list<int>::iterator i = only.begin(); i != only.end(); ++i) if (*i >= 0 && *i < 256) prefs.block[*i] = true; } // Exclude these blocks else if (!exclude.empty()) { for (list<int>::iterator i = exclude.begin(); i != exclude.end(); ++i) if (*i >= 0 && *i < 256) prefs.block[*i] = false; } // Special savefile if (saveFile.size() == 0) { save.assign(save.c_str()); save.append(str.str() + STR(".png")); } // Disable heightmap if (noHeightMap) prefs.flags |= CHUNKP_NOHEIGHTMAP; // Validate folders folder = Port::ReplacePath(folder); save = Port::ReplacePath(save); level->prefs = prefs; go.level = level; go.folder->assign(folder.c_str()); go.save->assign(save.c_str()); counter.Update(); // Start here }
void ParseCommandLineFlags(const char* usage, int* argc, char*** argv, const bool remove_flags) { if (*argc == 1) { tprintf("USAGE: %s\n", usage); PrintCommandLineFlags(); exit(0); } unsigned int i = 1; for (i = 1; i < *argc; ++i) { const char* current_arg = (*argv)[i]; // If argument does not start with a hyphen then break. if (current_arg[0] != '-') { break; } // Position current_arg after startings hyphens. We treat a sequence of // consecutive hyphens of any length identically. while (*current_arg == '-') { ++current_arg; } // If this is asking for usage, print the help message and abort. if (!strcmp(current_arg, "help") || !strcmp(current_arg, "helpshort")) { tprintf("USAGE: %s\n", usage); PrintCommandLineFlags(); exit(0); } // Find the starting position of the value if it was specified in this // string. const char* equals_position = strchr(current_arg, '='); const char* rhs = NULL; if (equals_position != NULL) { rhs = equals_position + 1; } // Extract the flag name. STRING lhs; if (equals_position == NULL) { lhs = current_arg; } else { lhs.assign(current_arg, equals_position - current_arg); } if (!lhs.length()) { tprintf("ERROR: Bad argument: %s\n", (*argv)[i]); exit(1); } // Find the flag name in the list of global flags. // inT32 flag inT32 int_val; if (IntFlagExists(lhs.string(), &int_val)) { if (rhs != NULL) { if (!strlen(rhs)) { // Bad input of the format --int_flag= tprintf("ERROR: Bad argument: %s\n", (*argv)[i]); exit(1); } if (!SafeAtoi(rhs, &int_val)) { tprintf("ERROR: Could not parse int from %s in flag %s\n", rhs, (*argv)[i]); exit(1); } } else { // We need to parse the next argument if (i + 1 >= *argc) { tprintf("ERROR: Could not find value argument for flag %s\n", lhs.string()); exit(1); } else { ++i; if (!SafeAtoi((*argv)[i], &int_val)) { tprintf("ERROR: Could not parse inT32 from %s\n", (*argv)[i]); exit(1); } } } SetIntFlagValue(lhs.string(), int_val); continue; } // double flag double double_val; if (DoubleFlagExists(lhs.string(), &double_val)) { if (rhs != NULL) { if (!strlen(rhs)) { // Bad input of the format --double_flag= tprintf("ERROR: Bad argument: %s\n", (*argv)[i]); exit(1); } if (!SafeAtod(rhs, &double_val)) { tprintf("ERROR: Could not parse double from %s in flag %s\n", rhs, (*argv)[i]); exit(1); } } else { // We need to parse the next argument if (i + 1 >= *argc) { tprintf("ERROR: Could not find value argument for flag %s\n", lhs.string()); exit(1); } else { ++i; if (!SafeAtod((*argv)[i], &double_val)) { tprintf("ERROR: Could not parse double from %s\n", (*argv)[i]); exit(1); } } } SetDoubleFlagValue(lhs.string(), double_val); continue; } // Bool flag. Allow input forms --flag (equivalent to --flag=true), // --flag=false, --flag=true, --flag=0 and --flag=1 bool bool_val; if (BoolFlagExists(lhs.string(), &bool_val)) { if (rhs == NULL) { // --flag form bool_val = true; } else { if (!strlen(rhs)) { // Bad input of the format --bool_flag= tprintf("ERROR: Bad argument: %s\n", (*argv)[i]); exit(1); } if (!strcmp(rhs, "false") || !strcmp(rhs, "0")) { bool_val = false; } else if (!strcmp(rhs, "true") || !strcmp(rhs, "1")) { bool_val = true; } else { tprintf("ERROR: Could not parse bool from flag %s\n", (*argv)[i]); exit(1); } } SetBoolFlagValue(lhs.string(), bool_val); continue; } // string flag const char* string_val; if (StringFlagExists(lhs.string(), &string_val)) { if (rhs != NULL) { string_val = rhs; } else { // Pick the next argument if (i + 1 >= *argc) { tprintf("ERROR: Could not find string value for flag %s\n", lhs.string()); exit(1); } else { string_val = (*argv)[++i]; } } SetStringFlagValue(lhs.string(), string_val); continue; } // Flag was not found. Exit with an error message. tprintf("ERROR: Non-existent flag %s\n", (*argv)[i]); exit(1); } // for each argv if (remove_flags) { (*argv)[i - 1] = (*argv)[0]; (*argv) += (i - 1); (*argc) -= (i - 1); } }
STRING Port::MakeString(const char * text) { STRING str; str.assign(text, text+strlen(text)); return str; }