X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=b116457e575d5df7addfa73e9571b0027c985395;hb=c71f734c9f306daaca1a262d9f07ddae5bc71073;hp=6d187a02ef97519c5125c1072ee20f5d39326dca;hpb=328e3faf46607ba39f55f84ed3d470de67d5bd6c;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 6d187a02..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 *artworkinfo_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, @@ -2102,85 +2135,212 @@ static void createParentTreeInfoNode(TreeInfo *node_parent) /* -------------------------------------------------------------------------- */ -/* functions for handling custom artwork info cache */ +/* functions for handling level and custom artwork info cache */ /* -------------------------------------------------------------------------- */ -#define ARTWORKINFO_CACHE_FILENAME "cache.conf" - static void LoadArtworkInfoCache() { - if (artworkinfo_hash == NULL) + InitCacheDirectory(); + + if (artworkinfo_cache_old == NULL) { - char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME); + char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE); /* try to load artwork info hash from already existing cache file */ - artworkinfo_hash = loadSetupFileHash(filename); + artworkinfo_cache_old = loadSetupFileHash(filename); /* if no artwork info cache file was found, start with empty hash */ - if (artworkinfo_hash == NULL) - artworkinfo_hash = newSetupFileHash(); + 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(getSetupDir(), ARTWORKINFO_CACHE_FILENAME); + char *filename = getPath2(getCacheDir(), ARTWORKINFO_CACHE_FILE); + + InitCacheDirectory(); - saveSetupFileHash(artworkinfo_hash, filename); + saveSetupFileHash(artworkinfo_cache_new, filename); free(filename); } -static TreeInfo *getArtworkInfoFromCache(char *identifier, int type) +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 = getStringCat2WithSeparator(type_string, identifier, "."); - char *cache_entry = getHashEntry(artworkinfo_hash, token_prefix); + 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_new = NULL; + TreeInfo *artwork_info = NULL; + + if (!use_artworkinfo_cache) + return NULL; if (cached) { int i; - printf("::: LOADING existing hash entry for '%s' ...\n", identifier); - - artwork_new = newTreeInfo(); - setTreeInfoToDefaults(artwork_new, type); + artwork_info = newTreeInfo(); + setTreeInfoToDefaults(artwork_info, type); /* set all structure fields according to the token/value pairs */ - ldi = *artwork_new; + ldi = *artwork_info; for (i = 0; artworkinfo_tokens[i].type != -1; i++) { - char *token = getStringCat2WithSeparator(token_prefix, - artworkinfo_tokens[i].text, "."); - char *value = getHashEntry(artworkinfo_hash, token); - - printf("::: - setting '%s' => '%s'\n", token, value); + 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; } - - checked_free(token); } - *artwork_new = ldi; + *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) - freeTreeInfo(artwork_new); + printf("::: '%s': INVALIDATED FROM CACHE BY TIMESTAMP\n", identifier); +#endif + + checked_free(filename_levelinfo); + checked_free(filename_artworkinfo); } - free(token_prefix); + if (!cached && artwork_info != NULL) + { + freeTreeInfo(artwork_info); - return artwork_new; + 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); + } } @@ -2245,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); @@ -2297,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 @@ -2322,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); } @@ -2410,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)); @@ -2510,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); @@ -2570,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); @@ -2662,7 +2821,7 @@ void LoadArtworkInfo() { LoadArtworkInfoCache(); - DrawInitText("Looking for custom artwork:", 120, FC_GREEN); + DrawInitText("Looking for custom artwork", 120, FC_GREEN); LoadArtworkInfoFromArtworkDir(&artwork.gfx_first, NULL, options.graphics_directory, @@ -2741,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) @@ -2748,80 +2909,46 @@ 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)); - TreeInfo *artwork_new = getArtworkInfoFromCache(level_node->subdir, - (*artwork_node)->type); - boolean cached = FALSE; + TreeInfo *artwork_new = getArtworkInfoCacheEntry(level_node, type); + boolean cached = (artwork_new != NULL); - if (artwork_new != NULL) + if (cached) { pushTreeInfo(artwork_node, artwork_new); - cached = TRUE; } else { - LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, - (*artwork_node)->type); - } + TreeInfo *topnode_last = *artwork_node; + char *path = getPath2(getLevelDirFromTreeInfo(level_node), + ARTWORK_DIRECTORY(type)); -#if 1 - if (!cached && topnode_last != *artwork_node) -#else - if (topnode_last != *artwork_node) -#endif - { - free((*artwork_node)->identifier); - free((*artwork_node)->name); - free((*artwork_node)->name_sorting); + LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, type); - (*artwork_node)->identifier = getStringCopy(level_node->subdir); - (*artwork_node)->name = getStringCopy(level_node->name); - (*artwork_node)->name_sorting = getStringCopy(level_node->name); + if (topnode_last != *artwork_node) /* check for newly added node */ + { + artwork_new = *artwork_node; - (*artwork_node)->sort_priority = level_node->sort_priority; - (*artwork_node)->color = LEVELCOLOR((*artwork_node)); + setString(&artwork_new->identifier, level_node->subdir); + setString(&artwork_new->name, level_node->name); + setString(&artwork_new->name_sorting, level_node->name_sorting); -#if 1 - { - char *identifier = level_node->subdir; - char *type_string = ARTWORK_DIRECTORY((*artwork_node)->type); - char *type_identifier = - getStringCat2WithSeparator(type_string, identifier, "."); - int i; - - printf("::: adding hash entry for set '%s' ...\n", type_identifier); - - setHashEntry(artworkinfo_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(artworkinfo_hash, token, value); - - printf("::: - setting '%s' => '%s'\n\n", - token, value); - } - - checked_free(token); - } - - free(type_identifier); + artwork_new->sort_priority = level_node->sort_priority; + artwork_new->color = LEVELCOLOR(artwork_new); } -#endif + + free(path); } - free(path); + /* insert artwork info (from old cache or filesystem) into new cache */ + if (artwork_new != NULL) + setArtworkInfoCacheEntry(artwork_new, level_node, type); } +#if 1 + if (level_node->level_group) + DrawInitText(level_node->name, 150, FC_YELLOW); +#endif + if (level_node->node_group != NULL) LoadArtworkInfoFromLevelInfo(artwork_node, level_node->node_group); @@ -2831,7 +2958,7 @@ 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);