9 static int load_tileset(struct level *lvl, struct ts_node *tsn);
11 int init_level(struct level *lvl, int xsz, int ysz)
13 if(!(lvl->cells = calloc(xsz * ysz, sizeof *lvl->cells))) {
22 void destroy_level(struct level *lvl)
30 int load_level(struct level *lvl, const char *fname)
32 struct ts_node *ts, *node, *iter;
36 lvl->fname = strdup(fname);
37 if((lvl->dirname = malloc(strlen(fname) + 1))) {
38 path_dir(lvl->fname, lvl->dirname);
41 if(!(ts = ts_load(fname))) {
42 fprintf(stderr, "failed to load level: %s\n", fname);
45 if(strcmp(ts->name, "dunged_level") != 0) {
46 fprintf(stderr, "invalid or corrupted level file: %s\n", fname);
51 if((sz = ts_get_attr_int(ts, "size", 0)) <= 0) {
55 if(init_level(lvl, sz, sz) == -1) {
56 fprintf(stderr, "failed to initialize a %dx%d level\n", sz, sz);
61 iter = ts->child_list;
66 if(strcmp(node->name, "tileset") == 0) {
67 load_tileset(lvl, node);
69 } else if(strcmp(node->name, "cell") == 0) {
70 cx = ts_get_attr_int(node, "x", -1);
71 cy = ts_get_attr_int(node, "y", -1);
72 if(cx < 0 || cy < 0 || cx >= sz || cy >= sz) {
73 fprintf(stderr, "ignoring cell with invalid or missing coordinates\n");
76 cell = lvl->cells + cy * sz + cx;
77 cell->type = ts_get_attr_int(node, "blocked", 0) ? CELL_BLOCKED : CELL_WALK;
78 /* TODO wall tiles and detail objects */
86 /* TODO: save tileset info */
87 int save_level(struct level *lvl, const char *fname)
90 struct ts_node *root, *node;
94 if(!(root = ts_alloc_node()) || ts_set_node_name(root, "dunged_level") == -1) {
98 if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "size") == -1) {
102 ts_set_valuei(&attr->val, lvl->width);
103 ts_add_attr(root, attr);
105 for(i=0; i<lvl->height; i++) {
106 for(j=0; j<lvl->width; j++) {
107 cell = lvl->cells + i * lvl->width + j;
108 if(cell->type == CELL_SOLID) continue;
110 if(!(node = ts_alloc_node()) || ts_set_node_name(node, "cell") == -1) {
114 if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "x") == -1) {
118 ts_set_valuei(&attr->val, j);
119 ts_add_attr(node, attr);
120 if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "y") == -1) {
124 ts_set_valuei(&attr->val, i);
125 ts_add_attr(node, attr);
127 if(cell->type == CELL_BLOCKED) {
128 if(!(attr = ts_alloc_attr()) || ts_set_attr_name(attr, "blocked") == -1) {
132 ts_set_valuei(&attr->val, 1);
133 ts_add_attr(node, attr);
136 ts_add_child(root, node);
140 if(ts_save(root, fname) == -1) {
141 fprintf(stderr, "failed to save level: %s\n", fname);
149 fprintf(stderr, "failed to construct treestore tree\n");
154 static int load_tileset(struct level *lvl, struct ts_node *tsn)
156 static const char *tile_types[] = {"straight", "corner", "door", 0};
161 struct ts_node *node;
164 node = tsn->child_list;
166 if(strcmp(node->name, "tile") == 0) {
167 if(!(tile = calloc(1, sizeof *tile))) {
168 fprintf(stderr, "failed to allocate tile\n");
171 if((str = ts_get_attr_str(node, "name", 0))) {
172 tile->name = strdup(str);
174 if((str = ts_get_attr_str(node, "type", 0))) {
175 for(i=0; tile_types[i]; i++) {
176 if(strcmp(str, tile_types[i]) == 0) {
182 if((str = ts_get_attr_str(node, "scene", 0))) {
184 path = alloca(strlen(lvl->dirname) + strlen(str) + 2);
185 combine_path(lvl->dirname, str, path);
189 load_scenefile(&tile->scn, path);
192 if(tile->name && tile->scn.meshlist) { /* valid tile */
193 tile->next = lvl->tiles;
196 fprintf(stderr, "load_tileset: skipping invalid tile: %s\n",
197 tile->name ? tile->name : "missing tile name");