summary refs log tree commit diff
path: root/src/loader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/loader.c')
-rw-r--r--src/loader.c106
1 files changed, 96 insertions, 10 deletions
diff --git a/src/loader.c b/src/loader.c
index 6a50341..3b39bca 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -39,6 +39,22 @@ struct blob_collection {
 	} items[];
 } *textures = NULL, *maps = NULL, *collisions = NULL;
 
+struct newfun_collection {
+	size_t count;
+	struct newfun_item {
+		struct entity *(*fun)(void);
+		name_T name;
+	} *items;
+} newfuns = {0, NULL};
+
+struct setfun_collection {
+	size_t count;
+	struct setfun_item {
+		int (*fun)(struct entity *const restrict self, char const *const restrict key, char const *const restrict value);
+		name_T name;
+	} *items;
+} setfuns = {0, NULL};
+
 static int name_compare(name_T a, name_T b) {
 	return strcmp(a, b);
 	// return (a > b) - (a < b);
@@ -124,24 +140,40 @@ void res_free_collision(void) {
 	collisions = NULL;
 }
 
+void res_free_newfun(void) {
+	for (size_t i = 0; i < newfuns.count; i++) {
+		free(newfuns.items[i].name);
+	}
+	free(newfuns.items);
+	newfuns.count = 0;
+}
+
+void res_free_setfun(void) {
+	for (size_t i = 0; i < setfuns.count; i++) {
+		free(setfuns.items[i].name);
+	}
+	free(setfuns.items);
+	setfuns.count = 0;
+}
+
 static int res_compare_blobs(void const *a, void const *b) {
 	struct blob_item const *aa = a, *bb = b;
 	return name_compare(aa->name, bb->name);
 }
 
+static int res_compare_newfuns(void const *a, void const *b) {
+	struct newfun_item const *aa = a, *bb = b;
+	return name_compare(aa->name, bb->name);
+}
+
+static int res_compare_setfuns(void const *a, void const *b) {
+	struct setfun_item const *aa = a, *bb = b;
+	return name_compare(aa->name, bb->name);
+}
+
 static struct blob res_get_blob(name_T const name, struct blob_collection *collection) {
 	struct blob_item new = {.name = name};
 	struct blob_item *dst = bsearch(&new, collection->items, collection->count, sizeof (struct blob_item), res_compare_blobs);
-	#if 0
-	fprintf(stderr, "== chunk %zu ==\n", dst - collection->items);
-	for (int i = 0; i < collection->count; i++) {
-		fprintf(stderr, "= %s, %p\n", collection->items[i].name, collection->items[i].blob.data);
-	}
-	if (dst != NULL)
-		fprintf(stderr, "== value %p ==\n", dst->blob.data);
-	else
-		fprintf(stderr, "== not found ==\n");
-	#endif
 	if (dst == NULL) {
 		return (struct blob) {.data = NULL, .size = 0};
 	}
@@ -160,6 +192,24 @@ struct blob res_get_collision(name_T const name) {
 	return res_get_blob(name, collisions);
 }
 
+struct entity *(*res_get_newfun(name_T const name))(void) {
+	struct newfun_item new = {.name = name};
+	struct newfun_item *dst = bsearch(&new, newfuns.items, newfuns.count, sizeof (struct newfun_item), res_compare_newfuns);
+	if (dst == NULL) {
+		return NULL;
+	}
+	return dst->fun;
+}
+
+int (*res_get_setfun(name_T const name))(struct entity *const restrict self, char const *const restrict key, char const *const restrict value) {
+	struct setfun_item new = {.name = name};
+	struct setfun_item *dst = bsearch(&new, setfuns.items, setfuns.count, sizeof (struct setfun_item), res_compare_setfuns);
+	if (dst == NULL) {
+		return NULL;
+	}
+	return dst->fun;
+}
+
 static struct blob_collection *res_push_blob(struct blob *blob, name_T name, struct blob_collection *collection, void (*freeFunc)(void *)) {
 	int found;
 	struct blob_item new = {.blob = *blob, .name = name};
@@ -206,6 +256,42 @@ void res_push_collision(struct blob *blob, name_T name) {
 	collisions = res_push_blob(blob, name, collisions, blob_free_func);
 }
 
+void res_push_newfun(struct entity *(*newfun)(void), name_T name) {
+	int found;
+	struct newfun_item new = {.fun = newfun, .name = name};
+	struct newfun_item *dst = bsearchinsertposition(&new, newfuns.items, newfuns.count, sizeof (struct newfun_item), res_compare_newfuns, &found);
+	if (found) {
+		fprintf(stderr, "warn: name collision: %s\n", new.name);
+		free(dst->name);
+		memcpy(dst, &new, sizeof (struct newfun_item));
+	} else {
+		size_t index = dst - newfuns.items; // hack
+		newfuns.count++;
+		newfuns.items = realloc(newfuns.items, sizeof (struct newfun_item) * newfuns.count);
+		dst = newfuns.items + index; // hack for the struct having been reallocated
+		memmove(dst + 1, dst, sizeof (struct newfun_item) * (newfuns.count - 1 - (dst - newfuns.items)));
+		memcpy(dst, &new, sizeof (struct newfun_item));
+	}
+}
+
+void res_push_setfun(int (*setfun)(struct entity *const restrict self, char const *const restrict key, char const *const restrict value), name_T name) {
+	int found;
+	struct setfun_item new = {.fun = setfun, .name = name};
+	struct setfun_item *dst = bsearchinsertposition(&new, setfuns.items, setfuns.count, sizeof (struct setfun_item), res_compare_setfuns, &found);
+	if (found) {
+		fprintf(stderr, "warn: name collision: %s\n", new.name);
+		free(dst->name);
+		memcpy(dst, &new, sizeof (struct setfun_item));
+	} else {
+		size_t index = dst - setfuns.items; // hack
+		setfuns.count++;
+		setfuns.items = realloc(setfuns.items, sizeof (struct setfun_item) * setfuns.count);
+		dst = setfuns.items + index; // hack for the struct having been reallocated
+		memmove(dst + 1, dst, sizeof (struct setfun_item) * (setfuns.count - 1 - (dst - setfuns.items)));
+		memcpy(dst, &new, sizeof (struct setfun_item));
+	}
+}
+
 int loadResources(char *filename) {
 	// open the file
 	FILE *zip = fopen(filename, "rb");