// //////////////////////////////////////////////////////////////////////////// // 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); } }
void MOD_SelectModMenu(char *basedir){ SceCtrlData pad, oldpad; sceCtrlPeekBufferPositive(0, &pad, 1); // Ch0wW: Enable the mod menu once the R trigger is hold on startup. if (!(pad.buttons & SCE_CTRL_RTRIGGER)) { // Reading current used mod char cur_mod[64]; modname = malloc(64); FILE* f; if ((f = fopen( va("%s/%s", basedir, MOD_FILE), "r")) != NULL) { char tmp[256]; fseek(f, 0, SEEK_END); int len = ftell(f); fseek(f, 0, SEEK_SET); fread(tmp, 1, len, f); fclose(f); tmp[len] = 0; sprintf(modname, "%s", tmp); } else modname = NULL; return; } // Initializing empty ModList ModsList* mods = NULL; int i = 0; int max_idx = -1; // Scanning main folder in search of mods int dd = sceIoDopen(basedir); SceIoDirent entry; int res; while (sceIoDread(dd, &entry) > 0){ if (SCE_S_ISDIR(entry.d_stat.st_mode)){ if (CheckForMod( va("%s/%s", basedir, entry.d_name))){ mods = addMod(entry.d_name, mods); max_idx++; } } } sceIoDclose(dd); // Reading current used mod char cur_mod[64]; modname = malloc(64); FILE* f; if ((f = fopen(va("%s/%s", basedir, MOD_FILE), "r")) != NULL) { char tmp[256]; fseek(f, 0, SEEK_END); int len = ftell(f); fseek(f, 0, SEEK_SET); fread(tmp, 1, len, f); fclose(f); tmp[len] = 0; sprintf(modname, "%s", tmp); sprintf(cur_mod, "Current in use mod: %s - Press START to launch vitaQuake core", tmp); }else strcpy(cur_mod,"Current in use mod: id1 - Press START to launch vitaQuake core"); // Initializing graphics stuffs vita2d_set_clear_color(RGBA8(0x00, 0x00, 0x00, 0xFF)); vita2d_pgf* debug_font = vita2d_load_default_pgf(); uint32_t white = RGBA8(0xFF, 0xFF, 0xFF, 0xFF); uint32_t green = RGBA8(0x00, 0xFF, 0x00, 0xFF); uint32_t red = RGBA8(0xFF, 0x00, 0x00, 0xFF); // Main loop while (max_idx >= 0){ vita2d_start_drawing(); vita2d_clear_screen(); vita2d_pgf_draw_text(debug_font, 2, 20, red, 1.0, cur_mod); // Drawing menu int y = 40; int d = 0; ModsList* ptr = mods; while (ptr != NULL && y < 540){ uint32_t color = white; if (d++ == i) color = green; vita2d_pgf_draw_text(debug_font, 2, y, color, 1.0, ptr->name); ptr = ptr->next; y += 20; } // Controls checking sceCtrlPeekBufferPositive(0, &pad, 1); if ((pad.buttons & SCE_CTRL_CROSS) && (!(oldpad.buttons & SCE_CTRL_CROSS))){ int z = 0; ModsList* tmp = mods; while (z < i){ tmp = tmp->next; z++; } sprintf(cur_mod,"Current in use mod: %s - Press START to launch vitaQuake core", tmp->name); if (!strcmp(tmp->name, "id1")) { sceIoRemove( va("%s/%s", basedir, MOD_FILE) ); modname = NULL; } else{ f = fopen(va("%s/%s", basedir, MOD_FILE), "w"); fwrite(tmp->name,1,strlen(tmp->name),f); fclose(f); strcpy(modname, tmp->name); // Refresh the mod directory. } }else if ((pad.buttons & SCE_CTRL_UP) && (!(oldpad.buttons & SCE_CTRL_UP))){ i--; if (i < 0) i = max_idx; }else if ((pad.buttons & SCE_CTRL_DOWN) && (!(oldpad.buttons & SCE_CTRL_DOWN))){ i++; if (i > max_idx) i = 0; }else if (pad.buttons & SCE_CTRL_START) break; oldpad = pad; vita2d_end_drawing(); vita2d_wait_rendering_done(); vita2d_swap_buffers(); } // Freeing stuffs ModsList* tmp = mods; ModsList* tmp2; while (tmp != NULL){ tmp2 = tmp->next; free(tmp); tmp = tmp2; } return; }