X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=1c7d78b660c6ba0215c18f6623460c5e579c3ace;hb=ec334a51f6f1f6fa6df1f70f10201ca2ce1e076f;hp=74c21fe33bdad1fe05195ff196b84a3f20278f56;hpb=3b7f6c6d572ffd50744e76f9ed93733785e13211;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 74c21fe3..1c7d78b6 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -1163,6 +1163,16 @@ void pushTreeInfo(TreeInfo **node_first, TreeInfo *node_new) *node_first = node_new; } +void removeTreeInfo(TreeInfo **node_first) +{ + TreeInfo *node_old = *node_first; + + *node_first = node_old->next; + node_old->next = NULL; + + freeTreeInfo(node_old); +} + int numTreeInfo(TreeInfo *node) { int num = 0; @@ -1215,7 +1225,7 @@ int numTreeInfoInGroup(TreeInfo *node) return numTreeInfo(getTreeInfoFirstGroupEntry(node)); } -int posTreeInfo(TreeInfo *node) +int getPosFromTreeInfo(TreeInfo *node) { TreeInfo *node_cmp = getTreeInfoFirstGroupEntry(node); int pos = 0; @@ -1249,7 +1259,8 @@ TreeInfo *getTreeInfoFromPos(TreeInfo *node, int pos) return node_default; } -TreeInfo *getTreeInfoFromIdentifier(TreeInfo *node, char *identifier) +static TreeInfo *getTreeInfoFromIdentifierExt(TreeInfo *node, char *identifier, + boolean include_node_groups) { if (identifier == NULL) return NULL; @@ -1258,10 +1269,12 @@ TreeInfo *getTreeInfoFromIdentifier(TreeInfo *node, char *identifier) { if (node->node_group) { - TreeInfo *node_group; - - node_group = getTreeInfoFromIdentifier(node->node_group, identifier); + if (include_node_groups && strEqual(identifier, node->identifier)) + return node; + TreeInfo *node_group = getTreeInfoFromIdentifierExt(node->node_group, + identifier, + include_node_groups); if (node_group) return node_group; } @@ -1277,6 +1290,11 @@ TreeInfo *getTreeInfoFromIdentifier(TreeInfo *node, char *identifier) return NULL; } +TreeInfo *getTreeInfoFromIdentifier(TreeInfo *node, char *identifier) +{ + return getTreeInfoFromIdentifierExt(node, identifier, FALSE); +} + static TreeInfo *cloneTreeNode(TreeInfo **node_top, TreeInfo *node_parent, TreeInfo *node, boolean skip_sets_without_levels) { @@ -1380,16 +1398,23 @@ static boolean adjustTreeSoundsForEMC(TreeInfo *node) void dumpTreeInfo(TreeInfo *node, int depth) { + char bullet_list[] = { '-', '*', 'o' }; int i; - Debug("tree", "Dumping TreeInfo:"); + if (depth == 0) + Debug("tree", "Dumping TreeInfo:"); while (node) { - for (i = 0; i < (depth + 1) * 3; i++) + char bullet = bullet_list[depth % ARRAY_SIZE(bullet_list)]; + + for (i = 0; i < depth * 2; i++) DebugContinued("", " "); - DebugContinued("tree", "'%s' / '%s'\n", node->identifier, node->name); + DebugContinued("tree", "%c '%s' ['%s] [PARENT: '%s'] %s\n", + bullet, node->name, node->identifier, + (node->node_parent ? node->node_parent->identifier : "-"), + (node->node_group ? "[GROUP]" : "")); /* // use for dumping artwork info tree @@ -2364,6 +2389,7 @@ SetupFileHash *loadSetupFileHash(char *filename) #define TOKEN_STR_LAST_LEVEL_SERIES "last_level_series" #define TOKEN_STR_LAST_PLAYED_LEVEL "last_played_level" #define TOKEN_STR_HANDICAP_LEVEL "handicap_level" +#define TOKEN_STR_LAST_USER "last_user" // level directory info #define LEVELINFO_TOKEN_IDENTIFIER 0 @@ -2886,7 +2912,7 @@ static TreeInfo *createTopTreeInfoNode(TreeInfo *node_first) ti_new->parent_link = FALSE; setString(&ti_new->identifier, node_first->identifier); - setString(&ti_new->name, "level sets"); + setString(&ti_new->name, INFOTEXT_LEVEL_DIR); setString(&ti_new->name_sorting, ti_new->name); setString(&ti_new->subdir, STRING_TOP_DIRECTORY); @@ -2895,7 +2921,7 @@ static TreeInfo *createTopTreeInfoNode(TreeInfo *node_first) ti_new->sort_priority = node_first->sort_priority;; ti_new->latest_engine = node_first->latest_engine; - setString(&ti_new->class_desc, "level sets"); + setString(&ti_new->class_desc, INFOTEXT_LEVEL_DIR); ti_new->node_group = node_first; ti_new->level_group = TRUE; @@ -3897,8 +3923,9 @@ void LoadArtworkInfo(void) #endif } -static void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, - LevelDirTree *level_node) +static void LoadArtworkInfoFromLevelInfoExt(ArtworkDirTree **artwork_node, + ArtworkDirTree *node_parent, + LevelDirTree *level_node) { int type = (*artwork_node)->type; @@ -3947,12 +3974,43 @@ static void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, DrawInitText(level_node->name, 150, FC_YELLOW); if (level_node->node_group != NULL) - LoadArtworkInfoFromLevelInfo(artwork_node, level_node->node_group); + { + TreeInfo *artwork_new = newTreeInfo(); + + if (node_parent) + setTreeInfoToDefaultsFromParent(artwork_new, node_parent); + else + setTreeInfoToDefaults(artwork_new, type); + + artwork_new->level_group = TRUE; + + setString(&artwork_new->identifier, level_node->subdir); + setString(&artwork_new->name, level_node->name); + setString(&artwork_new->name_sorting, level_node->name_sorting); + + pushTreeInfo(artwork_node, artwork_new); + + // create node to link back to current custom artwork directory + createParentTreeInfoNode(artwork_new); + + // recursively step into sub-directory and look for more custom artwork + LoadArtworkInfoFromLevelInfoExt(&artwork_new->node_group, artwork_new, + level_node->node_group); + + // if sub-tree has no custom artwork at all, remove it + if (artwork_new->node_group->next == NULL) + removeTreeInfo(artwork_node); + } level_node = level_node->next; } } +static void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node) +{ + LoadArtworkInfoFromLevelInfoExt(artwork_node, NULL, leveldir_first_all); +} + void LoadLevelArtworkInfo(void) { print_timestamp_init("LoadLevelArtworkInfo"); @@ -3961,11 +4019,11 @@ void LoadLevelArtworkInfo(void) print_timestamp_time("DrawTimeText"); - LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first_all); + LoadArtworkInfoFromLevelInfo(&artwork.gfx_first); print_timestamp_time("LoadArtworkInfoFromLevelInfo (gfx)"); - LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all); + LoadArtworkInfoFromLevelInfo(&artwork.snd_first); print_timestamp_time("LoadArtworkInfoFromLevelInfo (snd)"); - LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all); + LoadArtworkInfoFromLevelInfo(&artwork.mus_first); print_timestamp_time("LoadArtworkInfoFromLevelInfo (mus)"); SaveArtworkInfoCache(); @@ -4391,6 +4449,99 @@ char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr) return line; } +static void InitLastPlayedLevels_ParentNode(void) +{ + LevelDirTree **leveldir_top = &leveldir_first->node_group->next; + LevelDirTree *leveldir_new = NULL; + + // check if parent node for last played levels already exists + if (strEqual((*leveldir_top)->identifier, TOKEN_STR_LAST_LEVEL_SERIES)) + return; + + leveldir_new = newTreeInfo(); + + setTreeInfoToDefaultsFromParent(leveldir_new, leveldir_first); + + leveldir_new->level_group = TRUE; + + setString(&leveldir_new->identifier, TOKEN_STR_LAST_LEVEL_SERIES); + setString(&leveldir_new->name, "<< (last played level sets)"); + + pushTreeInfo(leveldir_top, leveldir_new); + + // create node to link back to current level directory + createParentTreeInfoNode(leveldir_new); +} + +void UpdateLastPlayedLevels_TreeInfo(void) +{ + char **last_level_series = setup.level_setup.last_level_series; + boolean reset_leveldir_current = FALSE; + LevelDirTree *leveldir_last; + TreeInfo **node_new = NULL; + int i; + + if (last_level_series[0] == NULL) + return; + + InitLastPlayedLevels_ParentNode(); + + // check if current level set is from "last played" sub-tree to be rebuilt + reset_leveldir_current = strEqual(leveldir_current->node_parent->identifier, + TOKEN_STR_LAST_LEVEL_SERIES); + + leveldir_last = getTreeInfoFromIdentifierExt(leveldir_first, + TOKEN_STR_LAST_LEVEL_SERIES, + TRUE); + if (leveldir_last == NULL) + return; + + node_new = &leveldir_last->node_group->next; + + freeTreeInfo(*node_new); + + for (i = 0; last_level_series[i] != NULL; i++) + { + LevelDirTree *node_last = getTreeInfoFromIdentifier(leveldir_first, + last_level_series[i]); + + *node_new = getTreeInfoCopy(node_last); // copy complete node + + (*node_new)->node_top = &leveldir_first; // correct top node link + (*node_new)->node_parent = leveldir_last; // correct parent node link + + (*node_new)->node_group = NULL; + (*node_new)->next = NULL; + + (*node_new)->cl_first = -1; // force setting tree cursor + + node_new = &((*node_new)->next); + } + + if (reset_leveldir_current) + leveldir_current = getTreeInfoFromIdentifier(leveldir_first, + last_level_series[0]); +} + +static void UpdateLastPlayedLevels_List(void) +{ + char **last_level_series = setup.level_setup.last_level_series; + int pos = MAX_LEVELDIR_HISTORY - 1; + int i; + + // search for potentially already existing entry in list of level sets + for (i = 0; last_level_series[i] != NULL; i++) + if (strEqual(last_level_series[i], leveldir_current->identifier)) + pos = i; + + // move list of level sets one entry down (using potentially free entry) + for (i = pos; i > 0; i--) + setString(&last_level_series[i], last_level_series[i - 1]); + + // put last played level set at top position + setString(&last_level_series[0], leveldir_current->identifier); +} + void LoadLevelSetup_LastSeries(void) { // -------------------------------------------------------------------------- @@ -4399,10 +4550,15 @@ void LoadLevelSetup_LastSeries(void) char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); SetupFileHash *level_setup_hash = NULL; + int pos = 0; + int i; // always start with reliable default values leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); + // start with empty history of last played level sets + setString(&setup.level_setup.last_level_series[0], NULL); + if (!strEqual(DEFAULT_LEVELSET, UNDEFINED_LEVELSET)) { leveldir_current = getTreeInfoFromIdentifier(leveldir_first, @@ -4421,6 +4577,24 @@ void LoadLevelSetup_LastSeries(void) if (leveldir_current == NULL) leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); + for (i = 0; i < MAX_LEVELDIR_HISTORY; i++) + { + char token[strlen(TOKEN_STR_LAST_LEVEL_SERIES) + 10]; + LevelDirTree *leveldir_last; + + sprintf(token, "%s.%03d", TOKEN_STR_LAST_LEVEL_SERIES, i); + + last_level_series = getHashEntry(level_setup_hash, token); + + leveldir_last = getTreeInfoFromIdentifier(leveldir_first, + last_level_series); + if (leveldir_last != NULL) + setString(&setup.level_setup.last_level_series[pos++], + last_level_series); + } + + setString(&setup.level_setup.last_level_series[pos], NULL); + freeSetupFileHash(level_setup_hash); } else @@ -4441,12 +4615,15 @@ static void SaveLevelSetup_LastSeries_Ext(boolean deactivate_last_level_series) if (leveldir_current == NULL) return; + char **last_level_series = setup.level_setup.last_level_series; char *filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); - char *level_subdir = leveldir_current->subdir; FILE *file; + int i; InitUserDataDirectory(); + UpdateLastPlayedLevels_List(); + if (!(file = fopen(filename, MODE_WRITE))) { Warn("cannot write setup file '%s'", filename); @@ -4461,8 +4638,17 @@ static void SaveLevelSetup_LastSeries_Ext(boolean deactivate_last_level_series) if (deactivate_last_level_series) fprintf(file, "# %s\n# ", "the following level set may have caused a problem and was deactivated"); - fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES, - level_subdir)); + fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES, + leveldir_current->identifier)); + + for (i = 0; last_level_series[i] != NULL; i++) + { + char token[strlen(TOKEN_STR_LAST_LEVEL_SERIES) + 10]; + + sprintf(token, "%s.%03d", TOKEN_STR_LAST_LEVEL_SERIES, i); + + fprintf(file, "%s\n", getFormattedSetupEntry(token, last_level_series[i])); + } fclose(file); @@ -4726,3 +4912,66 @@ void LevelStats_incSolved(int nr) if (nr >= 0 && nr < MAX_LEVELS) level_stats[nr].solved++; } + +void LoadUserSetup(void) +{ + // -------------------------------------------------------------------------- + // ~/./usersetup.conf + // -------------------------------------------------------------------------- + + char *filename = getPath2(getMainUserGameDataDir(), USERSETUP_FILENAME); + SetupFileHash *user_setup_hash = NULL; + + // always start with reliable default values + user.nr = 0; + + if ((user_setup_hash = loadSetupFileHash(filename))) + { + char *token_value; + + // get last selected user number + token_value = getHashEntry(user_setup_hash, TOKEN_STR_LAST_USER); + + if (token_value) + user.nr = MIN(MAX(0, atoi(token_value)), MAX_PLAYER_NAMES - 1); + + freeSetupFileHash(user_setup_hash); + } + else + { + Debug("setup", "using default setup values"); + } + + free(filename); +} + +void SaveUserSetup(void) +{ + // -------------------------------------------------------------------------- + // ~/./usersetup.conf + // -------------------------------------------------------------------------- + + char *filename = getPath2(getMainUserGameDataDir(), USERSETUP_FILENAME); + FILE *file; + + InitMainUserDataDirectory(); + + if (!(file = fopen(filename, MODE_WRITE))) + { + Warn("cannot write setup file '%s'", filename); + + free(filename); + + return; + } + + fprintFileHeader(file, USERSETUP_FILENAME); + + fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_USER, + i_to_a(user.nr))); + fclose(file); + + SetFilePermissions(filename, PERMS_PRIVATE); + + free(filename); +}