void iV_saveImage_JPEG(const char *fileName, const iV_Image *image) { unsigned char *buffer = NULL; unsigned char *jpeg = NULL; char newfilename[PATH_MAX]; unsigned int currentRow; const unsigned int row_stride = image->width * 3; // 3 bytes per pixel PHYSFS_file* fileHandle; unsigned char *jpeg_end; sstrcpy(newfilename, fileName); memcpy(newfilename + strlen(newfilename) - 4, ".jpg", 4); fileHandle = PHYSFS_openWrite(newfilename); if (fileHandle == NULL) { debug(LOG_ERROR, "pie_JPEGSaveFile: PHYSFS_openWrite failed (while opening file %s) with error: %s\n", fileName, PHYSFS_getLastError()); return; } buffer = (unsigned char *)malloc(sizeof(const char*) * image->height * image->width); // Suspect it should be sizeof(unsigned char)*3 == 3 here, not sizeof(const char *) == 8. if (buffer == NULL) { debug(LOG_ERROR, "pie_JPEGSaveFile: Couldn't allocate memory\n"); return; } // Create an array of scanlines for (currentRow = 0; currentRow < image->height; ++currentRow) { // We're filling the scanline from the bottom up here, // otherwise we'd have a vertically mirrored image. memcpy(buffer + row_stride * currentRow, &image->bmp[row_stride * (image->height - currentRow - 1)], row_stride); } jpeg = (unsigned char *)malloc(sizeof(const char*) * image->height * image->width); // Suspect it should be something else here, but sizeof(const char *) == 8 is hopefully big enough... if (jpeg == NULL) { debug(LOG_ERROR, "pie_JPEGSaveFile: Couldn't allocate memory\n"); free(buffer); return; } jpeg_end = jpeg_encode_image(buffer, jpeg, 1, JPEG_FORMAT_RGB, image->width, image->height); PHYSFS_write(fileHandle, jpeg, jpeg_end - jpeg, 1); free(buffer); free(jpeg); PHYSFS_close(fileHandle); }
const char *objInfo(const BASE_OBJECT *psObj) { static char info[PATH_MAX]; switch (psObj->type) { case OBJ_DROID: { const DROID *psDroid = (const DROID *)psObj; return droidGetName(psDroid); } case OBJ_STRUCTURE: { const STRUCTURE *psStruct = (const STRUCTURE *)psObj; return getName(psStruct->pStructureType->pName); } case OBJ_FEATURE: { const FEATURE *psFeat = (const FEATURE *)psObj; return getName(psFeat->psStats->pName); } case OBJ_PROJECTILE: sstrcpy(info, "Projectile"); // TODO break; case OBJ_TARGET: sstrcpy(info, "Target"); // TODO break; default: sstrcpy(info, "Unknown object type"); break; } return info; }
const char* version_getVcsDate() { #if (VCS_NUM == 0) return ""; #else static char vcs_date[sizeof(vcs_date_cstr) - 9] = { '\0' }; if (vcs_date[0] == '\0') { sstrcpy(vcs_date, vcs_date_cstr); } return vcs_date; #endif }
void pie_LoadBackDrop(SCREENTYPE screenType) { char backd[128]; //randomly load in a backdrop piccy. srand( (unsigned)time(NULL) + 17 ); // Use offset since time alone doesn't work very well switch (screenType) { case SCREEN_RANDOMBDROP: snprintf(backd, sizeof(backd), "texpages/bdrops/backdrop%i.png", rand() % NUM_BACKDROPS); // Range: 0 to (NUM_BACKDROPS-1) break; case SCREEN_MISSIONEND: sstrcpy(backd, "texpages/bdrops/missionend.png"); break; case SCREEN_CREDITS: default: sstrcpy(backd, "texpages/bdrops/credits.png"); break; } screen_SetBackDropFromFile(backd); }
const char* version_getSvnDate() { #if (SVN_REV == 0) return ""; #else static char svn_date[sizeof(svn_date_cstr) - 9] = { '\0' }; if (svn_date[0] == '\0') { sstrcpy(svn_date, svn_date_cstr); } return svn_date; #endif }
/** * Safe strcat */ static void sstrcat(char *dest,const char*source,size_t size) { size_t length = strlen(dest); if (length < size) { sstrcpy(dest+length,source,size - length); } else { LWIP_DEBUGF(GPRS_DEBUG,("gprs: sstrcat() String overflow short size=%u length=%u",size,length)); LWIP_ASSERT("gprs: sstrcat()",length < size); } }
// //////////////////////////////////////////////////////////////////////////// // Host Campaign. bool hostCampaign(char *sGame, char *sPlayer) { PLAYERSTATS playerStats; UDWORD i; debug(LOG_WZ, "Hosting campaign: '%s', player: '%s'", sGame, sPlayer); freeMessages(); // If we had a single player (i.e. campaign) game before this value will // have been set to 0. So revert back to the default value. if (game.maxPlayers == 0) { game.maxPlayers = 4; } if (!NEThostGame(sGame, sPlayer, game.type, 0, 0, 0, game.maxPlayers)) { return false; } for (i = 0; i < MAX_PLAYERS; i++) { if (NetPlay.bComms) { game.skDiff[i] = 0; // disable AI } setPlayerName(i, ""); //Clear custom names (use default ones instead) } NetPlay.players[selectedPlayer].ready = false; ingame.localJoiningInProgress = true; ingame.JoiningInProgress[selectedPlayer] = true; bMultiPlayer = true; bMultiMessages = true; // enable messages loadMultiStats(sPlayer, &playerStats); // stats stuff setMultiStats(selectedPlayer, playerStats, false); setMultiStats(selectedPlayer, playerStats, true); if (!NetPlay.bComms) { sstrcpy(NetPlay.players[0].name, sPlayer); } return true; }
void initI18n(void) { const char *textdomainDirectory = NULL; if (!setLanguage("")) // set to system default { // no system default? debug(LOG_ERROR, "initI18n: No system language found"); } #if defined(WZ_OS_WIN) { // Retrieve an absolute path to the locale directory char localeDir[PATH_MAX]; sstrcpy(localeDir, PHYSFS_getBaseDir()); sstrcat(localeDir, "\\" LOCALEDIR); // Set locale directory and translation domain name textdomainDirectory = bindtextdomain(PACKAGE, localeDir); } #else #ifdef WZ_OS_MAC { char resourcePath[PATH_MAX]; CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); if( CFURLGetFileSystemRepresentation( resourceURL, true, (UInt8 *) resourcePath, PATH_MAX) ) { sstrcat(resourcePath, "/locale"); textdomainDirectory = bindtextdomain(PACKAGE, resourcePath); } else { debug( LOG_ERROR, "Could not change to resources directory." ); } debug(LOG_INFO, "resourcePath is %s", resourcePath); } #else textdomainDirectory = bindtextdomain(PACKAGE, LOCALEDIR); #endif #endif if (!textdomainDirectory) { debug(LOG_ERROR, "initI18n: bindtextdomain failed!"); } (void)bind_textdomain_codeset(PACKAGE, "UTF-8"); (void)textdomain(PACKAGE); }
W_LABEL::W_LABEL(W_LABINIT const *init) : WIDGET(init, WIDG_LABEL) , FontID(init->FontID) , pTip(init->pTip) { if (display == NULL) { display = labelDisplay; } aText[0] = '\0'; if (init->pText) { sstrcpy(aText, init->pText); } }
// Generate a new texture page both in the texture page table, and on the graphics card static int newPage(const char *name, int level, int width, int height, int count) { int texPage = firstPage + ((count + 1) / TILES_IN_PAGE); // debug(LOG_TEXTURE, "newPage: texPage=%d firstPage=%d %s %d (%d,%d) (count %d + 1) / %d _TEX_INDEX=%u", // texPage, firstPage, name, level, width, height, count, TILES_IN_PAGE, _TEX_INDEX); if (texPage == _TEX_INDEX) { // We need to create a new texture page; create it and increase texture table to store it glGenTextures(1, &_TEX_PAGE[texPage].id); _TEX_INDEX++; } terrainPage = texPage; ASSERT(_TEX_INDEX > texPage, "newPage: Index too low (%d > %d)", _TEX_INDEX, texPage); ASSERT(_TEX_INDEX < iV_TEX_MAX, "Too many texture pages used"); sstrcpy(_TEX_PAGE[texPage].name, name); pie_SetTexturePage(texPage); // Specify first and last mipmap level to be used glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmap_levels - 1); // debug(LOG_TEXTURE, "newPage: glTexImage2D(page=%d, level=%d) opengl id=%u", texPage, level, _TEX_PAGE[texPage].id); glTexImage2D(GL_TEXTURE_2D, level, wz_texture_compression, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Use anisotropic filtering, if available, but only max 4.0 to reduce processor burden if (GLEW_EXT_texture_filter_anisotropic) { GLfloat max; glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, MIN(4.0f, max)); } return texPage; }
/** * Send the command to initialize the gprs of the modem. */ static void do_modem_init(gprs_t * gprs) { UNTIMEOUT(); gprs_set_state(gprs,GPRS_STATE_MODEM_INIT); sstrcpy(gprs->replyBuffer,"AT+CGDCONT=1,\"IP\",\"",sizeof(gprs->replyBuffer)); #if GPRS_RUNTIME_APN sstrcat(gprs->replyBuffer,gprs->apn,sizeof(gprs->replyBuffer)); #else sstrcat(gprs->replyBuffer,GPRS_APN,sizeof(gprs->replyBuffer)); #endif sstrcat(gprs->replyBuffer,"\"",sizeof(gprs->replyBuffer)); gprs_command(gprs,gprs->replyBuffer,'\r'); }
/* Allocate a RES_TYPE structure */ static RES_TYPE* resAlloc(const char *pType) { RES_TYPE *psT; #ifdef DEBUG // Check for a duplicate type for(psT = psResTypes; psT; psT = psT->psNext) { ASSERT(strcmp(psT->aType, pType) != 0, "Duplicate function for type: %s", pType); } #endif // setup the structure psT = (RES_TYPE *)malloc(sizeof(RES_TYPE)); sstrcpy(psT->aType, pType); psT->HashedType = HashString(psT->aType); // store a hased version for super speed ! psT->psRes = NULL; return psT; }
static bool recvBeacon(NETQUEUE queue) { int32_t sender, receiver,locX, locY; char msg[MAX_CONSOLE_STRING_LENGTH]; NETbeginDecode(queue, NET_BEACONMSG); NETint32_t(&sender); // the actual sender NETint32_t(&receiver); // the actual receiver (might not be the same as the one we are actually sending to, in case of AIs) NETint32_t(&locX); NETint32_t(&locY); NETstring(msg, sizeof(msg)); // Receive the actual message NETend(); debug(LOG_WZ, "Received beacon for player: %d, from: %d",receiver, sender); sstrcat(msg, NetPlay.players[sender].name); // name sstrcpy(beaconReceiveMsg[sender], msg); return addBeaconBlip(locX, locY, receiver, sender, beaconReceiveMsg[sender]); }
/*! * Register searchPath above the path with next lower priority * For information about what can be a search path, refer to PhysFS documentation */ void registerSearchPath( const char path[], unsigned int priority ) { wzSearchPath * curSearchPath = searchPathRegistry, * tmpSearchPath = NULL; tmpSearchPath = (wzSearchPath*)malloc(sizeof(*tmpSearchPath)); sstrcpy(tmpSearchPath->path, path); if (path[strlen(path)-1] != *PHYSFS_getDirSeparator()) sstrcat(tmpSearchPath->path, PHYSFS_getDirSeparator()); tmpSearchPath->priority = priority; debug( LOG_WZ, "registerSearchPath: Registering %s at priority %i", path, priority ); if ( !curSearchPath ) { searchPathRegistry = tmpSearchPath; searchPathRegistry->lowerPriority = NULL; searchPathRegistry->higherPriority = NULL; return; } while( curSearchPath->higherPriority && priority > curSearchPath->priority ) curSearchPath = curSearchPath->higherPriority; while( curSearchPath->lowerPriority && priority < curSearchPath->priority ) curSearchPath = curSearchPath->lowerPriority; if ( priority < curSearchPath->priority ) { tmpSearchPath->lowerPriority = curSearchPath->lowerPriority; tmpSearchPath->higherPriority = curSearchPath; } else { tmpSearchPath->lowerPriority = curSearchPath; tmpSearchPath->higherPriority = curSearchPath->higherPriority; } if( tmpSearchPath->lowerPriority ) tmpSearchPath->lowerPriority->higherPriority = tmpSearchPath; if( tmpSearchPath->higherPriority ) tmpSearchPath->higherPriority->lowerPriority = tmpSearchPath; }
bool OverrideRPTDirectory(char *newPath) { # if defined(WZ_CC_MINGW) wchar_t buf[MAX_PATH]; if (!MultiByteToWideChar(CP_UTF8, 0, newPath, -1, buf, MAX_PATH)) { //conversion failed-- we won't use the user's directory. LPVOID lpMsgBuf; DWORD dw = GetLastError(); TCHAR szBuffer[4196]; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); wsprintf(szBuffer, _T("Exception handler failed setting new directory with error %d: %s\n"), dw, lpMsgBuf); MessageBox((HWND)MB_ICONEXCLAMATION, szBuffer, _T("Error"), MB_OK); LocalFree(lpMsgBuf); return false; } PathRemoveFileSpecW(buf); wcscat(buf, L"\\logs\\"); // stuff it in the logs directory wcscat(buf, L"Warzone2100.RPT"); ResetRPTDirectory(buf); #elif defined(WZ_OS_UNIX) && !defined(WZ_OS_MAC) sstrcpy(WritePath, newPath); #endif return true; }
//add a sequence to the list to be played void seq_AddSeqToList(const char *pSeqName, const char *pAudioName, const char *pTextName, BOOL bLoop) { currentSeq++; ASSERT(currentSeq < MAX_SEQ_LIST, "too many sequences"); if (currentSeq >= MAX_SEQ_LIST) { return; } //OK so add it to the list aSeqList[currentSeq].pSeq = pSeqName; aSeqList[currentSeq].pAudio = pAudioName; aSeqList[currentSeq].bSeqLoop = bLoop; if (pTextName != NULL) { // Ordinary text shouldn't be justified seq_AddTextFromFile(pTextName, SEQ_TEXT_POSITION); } if (bSeqSubtitles) { char aSubtitleName[MAX_STR_LENGTH]; size_t check_len = sstrcpy(aSubtitleName, pSeqName); char* extension; ASSERT(check_len < sizeof(aSubtitleName), "given sequence name (%s) longer (%lu) than buffer (%lu)", pSeqName, (unsigned long) check_len, (unsigned long) sizeof(aSubtitleName)); // check for a subtitle file extension = strrchr(aSubtitleName, '.'); if (extension) *extension = '\0'; check_len = sstrcat(aSubtitleName, ".txt"); ASSERT(check_len < sizeof(aSubtitleName), "sequence name to long to attach an extension too"); // Subtitles should be center justified seq_AddTextFromFile(aSubtitleName, SEQ_TEXT_JUSTIFY); } }
// //////////////////////////////////////////////////////////////////////////// static void displayLoadSlot(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) { int x = xOffset + psWidget->x(); int y = yOffset + psWidget->y(); char butString[64]; drawBlueBox(x, y, psWidget->width(), psWidget->height()); //draw box if (!((W_BUTTON *)psWidget)->pText.isEmpty()) { sstrcpy(butString, ((W_BUTTON *)psWidget)->pText.toUtf8().constData()); iV_SetFont(font_regular); // font iV_SetTextColour(WZCOL_FORM_TEXT); while(iV_GetTextWidth(butString) > psWidget->width()) { butString[strlen(butString)-1]='\0'; } //draw text iV_DrawText( butString, x+4, y+17); } }
/** * Setup the exception handler responsible for target OS. * * \param programCommand Command used to launch this program. Only used for POSIX handler. */ void setupExceptionHandler(int argc, const char ** argv) { #if defined(WZ_OS_UNIX) && !defined(WZ_OS_MAC) const char *programCommand; time_t currentTime; #endif #if !defined(WZ_OS_MAC) // Initialize info required for the debug dumper dbgDumpInit(argc, argv); #endif #if defined(WZ_OS_WIN) # if defined(WZ_CC_MINGW) ExchndlSetup(); # else prevExceptionHandler = SetUnhandledExceptionFilter(windowsExceptionHandler); # endif // !defined(WZ_CC_MINGW) #elif defined(WZ_OS_UNIX) && !defined(WZ_OS_MAC) programCommand = argv[0]; // Get full path to this program. Needed for gdb to find the binary. programIsAvailable = fetchProgramPath(programPath, sizeof(programPath), programCommand); // Get full path to 'gdb' gdbIsAvailable = fetchProgramPath(gdbPath, sizeof(gdbPath), "gdb"); sysInfoValid = (uname(&sysInfo) == 0); currentTime = time(NULL); sstrcpy(executionDate, ctime(¤tTime)); snprintf(programPID, sizeof(programPID), "%i", getpid()); setFatalSignalHandler(posixExceptionHandler); #endif // WZ_OS_* }
//AI multiplayer message - received message from AI (from scripts) bool recvTextMessageAI(NETQUEUE queue) { UDWORD sender, receiver; char msg[MAX_CONSOLE_STRING_LENGTH]; char newmsg[MAX_CONSOLE_STRING_LENGTH]; NETbeginDecode(queue, NET_AITEXTMSG); NETuint32_t(&sender); //in-game player index ('normal' one) NETuint32_t(&receiver); //in-game player index NETstring(newmsg,MAX_CONSOLE_STRING_LENGTH); NETend(); if (whosResponsible(sender) != queue.index) { sender = queue.index; // Fix corrupted sender. } //sstrcpy(msg, getPlayerName(sender)); // name //sstrcat(msg, " : "); // seperator sstrcpy(msg, newmsg); triggerEventChat(sender, receiver, newmsg); //Display the message and make the script callback displayAIMessage(msg, sender, receiver); //Received a console message from a player callback //store and call later //------------------------------------------------- if(!msgStackPush(CALL_AI_MSG,sender,receiver,msg,-1,-1,NULL)) { debug(LOG_ERROR, "recvTextMessageAI() - msgStackPush - stack failed"); return false; } return true; }
VOID SetWinTitle(HWND hwnd, PATTMAN pam) { CHAR buf[LPATH + 32]; dprintf("Settaggio titolo finestra\n"); DlgLboxQueryItemText(hwnd, LB_FILE, pam->fsp.psSel[1], buf, LPATH + 32); // se Šuna dir ed Šattiva opzione Selez All files in directory legge // attr primo file selezionato e titolo = nomedir\*.* if (pam->pro.sel.extsel && pam->pro.sel.dir && pam->fsp.pszFile[0] == '\\' && pam->fsp.psSel[0]) { sstrcpy(pam->fsp.pszFile, buf); //copia in pszFile nome Iø file selez sprintf(buf, "%s%s%s & *.*", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), pam->fsp.pszFile); // se Šuna dir con opzione SelectAll non attiva o non ci sono file selez // legge attr dir corrente e titolo = nomedir\. } else if (pam->fsp.pszFile[0] == '\\' || !pam->fsp.psSel[0]) { if (!pam->fsp.psSel[0]) MyDlgLboxSelectItem(hwnd, LB_FILE, 0); pam->fsp.pszFile[0] = '.'; pam->fsp.pszFile[1] = 0; sstrcpy(buf, pam->fsp.pszPath); sstrcat(buf, pam->fsp.pszPath[3]? "\\.": "."); // se Šun file specificato con una mask di wildchar e ci sono + file // selez legge attr primo file e titolo = nomefile & mask } else if (isWildCh(pam->fsp.pszFile) && pam->fsp.psSel[0] > 1) { char tmp[256]; sstrcpy(tmp, buf); sprintf(buf, "%s%s%s & %s", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), tmp, pam->fsp.pszFile); sstrcpy(pam->fsp.pszFile, tmp); // pi— file selezionati non secondo una mask di wildchars } else if (pam->fsp.psSel[0] > 1) { sstrcpy(pam->fsp.pszFile, buf); sprintf(buf, "%s%s%s & ...", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), pam->fsp.pszFile); // un solo file selezionato } else { sstrcpy(pam->fsp.pszFile, buf); sprintf(buf, "%s%s%s", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), pam->fsp.pszFile); } // endif --- se Šautoimport e subject e comment sono vuoti WinSetWindowText(hwnd, buf); }
/*! * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs * * Priority: * maps > mods > base > base.wz */ bool rebuildSearchPath( searchPathMode mode, bool force ) { static searchPathMode current_mode = mod_clean; static std::string current_current_map; wzSearchPath * curSearchPath = searchPathRegistry; char tmpstr[PATH_MAX] = "\0"; if (mode != current_mode || (current_map != NULL? current_map : "") != current_current_map || force || (use_override_mods && strcmp(override_mod_list, getModList()))) { if (mode != mod_clean) { rebuildSearchPath( mod_clean, false ); } current_mode = mode; current_current_map = current_map != NULL? current_map : ""; // Start at the lowest priority while( curSearchPath->lowerPriority ) curSearchPath = curSearchPath->lowerPriority; switch ( mode ) { case mod_clean: debug(LOG_WZ, "Cleaning up"); clearLoadedMods(); while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path); #endif // DEBUG // Remove maps and mods removeSubdirs( curSearchPath->path, "maps", NULL ); removeSubdirs( curSearchPath->path, "mods/music", NULL ); removeSubdirs( curSearchPath->path, "mods/global", NULL ); removeSubdirs( curSearchPath->path, "mods/campaign", NULL ); removeSubdirs( curSearchPath->path, "mods/multiplay", NULL ); removeSubdirs( curSearchPath->path, "mods/autoload", NULL ); // Remove multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // Remove plain dir PHYSFS_removeFromSearchPath( curSearchPath->path ); // Remove base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // remove video search path as well sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_removeFromSearchPath( tmpstr ); curSearchPath = curSearchPath->higherPriority; } break; case mod_campaign: debug(LOG_WZ, "*** Switching to campaign mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and campaign mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true ); if (!PHYSFS_removeFromSearchPath( curSearchPath->path )) { debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path); } // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; case mod_multiplay: debug(LOG_WZ, "*** Switching to multiplay mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } // Add the selected map first, for mapmod support if (current_map != NULL) { std::string realPathAndDir = std::string(PHYSFS_getRealDir(current_map)) + current_map; PHYSFS_addToSearchPath(realPathAndDir.c_str(), PHYSFS_APPEND); } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and multiplay mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true ); PHYSFS_removeFromSearchPath( curSearchPath->path ); // Add multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; default: debug(LOG_ERROR, "Can't switch to unknown mods %i", mode); return false; } if (use_override_mods && mode != mod_clean) { if (strcmp(getModList(),override_mod_list)) { debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list); } clearOverrideMods(); current_mode = mod_override; } // User's home dir must be first so we allways see what we write PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir()); PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); #ifdef DEBUG printSearchPath(); #endif // DEBUG } else if (use_override_mods) { // override mods are already the same as current mods, so no need to do anything clearOverrideMods(); } return true; }
// load up the data for a level bool levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType) { LEVEL_DATASET *psNewLevel, *psBaseData, *psChangeLevel; SDWORD i; bool bCamChangeSaveGame; debug(LOG_WZ, "Loading level %s (%s, type %d)", name, pSaveName, (int)saveType); if (saveType == GTYPE_SAVE_START || saveType == GTYPE_SAVE_MIDMISSION) { if (!levReleaseAll()) { debug(LOG_ERROR, "Failed to unload old data"); return false; } } levelLoadType = saveType; // find the level dataset psNewLevel = levFindDataSet(name); if (psNewLevel == NULL) { debug(LOG_WZ, "Dataset %s not found - trying to load as WRF", name); return levLoadSingleWRF(name); } debug(LOG_WZ, "** Data set found is %s type %d", psNewLevel->pName, (int)psNewLevel->type); /* Keep a copy of the present level name */ sstrcpy(currentLevelName, name); bCamChangeSaveGame = false; if (pSaveName && saveType == GTYPE_SAVE_START) { if (psNewLevel->psChange != NULL) { bCamChangeSaveGame = true; debug(LOG_WZ, "** CAMCHANGE FOUND"); } } // select the change dataset if there is one psChangeLevel = NULL; if (((psNewLevel->psChange != NULL) && (psCurrLevel != NULL)) || bCamChangeSaveGame) { //store the level name debug(LOG_WZ, "Found CAMCHANGE dataset"); psChangeLevel = psNewLevel; psNewLevel = psNewLevel->psChange; } // ensure the correct dataset is loaded if (psNewLevel->type == LDS_CAMPAIGN) { debug(LOG_ERROR, "Cannot load a campaign dataset (%s)", psNewLevel->pName); return false; } else { if (psCurrLevel != NULL) { if ((psCurrLevel->psBaseData != psNewLevel->psBaseData) || (psCurrLevel->type < LDS_NONE && psNewLevel->type >= LDS_NONE) || (psCurrLevel->type >= LDS_NONE && psNewLevel->type < LDS_NONE)) { // there is a dataset loaded but it isn't the correct one debug(LOG_WZ, "Incorrect base dataset loaded (%p != %p, %d - %d)", psCurrLevel->psBaseData, psNewLevel->psBaseData, (int)psCurrLevel->type, (int)psNewLevel->type); if (!levReleaseAll()) // this sets psCurrLevel to NULL { return false; } } else { debug(LOG_WZ, "Correct base dataset already loaded."); } } // setup the correct dataset to load if necessary if (psCurrLevel == NULL) { if (psNewLevel->psBaseData != NULL) { debug(LOG_WZ, "Setting base dataset to load: %s", psNewLevel->psBaseData->pName); } psBaseData = psNewLevel->psBaseData; } else { debug(LOG_WZ, "No base dataset to load"); psBaseData = NULL; } } setCurrentMap(psNewLevel->pName, psNewLevel->players); if (!rebuildSearchPath(psNewLevel->dataDir, true)) { return false; } // reset the old mission data if necessary if (psCurrLevel != NULL) { debug(LOG_WZ, "Reseting old mission data"); if (!levReleaseMissionData()) { return false; } } // need to free the current map and droids etc for a save game if ((psBaseData == NULL) && (pSaveName != NULL)) { if (!saveGameReset()) { return false; } } // initialise if necessary if (psNewLevel->type == LDS_COMPLETE || //psNewLevel->type >= LDS_MULTI_TYPE_START || psBaseData != NULL) { debug(LOG_WZ, "Calling stageOneInitialise!"); if (!stageOneInitialise()) { return false; } } // load up a base dataset if necessary if (psBaseData != NULL) { debug(LOG_WZ, "Loading base dataset %s", psBaseData->pName); for(i=0; i<LEVEL_MAXFILES; i++) { if (psBaseData->apDataFiles[i]) { // load the data debug(LOG_WZ, "Loading [directory: %s] %s ...", PHYSFS_getRealDir(psBaseData->apDataFiles[i]), psBaseData->apDataFiles[i]); if (!resLoad(psBaseData->apDataFiles[i], i)) { return false; } } } } if (psNewLevel->type == LDS_CAMCHANGE) { if (!campaignReset()) { return false; } } if (psNewLevel->game == -1) //no .gam file to load - BETWEEN missions (for Editor games only) { ASSERT( psNewLevel->type == LDS_BETWEEN, "levLoadData: only BETWEEN missions do not need a .gam file" ); debug(LOG_WZ, "No .gam file for level: BETWEEN mission"); if (pSaveName != NULL) { if (psBaseData != NULL) { if (!stageTwoInitialise()) { return false; } } //set the mission type before the saveGame data is loaded if (saveType == GTYPE_SAVE_MIDMISSION) { debug(LOG_WZ, "Init mission stuff"); if (!startMissionSave(psNewLevel->type)) { return false; } debug(LOG_NEVER, "dataSetSaveFlag"); dataSetSaveFlag(); } debug(LOG_NEVER, "Loading savegame: %s", pSaveName); if (!loadGame(pSaveName, false, true,true)) { return false; } } if ((pSaveName == NULL) || (saveType == GTYPE_SAVE_START)) { debug(LOG_NEVER, "Start mission - no .gam"); if (!startMission((LEVEL_TYPE)psNewLevel->type, NULL)) { return false; } } } //we need to load up the save game data here for a camchange if (bCamChangeSaveGame) { if (pSaveName != NULL) { if (psBaseData != NULL) { if (!stageTwoInitialise()) { return false; } } debug(LOG_NEVER, "loading savegame: %s", pSaveName); if (!loadGame(pSaveName, false, true,true)) { return false; } if (!campaignReset()) { return false; } } } // load the new data debug(LOG_NEVER, "Loading mission dataset: %s", psNewLevel->pName); for(i=0; i < LEVEL_MAXFILES; i++) { if (psNewLevel->game == i) { // do some more initialising if necessary if (psNewLevel->type == LDS_COMPLETE || psNewLevel->type >= LDS_MULTI_TYPE_START || (psBaseData != NULL && !bCamChangeSaveGame)) { if (!stageTwoInitialise()) { return false; } } // load a savegame if there is one - but not if already done so if (pSaveName != NULL && !bCamChangeSaveGame) { //set the mission type before the saveGame data is loaded if (saveType == GTYPE_SAVE_MIDMISSION) { debug(LOG_WZ, "Init mission stuff"); if (!startMissionSave(psNewLevel->type)) { return false; } debug(LOG_NEVER, "dataSetSaveFlag"); dataSetSaveFlag(); } debug(LOG_NEVER, "Loading save game %s", pSaveName); if (!loadGame(pSaveName, false, true,true)) { return false; } } if ((pSaveName == NULL) || (saveType == GTYPE_SAVE_START)) { // load the game debug(LOG_WZ, "Loading scenario file %s", psNewLevel->apDataFiles[i]); switch (psNewLevel->type) { case LDS_COMPLETE: case LDS_CAMSTART: debug(LOG_WZ, "LDS_COMPLETE / LDS_CAMSTART"); if (!startMission(LDS_CAMSTART, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_BETWEEN: debug(LOG_WZ, "LDS_BETWEEN"); if (!startMission(LDS_BETWEEN, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_MKEEP: debug(LOG_WZ, "LDS_MKEEP"); if (!startMission(LDS_MKEEP, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_CAMCHANGE: debug(LOG_WZ, "LDS_CAMCHANGE"); if (!startMission(LDS_CAMCHANGE, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_EXPAND: debug(LOG_WZ, "LDS_EXPAND"); if (!startMission(LDS_EXPAND, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_EXPAND_LIMBO: debug(LOG_WZ, "LDS_LIMBO"); if (!startMission(LDS_EXPAND_LIMBO, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_MCLEAR: debug(LOG_WZ, "LDS_MCLEAR"); if (!startMission(LDS_MCLEAR, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_MKEEP_LIMBO: debug(LOG_WZ, "LDS_MKEEP_LIMBO"); if (!startMission(LDS_MKEEP_LIMBO, psNewLevel->apDataFiles[i])) { return false; } break; default: ASSERT( psNewLevel->type >= LDS_MULTI_TYPE_START, "levLoadData: Unexpected mission type" ); debug(LOG_WZ, "default (MULTIPLAYER)"); if (!startMission(LDS_CAMSTART, psNewLevel->apDataFiles[i])) { return false; } break; } } } else if (psNewLevel->apDataFiles[i]) { // load the data debug(LOG_WZ, "Loading %s", psNewLevel->apDataFiles[i]); if (!resLoad(psNewLevel->apDataFiles[i], i + CURRENT_DATAID)) { return false; } } } if (pSaveName != NULL) { //load MidMission Extras if (!loadMissionExtras(pSaveName, psNewLevel->type)) { return false; } } if (bMultiPlayer) { loadMultiScripts(); } if (pSaveName != NULL && saveType == GTYPE_SAVE_MIDMISSION) { //load script stuff // load the event system state here for a save game debug(LOG_SAVE, "Loading script system state"); if (!loadScriptState(pSaveName)) { return false; } } if (!stageThreeInitialise()) { return false; } dataClearSaveFlag(); //this enables us to to start cam2/cam3 without going via a save game and get the extra droids //in from the script-controlled Transporters if (!pSaveName && psNewLevel->type == LDS_CAMSTART) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_NO_REINFORCEMENTS_LEFT); } //restore the level name for comparisons on next mission load up if (psChangeLevel == NULL) { psCurrLevel = psNewLevel; } else { psCurrLevel = psChangeLevel; } { // Copy this info to be used by the crash handler for the dump file char buf[256]; ssprintf(buf, "Current Level/map is %s", psCurrLevel->pName); addDumpInfo(buf); } return true; }
/** * Second half of command line parsing. See ParseCommandLineEarly() for * the first half. Note that render mode must come before resolution flag. * \param argc number of arguments given * \param argv string array of the arguments * \return Returns true on success, false on error */ bool ParseCommandLine(int argc, const char **argv) { poptContext poptCon = poptGetContext(NULL, argc, argv, getOptionsTable(), 0); int iOption; /* loop through command line */ while ((iOption = poptGetNextOpt(poptCon)) > 0) { const char *token; CLI_OPTIONS option = (CLI_OPTIONS)iOption; switch (option) { case CLI_DEBUG: case CLI_DEBUGFILE: case CLI_FLUSHDEBUGSTDERR: case CLI_CONFIGDIR: case CLI_HELP: case CLI_VERSION: // These options are parsed in ParseCommandLineEarly() already, so ignore them break; case CLI_NOASSERT: kf_NoAssert(); break; // NOTE: The sole purpose of this is to test the crash handler. case CLI_CRASH: CauseCrash = true; NetPlay.bComms = false; sstrcpy(aLevelName, "CAM_3A"); SetGameMode(GS_NORMAL); break; case CLI_DATADIR: // retrieve the quoted path name token = poptGetOptArg(poptCon); if (token == NULL) { qFatal("Unrecognised datadir"); } sstrcpy(datadir, token); break; case CLI_FULLSCREEN: war_setFullscreen(true); break; case CLI_CONNECTTOIP: //get the ip we want to connect with, and go directly to join screen. token = poptGetOptArg(poptCon); if (token == NULL) { qFatal("No IP/hostname given"); } sstrcpy(iptoconnect, token); break; case CLI_HOSTLAUNCH: // go directly to host screen, bypass all others. hostlaunch = true; break; case CLI_GAME: // retrieve the game name token = poptGetOptArg(poptCon); if (token == NULL || (strcmp(token, "CAM_1A") && strcmp(token, "CAM_2A") && strcmp(token, "CAM_3A") && strcmp(token, "TUTORIAL3") && strcmp(token, "FASTPLAY"))) { qFatal("The game parameter requires one of the following keywords:" "CAM_1A, CAM_2A, CAM_3A, TUTORIAL3, or FASTPLAY."); } NetPlay.bComms = false; bMultiPlayer = false; bMultiMessages = false; NetPlay.players[0].allocated = true; if (!strcmp(token, "CAM_1A") || !strcmp(token, "CAM_2A") || !strcmp(token, "CAM_3A")) { game.type = CAMPAIGN; } else { game.type = SKIRMISH; // tutorial is skirmish for some reason } sstrcpy(aLevelName, token); SetGameMode(GS_NORMAL); break; case CLI_MOD_GLOB: { unsigned int i; // retrieve the file name token = poptGetOptArg(poptCon); if (token == NULL) { qFatal("Missing mod name?"); } // Find an empty place in the global_mods list for (i = 0; i < 100 && global_mods[i] != NULL; ++i) {} if (i >= 100 || global_mods[i] != NULL) { qFatal("Too many mods registered! Aborting!"); } global_mods[i] = strdup(token); break; } case CLI_MOD_CA: { unsigned int i; // retrieve the file name token = poptGetOptArg(poptCon); if (token == NULL) { qFatal("Missing mod name?"); } // Find an empty place in the campaign_mods list for (i = 0; i < 100 && campaign_mods[i] != NULL; ++i) {} if (i >= 100 || campaign_mods[i] != NULL) { qFatal("Too many mods registered! Aborting!"); } campaign_mods[i] = strdup(token); break; } case CLI_MOD_MP: { unsigned int i; // retrieve the file name token = poptGetOptArg(poptCon); if (token == NULL) { qFatal("Missing mod name?"); } for (i = 0; i < 100 && multiplay_mods[i] != NULL; ++i) {} if (i >= 100 || multiplay_mods[i] != NULL) { qFatal("Too many mods registered! Aborting!"); } multiplay_mods[i] = strdup(token); break; } case CLI_RESOLUTION: { unsigned int width, height; token = poptGetOptArg(poptCon); if (sscanf(token, "%ix%i", &width, &height) != 2) { qFatal("Invalid parameter specified (format is WIDTHxHEIGHT, e.g. 800x600)"); } if (width < 640) { debug(LOG_ERROR, "Screen width < 640 unsupported, using 640"); width = 640; } if (height < 480) { debug(LOG_ERROR, "Screen height < 480 unsupported, using 480"); height = 480; } // tell the display system of the desired resolution pie_SetVideoBufferWidth(width); pie_SetVideoBufferHeight(height); // and update the configuration war_SetWidth(width); war_SetHeight(height); break; } case CLI_SAVEGAME: // retrieve the game name token = poptGetOptArg(poptCon); if (token == NULL) { qFatal("Unrecognised savegame name"); } snprintf(saveGameName, sizeof(saveGameName), "%s/%s", SaveGamePath, token); SetGameMode(GS_SAVEGAMELOAD); break; case CLI_WINDOW: war_setFullscreen(false); break; case CLI_SHADOWS: setDrawShadows(true); break; case CLI_NOSHADOWS: setDrawShadows(false); break; case CLI_SOUND: war_setSoundEnabled(true); break; case CLI_NOSOUND: war_setSoundEnabled(false); break; case CLI_TEXTURECOMPRESSION: wz_texture_compression = GL_COMPRESSED_RGBA_ARB; break; case CLI_NOTEXTURECOMPRESSION: wz_texture_compression = GL_RGBA; break; }; } return true; }
static void getPlatformUserDir(char * const tmpstr, size_t const size) { #if defined(WZ_OS_WIN) // When WZ_PORTABLE is passed, that means we want the config directory at the same location as the program file DWORD dwRet; wchar_t tmpWStr[MAX_PATH]; #ifndef WZ_PORTABLE if ( SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, tmpWStr ) ) ) { #else if (dwRet = GetCurrentDirectoryW(MAX_PATH, tmpWStr)) { if(dwRet > MAX_PATH) { debug(LOG_FATAL, "Buffer exceeds maximum path to create directory. Exiting."); exit(1); } #endif if (WideCharToMultiByte(CP_UTF8, 0, tmpWStr, -1, tmpstr, size, NULL, NULL) == 0) { debug(LOG_FATAL, "Config directory encoding conversion error."); exit(1); } strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else #elif defined(WZ_OS_MAC) FSRef fsref; OSErr error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &fsref); if (!error) error = FSRefMakePath(&fsref, (UInt8 *) tmpstr, size); if (!error) strlcat(tmpstr, PHYSFS_getDirSeparator(), size); else #endif if (PHYSFS_getUserDir()) { strlcpy(tmpstr, PHYSFS_getUserDir(), size); // Use PhysFS supplied UserDir (As fallback on Windows / Mac, default on Linux) } // If PhysicsFS fails (might happen if environment variable HOME is unset or wrong) then use the current working directory else if (getCurrentDir(tmpstr, size)) { strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else { debug(LOG_FATAL, "Can't get UserDir?"); abort(); } } static void initialize_ConfigDir(void) { char tmpstr[PATH_MAX] = { '\0' }; if (strlen(configdir) == 0) { getPlatformUserDir(tmpstr, sizeof(tmpstr)); if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected. { debug(LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError()); exit(1); } if (!PHYSFS_mkdir(WZ_WRITEDIR)) // s.a. { debug(LOG_FATAL, "Error creating directory \"%s\": %s", WZ_WRITEDIR, PHYSFS_getLastError()); exit(1); } // Append the Warzone subdir sstrcat(tmpstr, WZ_WRITEDIR); sstrcat(tmpstr, PHYSFS_getDirSeparator()); if (!PHYSFS_setWriteDir(tmpstr)) { debug( LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError() ); exit(1); } } else { sstrcpy(tmpstr, configdir); // Make sure that we have a directory separator at the end of the string if (tmpstr[strlen(tmpstr) - 1] != PHYSFS_getDirSeparator()[0]) sstrcat(tmpstr, PHYSFS_getDirSeparator()); debug(LOG_WZ, "Using custom configuration directory: %s", tmpstr); if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected. { debug(LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError()); exit(1); } // NOTE: This is currently only used for mingw builds for now. #if defined (WZ_CC_MINGW) if (!OverrideRPTDirectory(tmpstr)) { // since it failed, we just use our default path, and not the user supplied one. debug(LOG_ERROR, "Error setting exception hanlder to use directory %s", tmpstr); } #endif } // User's home dir first so we allways see what we write PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); PHYSFS_permitSymbolicLinks(1); debug(LOG_WZ, "Write dir: %s", PHYSFS_getWriteDir()); debug(LOG_WZ, "Base dir: %s", PHYSFS_getBaseDir()); }
/*! * \brief Adds default data dirs * * Priority: * Lower loads first. Current: * -datadir > User's home dir > source tree data > AutoPackage > BaseDir > DEFAULT_DATADIR * * Only -datadir and home dir are allways examined. Others only if data still not found. * * We need ParseCommandLine, before we can add any mods... * * \sa rebuildSearchPath */ static void scanDataDirs( void ) { char tmpstr[PATH_MAX], prefix[PATH_MAX]; char* separator; #if defined(WZ_OS_MAC) // version-independent location for video files registerSearchPath("/Library/Application Support/Warzone 2100/", 1); #endif // Find out which PREFIX we are in... sstrcpy(prefix, PHYSFS_getBaseDir()); separator = strrchr(prefix, *PHYSFS_getDirSeparator()); if (separator) { *separator = '\0'; // Trim ending '/', which getBaseDir always provides separator = strrchr(prefix, *PHYSFS_getDirSeparator()); if (separator) { *separator = '\0'; // Skip the last dir from base dir } } // Commandline supplied datadir if( strlen( datadir ) != 0 ) registerSearchPath( datadir, 1 ); // User's home dir registerSearchPath( PHYSFS_getWriteDir(), 2 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Data in source tree sstrcpy(tmpstr, prefix); sstrcat(tmpstr, "/data/"); registerSearchPath( tmpstr, 3 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Relocation for AutoPackage sstrcpy(tmpstr, prefix); sstrcat(tmpstr, "/share/warzone2100/"); registerSearchPath( tmpstr, 4 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Program dir registerSearchPath( PHYSFS_getBaseDir(), 5 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Guessed fallback default datadir on Unix registerSearchPath( WZ_DATADIR, 6 ); rebuildSearchPath( mod_multiplay, true ); } } } } #ifdef WZ_OS_MAC if( !PHYSFS_exists("gamedesc.lev") ) { CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); char resourcePath[PATH_MAX]; if( CFURLGetFileSystemRepresentation( resourceURL, true, (UInt8 *) resourcePath, PATH_MAX) ) { chdir( resourcePath ); registerSearchPath( "data", 7 ); rebuildSearchPath( mod_multiplay, true ); } else { debug( LOG_ERROR, "Could not change to resources directory." ); } if( resourceURL != NULL ) { CFRelease( resourceURL ); } } #endif /** Debugging and sanity checks **/ printSearchPath(); if( PHYSFS_exists("gamedesc.lev") ) { debug( LOG_WZ, "gamedesc.lev found at %s", PHYSFS_getRealDir( "gamedesc.lev" ) ); } else { debug( LOG_FATAL, "Could not find game data. Aborting." ); exit(1); } }
int realmain(int argc, char *argv[]) { // The libcrypto startup stuff... May or may not actually be needed for anything at all. ERR_load_crypto_strings(); // This is needed for descriptive error messages. OpenSSL_add_all_algorithms(); // Don't actually use the EVP functions, so probably not needed. OPENSSL_config(nullptr); // What does this actually do? #ifdef WZ_OS_WIN RAND_screen(); // Uses a screenshot as a random seed, on systems lacking /dev/random. #endif wzMain(argc, argv); int utfargc = argc; const char** utfargv = (const char**)argv; #ifdef WZ_OS_MAC cocoaInit(); #endif debug_init(); debug_register_callback( debug_callback_stderr, NULL, NULL, NULL ); #if defined(WZ_OS_WIN) && defined(DEBUG_INSANE) debug_register_callback( debug_callback_win32debug, NULL, NULL, NULL ); #endif // WZ_OS_WIN && DEBUG_INSANE // ***** // NOTE: Try *NOT* to use debug() output routines without some other method of informing the user. All this output is sent to /dev/nul at this point on some platforms! // ***** if (!getUTF8CmdLine(&utfargc, &utfargv)) { return EXIT_FAILURE; } QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); // make Qt treat all C strings in Warzone as UTF-8 setupExceptionHandler(utfargc, utfargv, version_getFormattedVersionString()); /*** Initialize PhysicsFS ***/ initialize_PhysicsFS(utfargv[0]); /*** Initialize translations ***/ initI18n(); // find early boot info if (!ParseCommandLineEarly(utfargc, utfargv)) { return EXIT_FAILURE; } /* Initialize the write/config directory for PhysicsFS. * This needs to be done __after__ the early commandline parsing, * because the user might tell us to use an alternative configuration * directory. */ initialize_ConfigDir(); /*** Initialize directory structure ***/ make_dir(ScreenDumpPath, "screenshots", NULL); make_dir(SaveGamePath, "savegames", NULL); PHYSFS_mkdir("savegames/campaign"); PHYSFS_mkdir("savegames/skirmish"); make_dir(MultiCustomMapsPath, "maps", NULL); // MUST have this to prevent crashes when getting map PHYSFS_mkdir("music"); PHYSFS_mkdir("logs"); // a place to hold our netplay, mingw crash reports & WZ logs PHYSFS_mkdir("userdata"); // a place to store per-mod data user generated data memset(rulesettag, 0, sizeof(rulesettag)); // tag to add to userdata to find user generated stuff make_dir(MultiPlayersPath, "multiplay", NULL); make_dir(MultiPlayersPath, "multiplay", "players"); if (!customDebugfile) { // there was no custom debug file specified (--debug-file=blah) // so we use our write directory to store our logs. time_t aclock; struct tm *newtime; char buf[PATH_MAX]; time( &aclock ); // Get time in seconds newtime = localtime( &aclock ); // Convert time to struct // Note: We are using fopen(), and not physfs routines to open the file // log name is logs/(or \)WZlog-MMDD_HHMMSS.txt snprintf(buf, sizeof(buf), "%slogs%sWZlog-%02d%02d_%02d%02d%02d.txt", PHYSFS_getWriteDir(), PHYSFS_getDirSeparator(), newtime->tm_mon + 1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec ); debug_register_callback( debug_callback_file, debug_callback_file_init, debug_callback_file_exit, buf ); // FIXME: Change this to LOG_WZ on next release debug(LOG_INFO, "Using %s debug file", buf); } // NOTE: it is now safe to use debug() calls to make sure output gets captured. check_Physfs(); debug(LOG_WZ, "Warzone 2100 - %s", version_getFormattedVersionString()); debug(LOG_WZ, "Using language: %s", getLanguage()); debug(LOG_WZ, "Backend: %s", BACKEND); debug(LOG_MEMORY, "sizeof: SIMPLE_OBJECT=%ld, BASE_OBJECT=%ld, DROID=%ld, STRUCTURE=%ld, FEATURE=%ld, PROJECTILE=%ld", (long)sizeof(SIMPLE_OBJECT), (long)sizeof(BASE_OBJECT), (long)sizeof(DROID), (long)sizeof(STRUCTURE), (long)sizeof(FEATURE), (long)sizeof(PROJECTILE)); /* Put in the writedir root */ sstrcpy(KeyMapPath, "keymap.map"); // initialise all the command line states war_SetDefaultStates(); debug(LOG_MAIN, "initializing"); PhysicsEngineHandler engine; // register abstract physfs filesystem loadConfig(); // parse the command line if (!ParseCommandLine(utfargc, utfargv)) { return EXIT_FAILURE; } // Save new (commandline) settings saveConfig(); // Find out where to find the data scanDataDirs(); // Now we check the mods to see if they exist or not (specified on the command line) // They are all capped at 100 mods max(see clparse.c) // FIX ME: I know this is a bit hackish, but better than nothing for now? { char *modname; char modtocheck[256]; int i = 0; int result = 0; // check global mods for(i=0; i < 100; i++) { modname = global_mods[i]; if (modname == NULL) { break; } ssprintf(modtocheck, "mods/global/%s", modname); result = PHYSFS_exists(modtocheck); result |= PHYSFS_isDirectory(modtocheck); if (!result) { debug(LOG_ERROR, "The (global) mod (%s) you have specified doesn't exist!", modname); } else { info("(global) mod (%s) is enabled", modname); } } // check campaign mods for(i=0; i < 100; i++) { modname = campaign_mods[i]; if (modname == NULL) { break; } ssprintf(modtocheck, "mods/campaign/%s", modname); result = PHYSFS_exists(modtocheck); result |= PHYSFS_isDirectory(modtocheck); if (!result) { debug(LOG_ERROR, "The mod_ca (%s) you have specified doesn't exist!", modname); } else { info("mod_ca (%s) is enabled", modname); } } // check multiplay mods for(i=0; i < 100; i++) { modname = multiplay_mods[i]; if (modname == NULL) { break; } ssprintf(modtocheck, "mods/multiplay/%s", modname); result = PHYSFS_exists(modtocheck); result |= PHYSFS_isDirectory(modtocheck); if (!result) { debug(LOG_ERROR, "The mod_mp (%s) you have specified doesn't exist!", modname); } else { info("mod_mp (%s) is enabled", modname); } } } if (!wzMain2(war_getFSAA(), war_getFullscreen(), war_GetVsync())) { return EXIT_FAILURE; } int w = pie_GetVideoBufferWidth(); int h = pie_GetVideoBufferHeight(); char buf[256]; ssprintf(buf, "Video Mode %d x %d (%s)", w, h, war_getFullscreen() ? "fullscreen" : "window"); addDumpInfo(buf); debug(LOG_MAIN, "Final initialization"); if (!frameInitialise()) { return EXIT_FAILURE; } if (!screenInitialise()) { return EXIT_FAILURE; } if (!pie_LoadShaders()) { return EXIT_FAILURE; } war_SetWidth(pie_GetVideoBufferWidth()); war_SetHeight(pie_GetVideoBufferHeight()); pie_SetFogStatus(false); pie_ScreenFlip(CLEAR_BLACK); pal_Init(); pie_LoadBackDrop(SCREEN_RANDOMBDROP); pie_SetFogStatus(false); pie_ScreenFlip(CLEAR_BLACK); if (!systemInitialise()) { return EXIT_FAILURE; } //set all the pause states to false setAllPauseStates(false); // Copy this info to be used by the crash handler for the dump file ssprintf(buf,"Using Backend: %s", BACKEND); addDumpInfo(buf); ssprintf(buf,"Using language: %s", getLanguageName()); addDumpInfo(buf); // Do the game mode specific initialisation. switch(GetGameMode()) { case GS_TITLE_SCREEN: startTitleLoop(); break; case GS_SAVEGAMELOAD: initSaveGameLoad(); break; case GS_NORMAL: startGameLoop(); break; default: debug(LOG_ERROR, "Weirdy game status, I'm afraid!!"); break; } #if defined(WZ_CC_MSVC) && defined(DEBUG) debug_MEMSTATS(); #endif debug(LOG_MAIN, "Entering main loop"); wzMain3(); saveConfig(); systemShutdown(); #ifdef WZ_OS_WIN // clean up the memory allocated for the command line conversion for (int i=0; i<argc; i++) { const char*** const utfargvF = &utfargv; free((void *)(*utfargvF)[i]); } free(utfargv); #endif wzShutdown(); debug(LOG_MAIN, "Completed shutting down Warzone 2100"); return EXIT_SUCCESS; }
//**************************************************************************************** // Challenge menu //***************************************************************************************** bool addChallenges() { char sPath[PATH_MAX]; const char *sSearchPath = "challenges"; UDWORD slotCount; static char sSlotCaps[totalslots][totalslotspace]; static char sSlotTips[totalslots][totalslotspace]; static char sSlotFile[totalslots][totalslotspace]; char **i, **files; (void) PHYSFS_mkdir(sSearchPath); // just in case psRequestScreen = widgCreateScreen(); // init the screen widgSetTipFont(psRequestScreen, font_regular); /* add a form to place the tabbed form on */ W_FORMINIT sFormInit; sFormInit.formID = 0; //this adds the blue background, and the "box" behind the buttons -Q sFormInit.id = CHALLENGE_FORM; sFormInit.style = WFORM_PLAIN; sFormInit.x = (SWORD) CHALLENGE_X; sFormInit.y = (SWORD) CHALLENGE_Y; sFormInit.width = CHALLENGE_W; // we need the form to be long enough for all resolutions, so we take the total number of items * height // and * the gaps, add the banner, and finally, the fudge factor ;) sFormInit.height = (slotsInColumn * CHALLENGE_ENTRY_H + CHALLENGE_HGAP * slotsInColumn) + CHALLENGE_BANNER_DEPTH + 20; sFormInit.disableChildren = true; sFormInit.pDisplay = intOpenPlainForm; widgAddForm(psRequestScreen, &sFormInit); // Add Banner sFormInit.formID = CHALLENGE_FORM; sFormInit.id = CHALLENGE_BANNER; sFormInit.x = CHALLENGE_HGAP; sFormInit.y = CHALLENGE_VGAP; sFormInit.width = CHALLENGE_W - (2 * CHALLENGE_HGAP); sFormInit.height = CHALLENGE_BANNER_DEPTH; sFormInit.disableChildren = false; sFormInit.pDisplay = displayLoadBanner; sFormInit.UserData = 0; widgAddForm(psRequestScreen, &sFormInit); // Add Banner Label W_LABINIT sLabInit; sLabInit.formID = CHALLENGE_BANNER; sLabInit.id = CHALLENGE_LABEL; sLabInit.style = WLAB_ALIGNCENTRE; sLabInit.x = 0; sLabInit.y = 3; sLabInit.width = CHALLENGE_W - (2 * CHALLENGE_HGAP); //CHALLENGE_W; sLabInit.height = CHALLENGE_BANNER_DEPTH; //This looks right -Q sLabInit.pText = "Challenge"; widgAddLabel(psRequestScreen, &sLabInit); // add cancel. W_BUTINIT sButInit; sButInit.formID = CHALLENGE_BANNER; sButInit.x = 8; sButInit.y = 8; sButInit.width = iV_GetImageWidth(IntImages, IMAGE_NRUTER); sButInit.height = iV_GetImageHeight(IntImages, IMAGE_NRUTER); sButInit.UserData = PACKDWORD_TRI(0, IMAGE_NRUTER , IMAGE_NRUTER); sButInit.id = CHALLENGE_CANCEL; sButInit.pTip = _("Close"); sButInit.pDisplay = intDisplayImageHilight; widgAddButton(psRequestScreen, &sButInit); // add slots sButInit = W_BUTINIT(); sButInit.formID = CHALLENGE_FORM; sButInit.width = CHALLENGE_ENTRY_W; sButInit.height = CHALLENGE_ENTRY_H; sButInit.pDisplay = displayLoadSlot; for (slotCount = 0; slotCount < totalslots; slotCount++) { sButInit.id = slotCount + CHALLENGE_ENTRY_START; if (slotCount < slotsInColumn) { sButInit.x = 22 + CHALLENGE_HGAP; sButInit.y = (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + ( slotCount * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H))); } else if (slotCount >= slotsInColumn && (slotCount < (slotsInColumn *2))) { sButInit.x = 22 + (2 * CHALLENGE_HGAP + CHALLENGE_ENTRY_W); sButInit.y = (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + ( (slotCount % slotsInColumn) * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H))); } else { sButInit.x = 22 + (3 * CHALLENGE_HGAP + (2 * CHALLENGE_ENTRY_W)); sButInit.y = (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + ( (slotCount % slotsInColumn) * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H))); } widgAddButton(psRequestScreen, &sButInit); } // fill slots. slotCount = 0; sstrcpy(sPath, sSearchPath); sstrcat(sPath, "/*.ini"); debug(LOG_SAVE, "Searching \"%s\" for challenges", sPath); // add challenges to buttons files = PHYSFS_enumerateFiles(sSearchPath); for (i = files; *i != NULL; ++i) { W_BUTTON *button; char description[totalslotspace]; char highscore[totalslotspace]; const char *name, *difficulty, *map, *givendescription; inifile *inif; // See if this filename contains the extension we're looking for if (!strstr(*i, ".ini")) { // If it doesn't, move on to the next filename continue; } /* First grab any high score associated with this challenge */ inif = inifile_load(CHALLENGE_SCORES); sstrcpy(sPath, *i); sPath[strlen(sPath) - 4] = '\0'; // remove .ini sstrcpy(highscore, "no score"); if (inif) { char key[64]; bool victory; int seconds; ssprintf(key, "%s:Player", sPath); name = inifile_get(inif, key, "NO NAME"); ssprintf(key, "%s:Victory", sPath); victory = inifile_get_as_bool(inif, key, false); ssprintf(key, "%s:Seconds", sPath); seconds = inifile_get_as_int(inif, key, -1); if (seconds > 0) { getAsciiTime(key, seconds * GAME_TICKS_PER_SEC); ssprintf(highscore, "%s by %s (%s)", key, name, victory ? "Victory" : "Survived"); } inifile_delete(inif); } ssprintf(sPath, "%s/%s", sSearchPath, *i); inif = inifile_load(sPath); inifile_set_current_section(inif, "challenge"); if (!inif) { debug(LOG_ERROR, "Could not open \"%s\"", sPath); continue; } name = inifile_get(inif, "Name", "BAD NAME"); map = inifile_get(inif, "Map", "BAD MAP"); difficulty = inifile_get(inif, "difficulty", "BAD DIFFICULTY"); givendescription = inifile_get(inif, "description", ""); ssprintf(description, "%s, %s, %s. %s", map, difficulty, highscore, givendescription); button = (W_BUTTON*)widgGetFromID(psRequestScreen, CHALLENGE_ENTRY_START + slotCount); debug(LOG_SAVE, "We found [%s]", *i); /* Set the button-text */ sstrcpy(sSlotCaps[slotCount], name); // store it! sstrcpy(sSlotTips[slotCount], description); // store it, too! sstrcpy(sSlotFile[slotCount], sPath); // store filename inifile_delete(inif); /* Add button */ button->pTip = sSlotTips[slotCount]; button->pText = sSlotCaps[slotCount]; button->pUserData = (void *)sSlotFile[slotCount]; slotCount++; // go to next button... if (slotCount == totalslots) { break; } } PHYSFS_freeList(files); challengesUp = true; return true; }
// Saves and loads the relevant part of the config files for MP games // Ensures that others' games don't change our own configuration settings bool reloadMPConfig(void) { QSettings ini(PHYSFS_getWriteDir() + QString("/") + fileName, QSettings::IniFormat); if (ini.status() != QSettings::NoError) { debug(LOG_ERROR, "Could not open configuration file \"%s\"", fileName); return false; } debug(LOG_WZ, "Reloading prefs prefs to registry"); // If we're in-game, we already have our own configuration set, so no need to reload it. if (NetPlay.isHost && !ingame.localJoiningInProgress) { if (bMultiPlayer && !NetPlay.bComms) { // one-player skirmish mode sets game name to "One Player Skirmish", so // reset the name if (ini.contains("gameName")) { sstrcpy(game.name, ini.value("gameName").toString().toUtf8().constData()); } } return true; } // If we're host and not in-game, we can safely save our settings and return. if (NetPlay.isHost && ingame.localJoiningInProgress) { if (bMultiPlayer && NetPlay.bComms) { ini.setValue("gameName", game.name); // last hosted game } else { // One-player skirmish mode sets game name to "One Player Skirmish", so // reset the name if (ini.contains("gameName")) { sstrcpy(game.name, ini.value("gameName").toString().toUtf8().constData()); } } // Set a default map to prevent hosting games without a map. sstrcpy(game.map, "Sk-Rush"); game.hash.setZero(); game.maxPlayers = 4; ini.setValue("power", game.power); // power ini.setValue("base", game.base); // size of base ini.setValue("alliance", game.alliance); // allow alliances return true; } // We're not host, so let's get rid of the host's game settings and restore our own. // game name if (ini.contains("gameName")) { sstrcpy(game.name, ini.value("gameName").toString().toUtf8().constData()); } // Set a default map to prevent hosting games without a map. sstrcpy(game.map, "Sk-Rush"); game.hash.setZero(); game.maxPlayers = 4; game.power = ini.value("power", LEV_MED).toInt(); game.base = ini.value("base", CAMP_BASE).toInt(); game.alliance = ini.value("alliance", NO_ALLIANCES).toInt(); return true; }
// //////////////////////////////////////////////////////////////////////////// // options for a game. (usually recvd in frontend) void recvOptions(NETQUEUE queue) { unsigned int i; debug(LOG_NET, "Receiving options from host"); NETbeginDecode(queue, NET_OPTIONS); // Get general information about the game NETuint8_t(&game.type); NETstring(game.map, 128); NETbin(game.hash.bytes, game.hash.Bytes); uint32_t modHashesSize; NETuint32_t(&modHashesSize); ASSERT_OR_RETURN(, modHashesSize < 1000000, "Way too many mods %u", modHashesSize); game.modHashes.resize(modHashesSize); for (auto &hash : game.modHashes) { NETbin(hash.bytes, hash.Bytes); } NETuint8_t(&game.maxPlayers); NETstring(game.name, 128); NETuint32_t(&game.power); NETuint8_t(&game.base); NETuint8_t(&game.alliance); NETbool(&game.scavengers); NETbool(&game.isMapMod); for (i = 0; i < MAX_PLAYERS; i++) { NETuint8_t(&game.skDiff[i]); } // Send the list of who is still joining for (i = 0; i < MAX_PLAYERS; i++) { NETbool(&ingame.JoiningInProgress[i]); } // Alliances for (i = 0; i < MAX_PLAYERS; i++) { unsigned int j; for (j = 0; j < MAX_PLAYERS; j++) { NETuint8_t(&alliances[i][j]); } } netPlayersUpdated = true; // Free any structure limits we may have in-place if (ingame.numStructureLimits) { ingame.numStructureLimits = 0; free(ingame.pStructureLimits); ingame.pStructureLimits = NULL; } // Get the number of structure limits to expect NETuint32_t(&ingame.numStructureLimits); debug(LOG_NET, "Host is sending us %u structure limits", ingame.numStructureLimits); // If there were any changes allocate memory for them if (ingame.numStructureLimits) { ingame.pStructureLimits = (MULTISTRUCTLIMITS *)malloc(ingame.numStructureLimits * sizeof(MULTISTRUCTLIMITS)); } for (i = 0; i < ingame.numStructureLimits; i++) { NETuint32_t(&ingame.pStructureLimits[i].id); NETuint32_t(&ingame.pStructureLimits[i].limit); } NETuint8_t(&ingame.flags); NETend(); // Do the skirmish slider settings if they are up for (i = 0; i < MAX_PLAYERS; i++) { if (widgGetFromID(psWScreen, MULTIOP_SKSLIDE + i)) { widgSetSliderPos(psWScreen, MULTIOP_SKSLIDE + i, game.skDiff[i]); } } debug(LOG_INFO, "Rebuilding map list"); // clear out the old level list. levShutDown(); levInitialise(); rebuildSearchPath(mod_multiplay, true); // MUST rebuild search path for the new maps we just got! buildMapList(); bool haveData = true; auto requestFile = [&haveData](Sha256 &hash, char const *filename) { if (std::any_of(NetPlay.wzFiles.begin(), NetPlay.wzFiles.end(), [&hash](WZFile const &file) { return file.hash == hash; })) { debug(LOG_INFO, "Already requested file, continue waiting."); haveData = false; return false; // Downloading the file already } if (!PHYSFS_exists(filename)) { debug(LOG_INFO, "Creating new file %s", filename); } else if (findHashOfFile(filename) != hash) { debug(LOG_INFO, "Overwriting old incomplete or corrupt file %s", filename); } else { return false; // Have the file already. } NetPlay.wzFiles.emplace_back(PHYSFS_openWrite(filename), hash); // Request the map/mod from the host NETbeginEncode(NETnetQueue(NET_HOST_ONLY), NET_FILE_REQUESTED); NETbin(hash.bytes, hash.Bytes); NETend(); haveData = false; return true; // Starting download now. }; LEVEL_DATASET *mapData = levFindDataSet(game.map, &game.hash); // See if we have the map or not if (mapData == nullptr) { char mapName[256]; sstrcpy(mapName, game.map); removeWildcards(mapName); if (strlen(mapName) >= 3 && mapName[strlen(mapName) - 3] == '-' && mapName[strlen(mapName) - 2] == 'T' && unsigned(mapName[strlen(mapName) - 1] - '1') < 3) { mapName[strlen(mapName) - 3] = '\0'; // Cut off "-T1", "-T2" or "-T3". } char filename[256]; ssprintf(filename, "maps/%dc-%s-%s.wz", game.maxPlayers, mapName, game.hash.toString().c_str()); // Wonder whether game.maxPlayers is initialised already? if (requestFile(game.hash, filename)) { debug(LOG_INFO, "Map was not found, requesting map %s from host, type %d", game.map, game.isMapMod); addConsoleMessage("MAP REQUESTED!", DEFAULT_JUSTIFY, SYSTEM_MESSAGE); } else { debug(LOG_FATAL, "Can't load map %s, even though we downloaded %s", game.map, filename); abort(); } } for (Sha256 &hash : game.modHashes) { char filename[256]; ssprintf(filename, "mods/downloads/%s", hash.toString().c_str()); if (requestFile(hash, filename)) { debug(LOG_INFO, "Mod was not found, requesting mod %s from host", hash.toString().c_str()); addConsoleMessage("MOD REQUESTED!", DEFAULT_JUSTIFY, SYSTEM_MESSAGE); } } if (mapData && CheckForMod(mapData->realFileName)) { char const *str = game.isMapMod ? _("Warning, this is a map-mod, it could alter normal gameplay.") : _("Warning, HOST has altered the game code, and can't be trusted!"); addConsoleMessage(str, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); game.isMapMod = true; } if (mapData) { loadMapPreview(false); } }
// //////////////////////////////////////////////////////////////////////////// bool loadConfig() { QSettings ini(PHYSFS_getWriteDir() + QString("/") + fileName, QSettings::IniFormat); if (ini.status() != QSettings::NoError) { debug(LOG_ERROR, "Could not open configuration file \"%s\"", fileName); return false; } debug(LOG_WZ, "Reading configuration from %s", ini.fileName().toUtf8().constData()); if (ini.contains("voicevol")) sound_SetUIVolume(ini.value("voicevol").toDouble() / 100.0); if (ini.contains("fxvol")) sound_SetEffectsVolume(ini.value("fxvol").toDouble() / 100.0); if (ini.contains("cdvol")) sound_SetMusicVolume(ini.value("cdvol").toDouble() / 100.0); if (ini.contains("music_enabled")) war_SetMusicEnabled(ini.value("music_enabled").toBool()); if (ini.contains("language")) setLanguage(ini.value("language").toString().toUtf8().constData()); if (ini.contains("nomousewarp")) setMouseWarp(ini.value("nomousewarp").toBool()); if (ini.contains("notexturecompression")) wz_texture_compression = GL_RGBA; showFPS = ini.value("showFPS", false).toBool(); scroll_speed_accel = ini.value("scroll", DEFAULTSCROLL).toInt(); setShakeStatus(ini.value("shake", false).toBool()); setDrawShadows(ini.value("shadows", true).toBool()); war_setSoundEnabled(ini.value("sound", true).toBool()); setInvertMouseStatus(ini.value("mouseflip", true).toBool()); setRightClickOrders(ini.value("RightClickOrders", false).toBool()); setMiddleClickRotate(ini.value("MiddleClickRotate", false).toBool()); rotateRadar = ini.value("rotateRadar", true).toBool(); war_SetPauseOnFocusLoss(ini.value("PauseOnFocusLoss", false).toBool()); NETsetMasterserverName(ini.value("masterserver_name", "lobby.wz2100.net").toString().toUtf8().constData()); iV_font(ini.value("fontname", "DejaVu Sans").toString().toUtf8().constData(), ini.value("fontface", "Book").toString().toUtf8().constData(), ini.value("fontfacebold", "Bold").toString().toUtf8().constData()); NETsetMasterserverPort(ini.value("masterserver_port", MASTERSERVERPORT).toInt()); NETsetGameserverPort(ini.value("gameserver_port", GAMESERVERPORT).toInt()); war_SetFMVmode((FMV_MODE)ini.value("FMVmode", FMV_FULLSCREEN).toInt()); war_setScanlineMode((SCANLINE_MODE)ini.value("scanlines", SCANLINES_OFF).toInt()); seq_SetSubtitles(ini.value("subtitles", true).toBool()); setDifficultyLevel((DIFFICULTY_LEVEL)ini.value("difficulty", DL_NORMAL).toInt()); war_SetSPcolor(ini.value("colour", 0).toInt()); // default is green (0) war_setMPcolour(ini.value("colourMP", -1).toInt()); // default is random (-1) sstrcpy(game.name, ini.value("gameName", _("My Game")).toString().toUtf8().constData()); sstrcpy(sPlayer, ini.value("playerName", _("Player")).toString().toUtf8().constData()); // Set a default map to prevent hosting games without a map. sstrcpy(game.map, "Sk-Rush"); game.hash.setZero(); game.maxPlayers = 4; game.power = ini.value("power", LEV_MED).toInt(); game.base = ini.value("base", CAMP_BASE).toInt(); game.alliance = ini.value("alliance", NO_ALLIANCES).toInt(); game.scavengers = ini.value("scavengers", false).toBool(); memset(&ingame.phrases, 0, sizeof(ingame.phrases)); for (int i = 1; i < 5; i++) { QString key("phrase" + QString::number(i)); if (ini.contains(key)) sstrcpy(ingame.phrases[i], ini.value(key).toString().toUtf8().constData()); } bEnemyAllyRadarColor = ini.value("radarObjectMode").toBool(); radarDrawMode = (RADAR_DRAW_MODE)ini.value("radarTerrainMode", RADAR_MODE_DEFAULT).toInt(); radarDrawMode = (RADAR_DRAW_MODE)MIN(NUM_RADAR_MODES - 1, radarDrawMode); // restrict to allowed values if (ini.contains("textureSize")) setTextureSize(ini.value("textureSize").toInt()); NetPlay.isUPNP = ini.value("UPnP", true).toBool(); if (ini.contains("FSAA")) war_setFSAA(ini.value("FSAA").toInt()); // Leave this to false, some system will fail and they can't see the system popup dialog! war_setFullscreen(ini.value("fullscreen", false).toBool()); war_SetTrapCursor(ini.value("trapCursor", false).toBool()); // this should be enabled on all systems by default war_SetVsync(ini.value("vsync", true).toBool()); // 640x480 is minimum that we will support int width = ini.value("width", 640).toInt(); int height = ini.value("height", 480).toInt(); if (width < 640 || height < 480) // sanity check { width = 640; height = 480; } pie_SetVideoBufferWidth(width); pie_SetVideoBufferHeight(height); war_SetWidth(width); war_SetHeight(height); if (ini.contains("bpp")) pie_SetVideoBufferDepth(ini.value("bpp").toInt()); return true; }