new method of pack loading, assume data or data.btw in root to point to all other
This commit is contained in:
parent
7bec9f6de6
commit
bbf79ad442
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) {
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) == -1) {
|
||||
CRY_SDL("SDL initialization failed.");
|
||||
@ -199,6 +289,9 @@ static bool initialize(void) {
|
||||
/* that is why PhysicsFS is initialized before anything else */
|
||||
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 */
|
||||
{
|
||||
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 */
|
||||
/* 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");
|
||||
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 */
|
||||
bool force_debug = false;
|
||||
bool force_release = false;
|
||||
bool data_dir_mounted = false;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
/* override data directory */
|
||||
if (SDL_strcmp(argv[i], "--data-dir") == 0) {
|
||||
@ -602,6 +678,8 @@ int enter_loop(int argc, char **argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
data_dir_mounted = true;
|
||||
|
||||
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())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
@ -191,6 +191,8 @@ void textures_dump_atlases(void) {
|
||||
|
||||
SDL_SaveBMP_RW(ctx.texture_cache.atlas_surfaces[i], handle, true);
|
||||
log_info("Dumped atlas %zu to %s", i, buf);
|
||||
|
||||
SDL_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user