X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=b116457e575d5df7addfa73e9571b0027c985395;hb=c71f734c9f306daaca1a262d9f07ddae5bc71073;hp=cb3b73f18611b40b131bcfe9ef71097f85467454;hpb=f3ab1f12fc514251aad3f8efcb30b7f1620fffdb;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index cb3b73f1..b116457e 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -86,13 +86,16 @@ static char *levelclass_desc[NUM_LEVELCLASS_DESC] = #define MAX_COOKIE_LEN 256 + static void setTreeInfoToDefaults(TreeInfo *, int); static int compareTreeInfoEntries(const void *, const void *); static int token_value_position = TOKEN_VALUE_POSITION_DEFAULT; static int token_comment_position = TOKEN_COMMENT_POSITION_DEFAULT; -static SetupFileHash *level_artwork_info_hash = NULL; +static SetupFileHash *artworkinfo_cache_old = NULL; +static SetupFileHash *artworkinfo_cache_new = NULL; +static boolean use_artworkinfo_cache = TRUE; /* ------------------------------------------------------------------------- */ @@ -157,6 +160,16 @@ static char *getLevelSetupDir(char *level_subdir) return levelsetup_dir; } +static char *getCacheDir() +{ + static char *cache_dir = NULL; + + if (cache_dir == NULL) + cache_dir = getPath2(getUserGameDataDir(), CACHE_DIRECTORY); + + return cache_dir; +} + static char *getLevelDirFromTreeInfo(TreeInfo *node) { static char *level_dir = NULL; @@ -796,7 +809,7 @@ void InitUserLevelDirectory(char *level_subdir) { createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE); createDirectory(getUserLevelDir(NULL), "main user level", PERMS_PRIVATE); - createDirectory(getUserLevelDir(level_subdir), "user level",PERMS_PRIVATE); + createDirectory(getUserLevelDir(level_subdir), "user level", PERMS_PRIVATE); SaveUserLevelInfo(); } @@ -806,7 +819,13 @@ void InitLevelSetupDirectory(char *level_subdir) { createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE); createDirectory(getLevelSetupDir(NULL), "main level setup", PERMS_PRIVATE); - createDirectory(getLevelSetupDir(level_subdir), "level setup",PERMS_PRIVATE); + createDirectory(getLevelSetupDir(level_subdir), "level setup", PERMS_PRIVATE); +} + +void InitCacheDirectory() +{ + createDirectory(getUserGameDataDir(), "user data", PERMS_PRIVATE); + createDirectory(getCacheDir(), "cache data", PERMS_PRIVATE); } @@ -1654,7 +1673,11 @@ static void *loadSetupFileData(char *filename, boolean use_hash) /* find end of token to determine start of value */ for (line_ptr = token; *line_ptr; line_ptr++) { +#if 1 + if (*line_ptr == ':' || *line_ptr == '=') +#else if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':') +#endif { *line_ptr = '\0'; /* terminate token string */ value = line_ptr + 1; /* set beginning of value */ @@ -1663,6 +1686,11 @@ static void *loadSetupFileData(char *filename, boolean use_hash) } } + /* cut trailing whitespaces from token */ + for (line_ptr = &token[strlen(token)]; line_ptr >= token; line_ptr--) + if ((*line_ptr == ' ' || *line_ptr == '\t') && *(line_ptr + 1) == '\0') + *line_ptr = '\0'; + /* cut leading whitespaces from value */ for (; *value; value++) if (*value != ' ' && *value != '\t') @@ -1962,6 +1990,9 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) static void freeTreeInfo(TreeInfo *ti) { + if (ti == NULL) + return; + checked_free(ti->subdir); checked_free(ti->fullpath); checked_free(ti->basepath); @@ -1993,6 +2024,8 @@ static void freeTreeInfo(TreeInfo *ti) checked_free(ti->level_filename); checked_free(ti->level_filetype); } + + checked_free(ti); } void setSetupInfo(struct TokenInfo *token_info, @@ -2100,6 +2133,221 @@ static void createParentTreeInfoNode(TreeInfo *node_parent) pushTreeInfo(&node_parent->node_group, ti_new); } + +/* -------------------------------------------------------------------------- */ +/* functions for handling level and custom artwork info cache */ +/* -------------------------------------------------------------------------- */ + +static void LoadArtworkInfoCache() +{ + InitCacheDirectory(); + + if (artworkinfo_cache_old == NULL) + { + char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE); + + /* try to load artwork info hash from already existing cache file */ + artworkinfo_cache_old = loadSetupFileHash(filename); + + /* if no artwork info cache file was found, start with empty hash */ + if (artworkinfo_cache_old == NULL) + artworkinfo_cache_old = newSetupFileHash(); + + free(filename); + } + + if (artworkinfo_cache_new == NULL) + artworkinfo_cache_new = newSetupFileHash(); +} + +static void SaveArtworkInfoCache() +{ + char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE); + + InitCacheDirectory(); + + saveSetupFileHash(artworkinfo_cache_new, filename); + + free(filename); +} + +static char *getCacheTokenPrefix(char *prefix1, char *prefix2) +{ + static char *prefix = NULL; + + checked_free(prefix); + + prefix = getStringCat2WithSeparator(prefix1, prefix2, "."); + + return prefix; +} + +/* (identical to above function, but separate string buffer needed -- nasty) */ +static char *getCacheToken(char *prefix, char *suffix) +{ + static char *token = NULL; + + checked_free(token); + + token = getStringCat2WithSeparator(prefix, suffix, "."); + + return token; +} + +static char *getFileTimestamp(char *filename) +{ + struct stat file_status; + + if (stat(filename, &file_status) != 0) /* cannot stat file */ + return getStringCopy(i_to_a(0)); + + return getStringCopy(i_to_a(file_status.st_mtime)); +} + +static boolean modifiedFileTimestamp(char *filename, char *timestamp_string) +{ + struct stat file_status; + + if (timestamp_string == NULL) + return TRUE; + + if (stat(filename, &file_status) != 0) /* cannot stat file */ + return TRUE; + + return (file_status.st_mtime != atoi(timestamp_string)); +} + +static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type) +{ + char *identifier = level_node->subdir; + char *type_string = ARTWORK_DIRECTORY(type); + char *token_prefix = getCacheTokenPrefix(type_string, identifier); + char *token_main = getCacheToken(token_prefix, "CACHED"); + char *cache_entry = getHashEntry(artworkinfo_cache_old, token_main); + boolean cached = (cache_entry != NULL && strEqual(cache_entry, "true")); + TreeInfo *artwork_info = NULL; + + if (!use_artworkinfo_cache) + return NULL; + + if (cached) + { + int i; + + artwork_info = newTreeInfo(); + setTreeInfoToDefaults(artwork_info, type); + + /* set all structure fields according to the token/value pairs */ + ldi = *artwork_info; + for (i = 0; artworkinfo_tokens[i].type != -1; i++) + { + char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text); + char *value = getHashEntry(artworkinfo_cache_old, token); + + setSetupInfo(artworkinfo_tokens, i, value); + + /* check if cache entry for this item is invalid or incomplete */ + if (value == NULL) + { +#if 1 + printf("::: - WARNING: cache entry '%s' invalid\n", token); +#endif + + cached = FALSE; + } + } + *artwork_info = ldi; + } + + if (cached) + { + char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node), + LEVELINFO_FILENAME); + char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info), + ARTWORKINFO_FILENAME(type)); + + /* check if corresponding "levelinfo.conf" file has changed */ + token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO"); + cache_entry = getHashEntry(artworkinfo_cache_old, token_main); + + if (modifiedFileTimestamp(filename_levelinfo, cache_entry)) + cached = FALSE; + + /* check if corresponding ".conf" file has changed */ + token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO"); + cache_entry = getHashEntry(artworkinfo_cache_old, token_main); + + if (modifiedFileTimestamp(filename_artworkinfo, cache_entry)) + cached = FALSE; + +#if 0 + if (!cached) + printf("::: '%s': INVALIDATED FROM CACHE BY TIMESTAMP\n", identifier); +#endif + + checked_free(filename_levelinfo); + checked_free(filename_artworkinfo); + } + + if (!cached && artwork_info != NULL) + { + freeTreeInfo(artwork_info); + + return NULL; + } + + return artwork_info; +} + +static void setArtworkInfoCacheEntry(TreeInfo *artwork_info, + LevelDirTree *level_node, int type) +{ + char *identifier = level_node->subdir; + char *type_string = ARTWORK_DIRECTORY(type); + char *token_prefix = getCacheTokenPrefix(type_string, identifier); + char *token_main = getCacheToken(token_prefix, "CACHED"); + boolean set_cache_timestamps = TRUE; + int i; + + setHashEntry(artworkinfo_cache_new, token_main, "true"); + + if (set_cache_timestamps) + { + char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node), + LEVELINFO_FILENAME); + char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info), + ARTWORKINFO_FILENAME(type)); + char *timestamp_levelinfo = getFileTimestamp(filename_levelinfo); + char *timestamp_artworkinfo = getFileTimestamp(filename_artworkinfo); + + token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO"); + setHashEntry(artworkinfo_cache_new, token_main, timestamp_levelinfo); + + token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO"); + setHashEntry(artworkinfo_cache_new, token_main, timestamp_artworkinfo); + + checked_free(filename_levelinfo); + checked_free(filename_artworkinfo); + checked_free(timestamp_levelinfo); + checked_free(timestamp_artworkinfo); + } + + ldi = *artwork_info; + for (i = 0; artworkinfo_tokens[i].type != -1; i++) + { + char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text); + char *value = getSetupValue(artworkinfo_tokens[i].type, + artworkinfo_tokens[i].value); + if (value != NULL) + setHashEntry(artworkinfo_cache_new, token, value); + } +} + + +/* -------------------------------------------------------------------------- */ +/* functions for loading level info and custom artwork info */ +/* -------------------------------------------------------------------------- */ + /* forward declaration for recursive call by "LoadLevelInfoFromLevelDir()" */ static void LoadLevelInfoFromLevelDir(TreeInfo **, TreeInfo *, char *); @@ -2157,8 +2405,6 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, if (strEqual(leveldir_new->name, ANONYMOUS_NAME)) setString(&leveldir_new->name, leveldir_new->subdir); - DrawInitText(leveldir_new->name, 150, FC_YELLOW); - if (leveldir_new->identifier == NULL) leveldir_new->identifier = getStringCopy(leveldir_new->subdir); @@ -2209,6 +2455,9 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, (leveldir_new->user_defined || !leveldir_new->handicap ? leveldir_new->last_level : leveldir_new->first_level); + if (leveldir_new->level_group) + DrawInitText(leveldir_new->name, 150, FC_YELLOW); + #if 0 /* !!! don't skip sets without levels (else artwork base sets are missing) */ #if 1 @@ -2234,7 +2483,7 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, /* create node to link back to current level directory */ createParentTreeInfoNode(leveldir_new); - /* step into sub-directory and look for more level series */ + /* recursively step into sub-directory and look for more level series */ LoadLevelInfoFromLevelDir(&leveldir_new->node_group, leveldir_new, directory_path); } @@ -2322,7 +2571,7 @@ void LoadLevelInfo() { InitUserLevelDirectory(getLoginName()); - DrawInitText("Loading level series:", 120, FC_GREEN); + DrawInitText("Loading level series", 120, FC_GREEN); LoadLevelInfoFromLevelDir(&leveldir_first, NULL, options.level_directory); LoadLevelInfoFromLevelDir(&leveldir_first, NULL, getUserLevelDir(NULL)); @@ -2422,10 +2671,6 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, if (strEqual(artwork_new->name, ANONYMOUS_NAME)) setString(&artwork_new->name, artwork_new->subdir); -#if 0 - DrawInitText(artwork_new->name, 150, FC_YELLOW); -#endif - if (artwork_new->identifier == NULL) artwork_new->identifier = getStringCopy(artwork_new->subdir); @@ -2482,7 +2727,9 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, setString(&artwork_new->name_sorting, artwork_new->name); } +#if 0 DrawInitText(artwork_new->name, 150, FC_YELLOW); +#endif pushTreeInfo(node_first, artwork_new); @@ -2572,21 +2819,9 @@ static TreeInfo *getDummyArtworkInfo(int type) void LoadArtworkInfo() { -#if 1 - if (level_artwork_info_hash == NULL) - { - char *filename = getPath2(getSetupDir(), "test.conf"); - - level_artwork_info_hash = loadSetupFileHash(filename); + LoadArtworkInfoCache(); - if (level_artwork_info_hash == NULL) - level_artwork_info_hash = newSetupFileHash(); - - free(filename); - } -#endif - - DrawInitText("Looking for custom artwork:", 120, FC_GREEN); + DrawInitText("Looking for custom artwork", 120, FC_GREEN); LoadArtworkInfoFromArtworkDir(&artwork.gfx_first, NULL, options.graphics_directory, @@ -2665,6 +2900,8 @@ void LoadArtworkInfo() void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, LevelDirTree *level_node) { + int type = (*artwork_node)->type; + /* recursively check all level directories for artwork sub-directories */ while (level_node) @@ -2672,138 +2909,45 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, /* check all tree entries for artwork, but skip parent link entries */ if (!level_node->parent_link) { - TreeInfo *topnode_last = *artwork_node; - char *path = getPath2(getLevelDirFromTreeInfo(level_node), - ARTWORK_DIRECTORY((*artwork_node)->type)); - -#if 0 - printf("::: looking in directory '%s' for '%s' ...\n", - path, ARTWORK_DIRECTORY((*artwork_node)->type)); -#endif - -#if 1 - char *type_string = ARTWORK_DIRECTORY((*artwork_node)->type); - char *identifier = level_node->subdir; - char *type_identifier = getStringCat2WithSeparator(type_string, - identifier, "."); - char *cache_entry = getHashEntry(level_artwork_info_hash, - type_identifier); - boolean cached = (cache_entry != NULL && strEqual(cache_entry, "true")); + TreeInfo *artwork_new = getArtworkInfoCacheEntry(level_node, type); + boolean cached = (artwork_new != NULL); if (cached) { - int i; - - printf("::: LOADING existing hash entry for '%s' ...\n", - identifier); - - char *type_dir = ARTWORK_DIRECTORY((*artwork_node)->type); - TreeInfo *artwork_new = newTreeInfo(); + pushTreeInfo(artwork_node, artwork_new); + } + else + { + TreeInfo *topnode_last = *artwork_node; + char *path = getPath2(getLevelDirFromTreeInfo(level_node), + ARTWORK_DIRECTORY(type)); - setTreeInfoToDefaults(artwork_new, (*artwork_node)->type); + LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, type); - /* set all structure fields according to the token/value pairs */ - ldi = *artwork_new; - for (i = 0; artworkinfo_tokens[i].type != -1; i++) + if (topnode_last != *artwork_node) /* check for newly added node */ { - char *token = getStringCat3WithSeparator(type_dir, identifier, - artworkinfo_tokens[i].text, - "."); - char *value = getHashEntry(level_artwork_info_hash, token); - - printf("::: - '%s' => '%s'\n", token, value); - - setSetupInfo(artworkinfo_tokens, i, value); + artwork_new = *artwork_node; - /* check if cache entry for this item is invalid or incomplete */ - if (value == NULL) - { - printf("::: - WARNING: cache entry '%s' invalid\n", token); + setString(&artwork_new->identifier, level_node->subdir); + setString(&artwork_new->name, level_node->name); + setString(&artwork_new->name_sorting, level_node->name_sorting); - cached = FALSE; - } - - checked_free(token); - } - *artwork_new = ldi; - -#if 0 - if (artwork_new->name_sorting == NULL) - { - printf("::: BOOOM!\n"); - exit(10); + artwork_new->sort_priority = level_node->sort_priority; + artwork_new->color = LEVELCOLOR(artwork_new); } -#endif - if (cached) - pushTreeInfo(artwork_node, artwork_new); - else - freeTreeInfo(artwork_new); + free(path); } - if (!cached) - LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, - (*artwork_node)->type); -#else - LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, - (*artwork_node)->type); -#endif + /* insert artwork info (from old cache or filesystem) into new cache */ + if (artwork_new != NULL) + setArtworkInfoCacheEntry(artwork_new, level_node, type); + } #if 1 - if (!cached && topnode_last != *artwork_node) -#else - if (topnode_last != *artwork_node) + if (level_node->level_group) + DrawInitText(level_node->name, 150, FC_YELLOW); #endif - { - free((*artwork_node)->identifier); - free((*artwork_node)->name); - free((*artwork_node)->name_sorting); - - (*artwork_node)->identifier = getStringCopy(level_node->subdir); - (*artwork_node)->name = getStringCopy(level_node->name); - (*artwork_node)->name_sorting = getStringCopy(level_node->name); - - (*artwork_node)->sort_priority = level_node->sort_priority; - (*artwork_node)->color = LEVELCOLOR((*artwork_node)); - -#if 1 - { - int i; - - printf("::: adding hash entry for set '%s' ...\n", type_identifier); - - setHashEntry(level_artwork_info_hash, type_identifier, "true"); - - ldi = **artwork_node; - for (i = 0; artworkinfo_tokens[i].type != -1; i++) - { - char *token = getStringCat2WithSeparator(type_identifier, - artworkinfo_tokens[i].text, - "."); - char *value = getSetupValue(artworkinfo_tokens[i].type, - artworkinfo_tokens[i].value); - if (value != NULL) - { - setHashEntry(level_artwork_info_hash, token, value); - - printf("::: - setting '%s' => '%s'\n\n", - token, value); - } - - if (strEqual(artworkinfo_tokens[i].text, "name_sorting")) - printf("::: - '%s' => '%s' => '%s'\n", - identifier, token, - (*artwork_node)->name_sorting); - - checked_free(token); - } - } -#endif - } - - free(path); - free(type_identifier); - } if (level_node->node_group != NULL) LoadArtworkInfoFromLevelInfo(artwork_node, level_node->node_group); @@ -2814,19 +2958,13 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, void LoadLevelArtworkInfo() { - DrawInitText("Looking for custom level artwork:", 120, FC_GREEN); + DrawInitText("Looking for custom level artwork", 120, FC_GREEN); LoadArtworkInfoFromLevelInfo(&artwork.gfx_first, leveldir_first_all); LoadArtworkInfoFromLevelInfo(&artwork.snd_first, leveldir_first_all); LoadArtworkInfoFromLevelInfo(&artwork.mus_first, leveldir_first_all); -#if 1 - char *filename = getPath2(getSetupDir(), "test.conf"); - - saveSetupFileHash(level_artwork_info_hash, filename); - - free(filename); -#endif + SaveArtworkInfoCache(); /* needed for reloading level artwork not known at ealier stage */