new method of pack loading, assume data or data.btw in root to point to all other
This commit is contained in:
		
							
								
								
									
										3
									
								
								apps/lua/data/packs/data.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								apps/lua/data/packs/data.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | [[deps]] | ||||||
|  | source = "../../common-data" # where does it come from, might be an url | ||||||
|  | name = "common-data"         # should be globally unique | ||||||
							
								
								
									
										11
									
								
								apps/lua/data/twn.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								apps/lua/data/twn.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | [about] | ||||||
|  | title = "Lua Townengine!" | ||||||
|  | developer = "Somebody" | ||||||
|  | app_id = "twnlua" | ||||||
|  | dev_id = "somebody" | ||||||
|  |  | ||||||
|  | [game] | ||||||
|  | base_render_width = 640 | ||||||
|  | base_render_height = 360 | ||||||
|  |  | ||||||
|  | [engine] | ||||||
							
								
								
									
										15
									
								
								docs/packaging.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								docs/packaging.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | assets are distributed by packs, which can come in archived or folder form (for development purposes) | ||||||
|  |  | ||||||
|  | one pack by the name of 'data' is always assumed to be present alongside game executable root, | ||||||
|  | whether in folder /data/ or /data.btw file, where precedence is taking over /data/ | ||||||
|  |  | ||||||
|  | root 'data' should be used to point to other dependency packs in /packs/data.toml file | ||||||
|  |  | ||||||
|  | --- | ||||||
|  | [[deps]] | ||||||
|  | source = "../../common-data" # where does it come from, might be an url | ||||||
|  | name = "common-data"         # should be globally unique | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | they're mounted to / in the virtual file system by default, if same files are present in multiple packs, | ||||||
|  | only the one loaded first is visible | ||||||
							
								
								
									
										128
									
								
								src/twn_loop.c
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								src/twn_loop.c
									
									
									
									
									
								
							| @@ -188,6 +188,96 @@ static void main_loop(void) { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* TODO: cache and deny duplicates */ | ||||||
|  | /* TODO: ability to redefine mounting point for a dependency */ | ||||||
|  | /* TODO: ability to load external sources over HTTP if url is given */ | ||||||
|  | static void resolve_pack_dependencies(const char *pack_name) { | ||||||
|  |     char *path; | ||||||
|  |     if (SDL_asprintf(&path, "/packs/%s.toml", pack_name) == -1) { | ||||||
|  |         CRY("resolve_pack_dependencies()", "Allocation error"); | ||||||
|  |         goto ERR_PACK_MANIFEST_PATH_ALLOC_FAIL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!PHYSFS_exists(path)) | ||||||
|  |         /* no package manifest provided, abort */ | ||||||
|  |         goto OK_NO_MANIFEST; | ||||||
|  |  | ||||||
|  |     char *manifest_file = file_to_str(path); | ||||||
|  |     if (!manifest_file) { | ||||||
|  |         CRY_PHYSFS("Pack manifest file loading failed"); | ||||||
|  |         goto ERR_PACK_MANIFEST_FILE_LOADING; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     char errbuf[256]; /* tomlc99 example implies that this is enough... */ | ||||||
|  |     toml_table_t *manifest = toml_parse(manifest_file, errbuf, sizeof errbuf); | ||||||
|  |     SDL_free(manifest_file); | ||||||
|  |  | ||||||
|  |     if (!manifest) { | ||||||
|  |         CRY("Pack manifest decoding failed", errbuf); | ||||||
|  |         goto ERR_PACK_MANIFEST_DECODING; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     toml_array_t *deps = toml_array_in(manifest, "deps"); | ||||||
|  |     if (!deps) | ||||||
|  |         goto OK_NO_DEPS; | ||||||
|  |  | ||||||
|  |     /* iterate over entries in [[deps]] array */ | ||||||
|  |     /* TODO: use sub procedures for failable loops? so that error mechanism cleans well */ | ||||||
|  |     toml_table_t *cur_dep = toml_table_at(deps, 0); | ||||||
|  |     for (int idx = 0; cur_dep; ++idx, cur_dep = toml_table_at(deps, idx)) { | ||||||
|  |         toml_datum_t dep_name = toml_string_in(cur_dep, "name"); | ||||||
|  |         if (!dep_name.ok) { | ||||||
|  |             log_warn("No 'name' is present in pack dependency, skipping it"); | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         char *dep_pack_name; | ||||||
|  |         if (SDL_asprintf(&dep_pack_name, "%s.btw", dep_name.u.s) == -1) { | ||||||
|  |             CRY("resolve_pack_dependencies()", "Allocation error"); | ||||||
|  |             SDL_free(dep_name.u.s); | ||||||
|  |             goto ERR_DEP_PATH_ALLOC_FAIL; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         /* try loading pack */ | ||||||
|  |         if (!PHYSFS_mount(dep_pack_name, "/", true)) { | ||||||
|  |             /* if it failes, try going for source */ | ||||||
|  |             toml_datum_t dep_source = toml_string_in(cur_dep, "source"); | ||||||
|  |             if (!dep_source.ok) { | ||||||
|  |                 log_warn("No 'source' is present in pack %s, while %s.btw isn't present, skipping it", dep_name.u.s, dep_name.u.s); | ||||||
|  |                 SDL_free(dep_name.u.s); | ||||||
|  |                 SDL_free(dep_pack_name); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (!PHYSFS_mount(dep_source.u.s, "/", true)) | ||||||
|  |                 CRY("Cannot load pack", "Nothing is given to work with"); | ||||||
|  |  | ||||||
|  |             log_info("Pack loaded: %s\n", dep_source.u.s); | ||||||
|  |  | ||||||
|  |             SDL_free(dep_source.u.s); | ||||||
|  |         } else | ||||||
|  |             log_info("Pack loaded: %s\n", dep_pack_name); | ||||||
|  |  | ||||||
|  |         SDL_free(dep_pack_name); | ||||||
|  |  | ||||||
|  |         /* recursive resolution */ | ||||||
|  |         resolve_pack_dependencies(dep_name.u.s); | ||||||
|  |  | ||||||
|  |         SDL_free(dep_name.u.s); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | ERR_DEP_PATH_ALLOC_FAIL: | ||||||
|  | OK_NO_DEPS: | ||||||
|  |     toml_free(manifest); | ||||||
|  | ERR_PACK_MANIFEST_DECODING: | ||||||
|  | ERR_PACK_MANIFEST_FILE_LOADING: | ||||||
|  | OK_NO_MANIFEST: | ||||||
|  |     SDL_free(path); | ||||||
|  | ERR_PACK_MANIFEST_PATH_ALLOC_FAIL: | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static bool initialize(void) { | static bool initialize(void) { | ||||||
|     if (SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) == -1) { |     if (SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) == -1) { | ||||||
|         CRY_SDL("SDL initialization failed."); |         CRY_SDL("SDL initialization failed."); | ||||||
| @@ -199,6 +289,9 @@ static bool initialize(void) { | |||||||
|     /* that is why PhysicsFS is initialized before anything else */ |     /* that is why PhysicsFS is initialized before anything else */ | ||||||
|     toml_set_memutil(SDL_malloc, SDL_free); |     toml_set_memutil(SDL_malloc, SDL_free); | ||||||
|  |  | ||||||
|  |     /* time to orderly resolve any dependencies present */ | ||||||
|  |     resolve_pack_dependencies("data"); | ||||||
|  |  | ||||||
|     /* load the config file into an opaque table */ |     /* load the config file into an opaque table */ | ||||||
|     { |     { | ||||||
|         char *config_file = file_to_str("/twn.toml"); |         char *config_file = file_to_str("/twn.toml"); | ||||||
| @@ -562,33 +655,16 @@ int enter_loop(int argc, char **argv) { | |||||||
|  |  | ||||||
|     /* needs to be done before anything else so config can be loaded */ |     /* needs to be done before anything else so config can be loaded */ | ||||||
|     /* TODO: ANDROID: see the warning in physicsfs PHYSFS_init docs/header */ |     /* TODO: ANDROID: see the warning in physicsfs PHYSFS_init docs/header */ | ||||||
|     if (!PHYSFS_init(ctx.argv[0]) || !PHYSFS_mount(PHYSFS_getBaseDir(), NULL, true)) { |     if (!PHYSFS_init(ctx.argv[0])) { | ||||||
|         CRY_PHYSFS("Filesystem initialization failed"); |         CRY_PHYSFS("Filesystem initialization failed"); | ||||||
|         return EXIT_FAILURE; |         return EXIT_FAILURE; | ||||||
|     } |     } | ||||||
|     /* base dir is fine, but we'd like to look into all the data archives, too */ |  | ||||||
|     char **files_here = PHYSFS_enumerateFiles("/"); |  | ||||||
|     if (files_here == NULL) { |  | ||||||
|         CRY_PHYSFS("Filesystem initialization failed"); |  | ||||||
|         return EXIT_FAILURE; |  | ||||||
|     } |  | ||||||
|     for (char **ptr = files_here; *ptr != NULL; ++ptr) { |  | ||||||
|         char *file = *ptr; |  | ||||||
|  |  | ||||||
|         if (!strends(file, "." PACKAGE_EXTENSION)) { |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (!PHYSFS_mount(file, "/", true)) { |  | ||||||
|             CRY_PHYSFS("Filesystem initialization failed"); |  | ||||||
|             return EXIT_FAILURE; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     PHYSFS_freeList(files_here); |  | ||||||
|  |  | ||||||
|     /* process arguments */ |     /* process arguments */ | ||||||
|     bool force_debug = false; |     bool force_debug = false; | ||||||
|     bool force_release = false; |     bool force_release = false; | ||||||
|  |     bool data_dir_mounted = false; | ||||||
|  |  | ||||||
|     for (int i = 1; i < argc; ++i) { |     for (int i = 1; i < argc; ++i) { | ||||||
|         /* override data directory */ |         /* override data directory */ | ||||||
|         if (SDL_strcmp(argv[i], "--data-dir") == 0) { |         if (SDL_strcmp(argv[i], "--data-dir") == 0) { | ||||||
| @@ -602,6 +678,8 @@ int enter_loop(int argc, char **argv) { | |||||||
|                 return EXIT_FAILURE; |                 return EXIT_FAILURE; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             data_dir_mounted = true; | ||||||
|  |  | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -618,6 +696,16 @@ int enter_loop(int argc, char **argv) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /* data path not explicitly specified, look into convention defined places */ | ||||||
|  |     if (!data_dir_mounted) { | ||||||
|  |         /* try mouning data folder first, relative to executable root */ | ||||||
|  |         if (!PHYSFS_mount("data", NULL, true)) { | ||||||
|  |             if (!PHYSFS_mount("data.btw", NULL, true)) | ||||||
|  |                 CRY_PHYSFS("Cannot find data.btw or data directory in root. Please create them or specify with --data-dir parameter."); | ||||||
|  |                 return EXIT_FAILURE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (!initialize()) |     if (!initialize()) | ||||||
|         return EXIT_FAILURE; |         return EXIT_FAILURE; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -191,6 +191,8 @@ void textures_dump_atlases(void) { | |||||||
|  |  | ||||||
|         SDL_SaveBMP_RW(ctx.texture_cache.atlas_surfaces[i], handle, true); |         SDL_SaveBMP_RW(ctx.texture_cache.atlas_surfaces[i], handle, true); | ||||||
|         log_info("Dumped atlas %zu to %s", i, buf); |         log_info("Dumped atlas %zu to %s", i, buf); | ||||||
|  |  | ||||||
|  |         SDL_free(buf); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user