diff --git a/README.md b/README.md index 08d7c26..b3c042f 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,8 @@ - ## TODO - - Change Config to read/write using new Parser logic + - Add array support to variant + - Read/Write keybindings using new parser object - Store Materials in new format supported by parser - Add model description file which has the same syntax supported by parser and modify old blender exporter to conform to new standards - Implement sound/listener loading from scene file @@ -328,4 +329,5 @@ * Removed duplicate parsing logic * Fixed bugs in stripping key name for input map * Modify entity loading logic to use the new parsing code by parsing all entity properties into a hashmap first then recreating entity from that - * Implmented writing to file through the new Parser and Parser_Object + * Implmented writing to file through the new Parser and Parser_Objects + * Changed Config to read/write using new Parser and Parser_Objects diff --git a/build/genie.lua b/build/genie.lua index 0ed1d35..169f99c 100644 --- a/build/genie.lua +++ b/build/genie.lua @@ -11,6 +11,8 @@ solution "Symmetry" buildoptions {"-Wall", "-std=c99", "`pkg-config --cflags-only-I sdl2`"} configuration {"windows", "gmake"} + postbuildcommands {"rm -rf debug/assets"} + postbuildcommands {"rm -rf release/assets"} postbuildcommands {"ln -fs " .. os.getcwd() .. "/../assets debug/assets"} postbuildcommands {"ln -fs " .. os.getcwd() .. "/../assets release/assets"} buildoptions {"-Wall", "-std=c99"} diff --git a/src/common/hashmap.c b/src/common/hashmap.c index eb650bb..13986be 100644 --- a/src/common/hashmap.c +++ b/src/common/hashmap.c @@ -347,3 +347,14 @@ int hashmap_iter_next(struct Hashmap* hashmap, char** key, struct Variant** valu } return 0; } + +void hashmap_copy(struct Hashmap* from, struct Hashmap* to) +{ + struct Variant* from_val = NULL; + char* from_key = NULL; + + HASHMAP_FOREACH(from, from_key, from_val) + { + hashmap_value_set(to, from_key, from_val); + } +} \ No newline at end of file diff --git a/src/common/hashmap.h b/src/common/hashmap.h index 3b0758f..74ac218 100644 --- a/src/common/hashmap.h +++ b/src/common/hashmap.h @@ -13,6 +13,7 @@ struct Variant; struct Hashmap* hashmap_new(void); void hashmap_free(struct Hashmap* hashmap); +void hashmap_copy(struct Hashmap* from, struct Hashmap* to); void hashmap_value_remove(struct Hashmap* hashmap, const char* key); bool hashmap_value_exists(struct Hashmap* hashmap, const char* key); void hashmap_value_set(struct Hashmap* hashmap, const char* key, const struct Variant* value); diff --git a/src/common/parser.c b/src/common/parser.c index f0c6fce..4ed35d5 100644 --- a/src/common/parser.c +++ b/src/common/parser.c @@ -13,9 +13,6 @@ #define MAX_LINE_LEN 512 #define MAX_VALUE_LEN 512 -static int parser_object_type_from_str(const char* str); -static const char* parser_object_type_to_str(int type); - bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line) { if(!file) @@ -241,9 +238,10 @@ int parser_object_type_from_str(const char* str) { int object_type = PO_UNKNOWN; - if(strncmp(str, "Entity", HASH_MAX_KEY_LEN) == 0) object_type = PO_ENTITY; - else if(strncmp(str, "Model", HASH_MAX_KEY_LEN) == 0) object_type = PO_MODEL; - else if(strncmp(str, "Material", HASH_MAX_KEY_LEN) == 0) object_type = PO_MATERIAL; + if(strncmp(str, "Entity", HASH_MAX_KEY_LEN) == 0) object_type = PO_ENTITY; + else if(strncmp(str, "Model", HASH_MAX_KEY_LEN) == 0) object_type = PO_MODEL; + else if(strncmp(str, "Material", HASH_MAX_KEY_LEN) == 0) object_type = PO_MATERIAL; + else if(strncmp(str, "Config", HASH_MAX_KEY_LEN) == 0) object_type = PO_CONFIG; return object_type; } @@ -255,6 +253,7 @@ const char* parser_object_type_to_str(int type) case PO_ENTITY: return "Entity"; case PO_MODEL: return "Model"; case PO_MATERIAL: return "Material"; + case PO_CONFIG: return "Config"; case PO_UNKNOWN: return "Unknown"; default: return "Unknown"; } diff --git a/src/common/parser.h b/src/common/parser.h index 70a9efe..999b6e9 100644 --- a/src/common/parser.h +++ b/src/common/parser.h @@ -5,6 +5,7 @@ enum Parser_Object_Type { + PO_CONFIG, PO_ENTITY, PO_MATERIAL, PO_MODEL, @@ -30,5 +31,7 @@ void parser_free(struct Parser* parser); struct Parser* parser_new(void); struct Parser_Object* parser_object_new(struct Parser* parser, int type); bool parser_write_objects(struct Parser* parser, FILE* file, const char* filename); +int parser_object_type_from_str(const char* str); +const char* parser_object_type_to_str(int type); #endif diff --git a/src/game/config_vars.c b/src/game/config_vars.c index 00373c6..9cb3e3e 100644 --- a/src/game/config_vars.c +++ b/src/game/config_vars.c @@ -14,8 +14,6 @@ static struct Hashmap* cvars = NULL; -static void config_on_parser_assign(const char* key, const char* value, const char* filename, int current_line); - void config_vars_init(void) { cvars = hashmap_new(); @@ -46,39 +44,53 @@ struct Hashmap* config_vars_get(void) return cvars; } -void config_on_parser_assign(const char* key, const char* value, const char* filename, int current_line) -{ - struct Variant* cvar = hashmap_value_get(cvars, key); - if(!cvar) - { - log_warning("Unknown config key '%s' in file %s, line %d", key, filename, current_line); - return; - } - variant_from_str(cvar, value, cvar->type); -} - bool config_vars_load(const char* filename, int directory_type) { - bool success = false; FILE* config_file = io_file_open(directory_type, filename, "rb"); if(!config_file) { log_error("config:vars_load", "Could not open %s", filename); - return success; + return false; } - if(!parser_load(config_file, filename, &config_on_parser_assign, false, 0)) - { - log_error("config_vars:load", "Failed to parse config file %s", filename); - } - else - { - log_message("Loaded config from %s", filename); - success = true; - } + struct Parser* parser = parser_load_objects(config_file, filename); + if(!parser) + { + log_error("config_vars:load", "Failed to load config data from %s", filename); + fclose(config_file); + return false; + } + bool config_loaded = false; + for(int i = 0; i < array_len(parser->objects); i++) + { + struct Parser_Object* object = &parser->objects[i]; + if(object->type != PO_CONFIG) + { + log_warning("Unexpected config object type %s in %s", parser_object_type_to_str(object->type), filename); + continue; + } + + config_loaded = true; + char* key = NULL; + struct Variant* value = NULL; + char variant_str[MAX_VARIANT_STR_LEN]; + HASHMAP_FOREACH(object->data, key, value) + { + struct Variant* existing_val = hashmap_value_get(cvars, key); + if(!existing_val) + { + log_warning("Unkown key '%s' in config file %s", key, filename); + continue; + } + + variant_copy(existing_val, value); + } + } + + if(config_loaded) log_message("Loaded config from %s", filename); fclose(config_file); - return success; + return config_loaded; } bool config_vars_save(const char* filename, int directory_type) @@ -91,17 +103,32 @@ bool config_vars_save(const char* filename, int directory_type) return success; } - char* key = NULL; - struct Variant* value = NULL; - char variant_str[MAX_VARIANT_STR_LEN]; - HASHMAP_FOREACH(cvars, key, value) + struct Parser* parser = parser_new(); + if(!parser) + { + log_error("config_vars:save", "Could not create Parser for %s", filename); + fclose(config_file); + return false; + } + + struct Parser_Object* object = parser_object_new(parser, PO_CONFIG); + if(!object) + { + log_error("config_vars:save", "Could not create Parser_Object for %s", filename); + parser_free(parser); + fclose(config_file); + return false; + } + + hashmap_copy(cvars, object->data); + + if(!parser_write_objects(parser, config_file, filename)) { - memset(variant_str, '\0', MAX_VARIANT_STR_LEN); - variant_to_str(value, variant_str, MAX_VARIANT_STR_LEN); - fprintf(config_file, "%s: %s\n", key, variant_str); + log_error("config_vars:save", "Failed to write config to '%s'", filename); + success = false; } - log_message("Config file %s written.", filename); - success = true; + + parser_free(parser); fclose(config_file); return success; } diff --git a/src/game/main.c b/src/game/main.c index 296a4ca..d72d599 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -176,10 +176,10 @@ bool init(void) io_file_init(install_path, user_path); free(install_path); free(user_path); - if(!config_vars_load("config.cfg", DIRT_USER)) + if(!config_vars_load("config.symtres", DIRT_USER)) { log_error("main:init", "Could not load config, reverting to defaults"); - config_vars_save("config.cfg", DIRT_USER); + config_vars_save("config.symtres", DIRT_USER); } if(!platform_init_video()) return false;