summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/entity.h2
-rw-r--r--src/funsinit.c7
-rw-r--r--src/loader.c106
-rw-r--r--src/loader.h11
-rw-r--r--src/main.c52
-rw-r--r--src/player.c2
6 files changed, 169 insertions, 11 deletions
diff --git a/src/entity.h b/src/entity.h
index 52a2eac..354fbc1 100644
--- a/src/entity.h
+++ b/src/entity.h
@@ -1,6 +1,6 @@
#pragma once
-#include "loader.h"
+#include <SDL2/SDL.h>
#define from_fixed(a) (a / 16)
#define to_fixed(a) (a * 16)
diff --git a/src/funsinit.c b/src/funsinit.c
new file mode 100644
index 0000000..5d15cc4
--- /dev/null
+++ b/src/funsinit.c
@@ -0,0 +1,7 @@
+#include "entity.h"
+#include "loader.h"
+#include "main.h"
+
+
+void funs_init(void) {
+}
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");
diff --git a/src/loader.h b/src/loader.h
index b1563bb..016b8b2 100644
--- a/src/loader.h
+++ b/src/loader.h
@@ -1,5 +1,8 @@
#pragma once
+#include <stddef.h>
+#include "entity.h"
+
typedef char * name_T;
struct blob {
@@ -21,4 +24,12 @@ void res_init_collision(void);
void res_free_collision(void);
struct blob res_get_collision(name_T const name);
+void res_free_newfun(void);
+void res_push_newfun(struct entity *(*newfun)(void), name_T name);
+struct entity *(*res_get_newfun(name_T const name))(void);
+
+void res_free_setfun(void);
+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 (*res_get_setfun(name_T const name))(struct entity *const restrict self, char const *const restrict key, char const *const restrict value);
+
int loadResources(char *filename);
diff --git a/src/main.c b/src/main.c
index 6b195b4..8fc400f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -39,6 +39,8 @@ struct entity player[1] = {0};
struct entity *player_new(void);
int player_property(struct entity *const restrict entity, char const *const restrict property, char const *const restrict value);
+void funs_init(void);
+
int main(int const argc, char *const *const argv) {
struct option opts[] = {
{"help", 0, NULL, 'h'},
@@ -156,6 +158,7 @@ int main(int const argc, char *const *const argv) {
{
res_init();
+ funs_init();
if (optind == argc) {
void *a = util_executableRelativePath("assets.res", *argv, 0);
puts(a);
@@ -175,6 +178,55 @@ int main(int const argc, char *const *const argv) {
}
struct blob map = res_get_map("untitled");
tilemap = tilemap_load(map.data, map.size);
+ char *a = (char *) map.data + tilemap->input_bytes;
+ map.size -= tilemap->input_bytes;
+ while (map.size) {
+ size_t len;
+ if ((len = strnlen(a, map.size)) == map.size) {
+ return 1; // hack
+ }
+ char *name = a;
+ puts(name);
+ struct entity *(*fun)(void) = res_get_newfun(name);
+ a += len + 1;
+ map.size -= len + 1;
+ if (fun) {
+ struct entity *entity = fun();
+ while (1) {
+ if ((len = strnlen(a, map.size)) == map.size) {
+ return 1; // hack
+ } else if (len == 0) {
+ a++;
+ map.size--;
+ break;
+ }
+ char *key = a;
+ a += len + 1;
+ map.size -= len + 1;
+ if ((len = strnlen(a, map.size)) == map.size) {
+ return 1; // hack
+ }
+ char *value = a;
+ a += len + 1;
+ map.size -= len + 1;
+ if (res_get_setfun(name)(entity, key, value)) {
+ return 1; // hack
+ }
+ }
+ } else {
+ while (1) { // hack
+ if ((len = strnlen(a, map.size)) == map.size) { // hack
+ return 1; // hack
+ } else if (len == 0) {
+ a++;
+ map.size--;
+ break;
+ }
+ a += len + 1;
+ map.size -= len + 1;
+ }
+ }
+ }
//memmem(map.data + tilemap->byte_count, map.size - tilemap->byte_count, (char []) {0, 0}, 2);
printf("load_tilemap %p\n", (void *) tilemap);
SDL_SetRenderTarget(renderer, NULL);
diff --git a/src/player.c b/src/player.c
index 9efd0ac..b23b2f0 100644
--- a/src/player.c
+++ b/src/player.c
@@ -1,5 +1,6 @@
#include "main.h"
#include "entity.h"
+#include "loader.h"
#include "input.h"
#include "tilemap.h"
#include <stdbool.h>
@@ -119,6 +120,7 @@ void anim(struct entity *self, unsigned anim) {
static int player_update(struct entity *self) {
if (self->hp <= 0) {
+ self->state = 0;
return 1;
}
switch (self->state) {