diff --git a/SDL3_Core b/SDL3_Core index 946cc2e..405ed84 160000 --- a/SDL3_Core +++ b/SDL3_Core @@ -1 +1 @@ -Subproject commit 946cc2e4953cdbe5204adb5a5fe71650ba9542ca +Subproject commit 405ed84cae9b83eba540d7ee319f5ff025a314a1 diff --git a/assets/Makefile b/assets/Makefile index 6921842..cd28cfd 100644 --- a/assets/Makefile +++ b/assets/Makefile @@ -5,7 +5,8 @@ ASSETS := \ props_sheets/lever_sheet.png \ props_sheets/barred_door_sheet.png \ props_sheets/wooden_door_sheet.png \ - tileset/tileset.png + tileset/tileset.png \ + maps/dungeon_room_1.map ASSETS := $(addprefix $(ASSETS_DIR)/,$(ASSETS)) diff --git a/assets/asset_builder/README.md b/assets/asset_builder/README.md index e66d496..b138bcd 100644 --- a/assets/asset_builder/README.md +++ b/assets/asset_builder/README.md @@ -1,13 +1,13 @@ # Asset file structure -| Description | Length | -| :---------------- | :---------------------------------- | -| Assets number | unsigned int (32 bits) | -| ... | | -| Asset name | const char * (variable length) | -| Asset start index | unsigned int (32 bits) | -| ... | | -| Asset data | depend on assets content and number | +| Description | Length | +| :---------------- | :------------------------------------------------ | +| Assets number | unsigned int (32 bits) | +| ... | | +| Asset name | const char [] (variable length, ends with '\00') | +| Asset start index | unsigned int (32 bits) | +| ... | | +| Asset data | depend on assets content and number | ## Image (.png) @@ -32,21 +32,26 @@ Image data is in RGB 565. ### Maps asset data structure -| Description | Length | -| :-------------------------- | :-------------------------------------- | -| Map width | int (32 bits) | -| Map height | int (32 bits) | -| Map background layer 1 data | depend on map size, tile short (16 bit) | -| Map background layer 2 data | depend on map size, tile short (16 bit) | -| Map background layer 3 data | depend on map size, tile short (16 bit) | -| Map foreground layer data | depend on map size, tile short (16 bit) | -| Entities number | int (32 bits) | -| ... | | -| Entity ID | int (32 bits) | -| Entity component number | int (32 bits) | -| ... | | -| Component type | int (32 bits) | -| ... | | -| Component attributes | depend on attribute type | -| ... | | -| ... | | +| Description | Length | +| :-------------------------- | :------------------------------------------------ | +| Map width | unsigned int (32 bits) | +| Map height | unsigned int (32 bits) | +| Map background layer 1 data | depend on map size, tile short (16 bits) | +| Map background layer 2 data | depend on map size, tile short (16 bits) | +| Map background layer 3 data | depend on map size, tile short (16 bits) | +| Map foreground layer data | depend on map size, tile short (16 bits) | +| Map hitboxes data | depend on map size, tile unsigned char (8 bits) | +| Entities number | unsigned int (32 bits) | +| ... | | +| Entity ID | unsigned int (32 bits) | +| Entity components number | unsigned int (32 bits) | +| ... | | +| Component type | int (32 bits) | +| ... | | +| Component attributes | depend on attribute type | +| int | int (32 bits) | +| float | float (32 bits) | +| bool | bool (8 bits) | +| str | const char [] (variable length, ends with '\00') | +| ... | | +| ... | | diff --git a/assets/asset_builder/src/.ccls b/assets/asset_builder/src/.ccls index 7385139..767e25a 100644 --- a/assets/asset_builder/src/.ccls +++ b/assets/asset_builder/src/.ccls @@ -1,6 +1,7 @@ gcc # Headers -Iassets/asset_builder/src/headers +-Isrc/components/headers # Macros -DDEBUG=2 diff --git a/assets/asset_builder/src/Makefile b/assets/asset_builder/src/Makefile index f8ccf19..42375de 100644 --- a/assets/asset_builder/src/Makefile +++ b/assets/asset_builder/src/Makefile @@ -1,16 +1,18 @@ # Source files ASSET_BUILDER_SOURCES := \ asset_file.c \ + image.c \ + map.c \ main.c # Compiler and flags ASSET_BUILDER_CC = gcc ifeq ($(RELEASE), 1) -ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O3 $(shell pkg-config --cflags libpng) # RELEASE +ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O3 $(shell pkg-config --cflags libpng json-c) # RELEASE else -ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O1 -g $(shell pkg-config --cflags libpng) \ +ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O1 -DDEBUG=1 -g $(shell pkg-config --cflags libpng json-c) \ -Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \ - -Wformat=2 -Wswitch-default -Wswitch-enum -Wcast-align \ + -Wformat=2 -Wswitch-default -Wswitch -Wcast-align \ -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \ -Wstrict-prototypes -Winline -Wundef -Wnested-externs \ -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \ @@ -18,10 +20,10 @@ ASSET_BUILDER_CFLAGS = --std=c17 --pedantic -O1 -g $(shell pkg-config --cflags l -Wold-style-definition # DEVELOPEMENT endif -ASSET_BUILDER_INCLUDE_DIRS = $(ASSET_BUILDER_DIR)/headers +ASSET_BUILDER_INCLUDE_DIRS = $(ASSET_BUILDER_DIR)/headers $(SOURCE_DIR)/components/headers ASSET_BUILDER_INCLUDE_DIRS := $(addprefix -I, $(ASSET_BUILDER_INCLUDE_DIRS)) -ASSET_BUILDER_LDFLAGS = $(shell pkg-config --libs libpng) +ASSET_BUILDER_LDFLAGS = $(shell pkg-config --libs libpng json-c) # Deduce objects ASSET_BUILDER_OBJECTS = $(ASSET_BUILDER_SOURCES:%.c=$(BUILD_DIR)/$(ASSET_BUILDER_DIR)/%.o) diff --git a/assets/asset_builder/src/asset_file.c b/assets/asset_builder/src/asset_file.c index 2f67cda..7e2e0f1 100644 --- a/assets/asset_builder/src/asset_file.c +++ b/assets/asset_builder/src/asset_file.c @@ -1,14 +1,11 @@ #include "asset_file.h" -#include #include #include -#include +#include "image.h" +#include "map.h" #include "errors.h" -int parse_png_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); -int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file); - int parse_file_for_header(const char *input_file_name, asset_header_def_t *asset_header_def) { const char *file_name_dot = strrchr(input_file_name, '.'); @@ -25,6 +22,10 @@ int parse_file_for_header(const char *input_file_name, asset_header_def_t *asset { if(parse_png_for_header(input_file_name, asset_header_def)) return_failure_int; } + else if(!strcmp(file_name_ext, "map")) + { + if(parse_map_for_header(input_file_name, asset_header_def)) return_failure_int; + } else { error_printf("Extension unsupported : %s", file_name_dot); @@ -77,6 +78,10 @@ int parse_file_for_content_and_write(const char *input_file_name, FILE *output_f { if(parse_png_for_content_and_write(input_file_name, output_file)) return_failure_int; } + else if(!strcmp(file_name_ext, "map")) + { + if(parse_map_for_content_and_write(input_file_name, output_file)) return_failure_int; + } else { error_printf("Extension unsupported : %s", file_name_dot); @@ -85,213 +90,3 @@ int parse_file_for_content_and_write(const char *input_file_name, FILE *output_f return EXIT_SUCCESS; } - -// File specific functions. -int parse_png_for_header(const char *file_name, asset_header_def_t *asset_header_def) -{ - FILE *input_file = fopen(file_name, "rb"); - - if(!input_file) - { - error_printf("Failed to open input file."); - return EXIT_FAILURE; - } - - // Check png autenticity. - unsigned char sig[8]; - if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) - { - fclose(input_file); - error_printf("Failed to read input file."); - return EXIT_FAILURE; - } - - if(!png_check_sig(sig, 8)) - { - fclose(input_file); - error_printf("Png file is not valid."); - return EXIT_FAILURE; - } - - // PNG structs. - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if(!png_ptr) - { - fclose(input_file); - error_printf("Failed to allocate png ptr."); - return EXIT_FAILURE; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - fclose(input_file); - error_printf("Failed to allocate png info."); - return EXIT_FAILURE; - } - - // Fill structs and load data. - png_init_io(png_ptr, input_file); - png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); - - uint32_t width = png_get_image_width(png_ptr, info_ptr); - uint32_t height = png_get_image_height(png_ptr, info_ptr); - uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); - uint8_t color_type = png_get_color_type(png_ptr, info_ptr); - - // Verify png attributes. - if(bit_depth != 8) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Png bit depth not supported."); - return EXIT_FAILURE; - } - - switch(color_type) - { - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - break; - - default: - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Png color type not supported."); - return EXIT_FAILURE; - } - - // Fill asset def. - asset_header_def->start = 0; - asset_header_def->end = sizeof(int) * 2 + height * width * sizeof(uint16_t); - - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - - return EXIT_SUCCESS; -} - -int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file) -{ - FILE *input_file = fopen(input_file_name, "rb"); - - if(!input_file) - { - error_printf("Failed to open input file."); - return EXIT_FAILURE; - } - - // Check png autenticity. - unsigned char sig[8]; - if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) - { - fclose(input_file); - error_printf("Failed to read input file."); - return EXIT_FAILURE; - } - - if(!png_check_sig(sig, 8)) - { - fclose(input_file); - error_printf("Png file is not valid."); - return EXIT_FAILURE; - } - - // PNG structs. - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if(!png_ptr) - { - fclose(input_file); - error_printf("Failed to allocate png ptr."); - return EXIT_FAILURE; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - fclose(input_file); - error_printf("Failed to allocate png info."); - return EXIT_FAILURE; - } - - // Fill structs and load data. - png_init_io(png_ptr, input_file); - png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); - - uint32_t width = png_get_image_width(png_ptr, info_ptr); - uint32_t height = png_get_image_height(png_ptr, info_ptr); - size_t row_length = png_get_rowbytes(png_ptr, info_ptr); - - // Write image size. - if(fwrite(&width, sizeof(width), 1, output_file) != 1) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - - if(fwrite(&height, sizeof(height), 1, output_file) != 1) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - - // Prepare storage. - png_byte src_pixels[height * row_length]; - png_bytep src_row_ptrs[height]; - for(png_uint_32 i = 0; i < height; i++) - src_row_ptrs[i] = &src_pixels[i * row_length]; - - // Read pixels. - png_read_image(png_ptr, src_row_ptrs); - - uint16_t dst_pixels[width * height * sizeof(uint16_t)]; - - for(uint32_t i = 0; i < height; i++) - { - for(uint32_t j = 0; j < width; j += 1) - { - uint8_t r, g, b; - - if(src_pixels[i * row_length + j * 4 + 3]) - { - r = src_pixels[i * row_length + j * 4] >> 3; - g = src_pixels[i * row_length + j * 4 + 1] >> 2; - b = src_pixels[i * row_length + j * 4 + 2] >> 3; - } - else - { - r = 0x1F; - g = 0x00; - b = 0x1F; - } - - uint16_t pixel = ((r) << 11) | ((g) << 5) | b; - - dst_pixels[i * width + j] = pixel; - -// printf("\033[48;2;%d;%d;%dm ", r << 3, g << 2, b << 3); - } -// puts("\033[m"); - } - - if(fwrite(&dst_pixels, sizeof(uint16_t), width * height, output_file) != width * height) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - error_printf("Failed to write to output file : %d", errno); - return EXIT_FAILURE; - } - - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(input_file); - - return EXIT_SUCCESS; -} diff --git a/assets/asset_builder/src/headers/image.h b/assets/asset_builder/src/headers/image.h new file mode 100644 index 0000000..477dc9b --- /dev/null +++ b/assets/asset_builder/src/headers/image.h @@ -0,0 +1,9 @@ +#ifndef IMAGE_H +#define IMAGE_H + +#include "asset_file.h" + +int parse_png_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); +int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file); + +#endif // IMAGE_H \ No newline at end of file diff --git a/assets/asset_builder/src/headers/map.h b/assets/asset_builder/src/headers/map.h new file mode 100644 index 0000000..e940b13 --- /dev/null +++ b/assets/asset_builder/src/headers/map.h @@ -0,0 +1,9 @@ +#ifndef MAP_H +#define MAP_H + +#include "asset_file.h" + +int parse_map_for_header(const char *input_file_name, asset_header_def_t *asset_header_def); +int parse_map_for_content_and_write(const char *input_file_name, FILE *output_file); + +#endif // MAP_H \ No newline at end of file diff --git a/assets/asset_builder/src/image.c b/assets/asset_builder/src/image.c new file mode 100644 index 0000000..2f85a51 --- /dev/null +++ b/assets/asset_builder/src/image.c @@ -0,0 +1,215 @@ +#include "image.h" + +#include +#include +#include "asset_file.h" +#include "errors.h" + +int parse_png_for_header(const char *file_name, asset_header_def_t *asset_header_def) +{ + FILE *input_file = fopen(file_name, "rb"); + + if(!input_file) + { + error_printf("Failed to open input file."); + return EXIT_FAILURE; + } + + // Check png autenticity. + unsigned char sig[8]; + if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) + { + fclose(input_file); + error_printf("Failed to read input file."); + return EXIT_FAILURE; + } + + if(!png_check_sig(sig, 8)) + { + fclose(input_file); + error_printf("Png file is not valid."); + return EXIT_FAILURE; + } + + // PNG structs. + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if(!png_ptr) + { + fclose(input_file); + error_printf("Failed to allocate png ptr."); + return EXIT_FAILURE; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if(!info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + fclose(input_file); + error_printf("Failed to allocate png info."); + return EXIT_FAILURE; + } + + // Fill structs and load data. + png_init_io(png_ptr, input_file); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + uint32_t width = png_get_image_width(png_ptr, info_ptr); + uint32_t height = png_get_image_height(png_ptr, info_ptr); + uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); + uint8_t color_type = png_get_color_type(png_ptr, info_ptr); + + // Verify png attributes. + if(bit_depth != 8) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + error_printf("Png bit depth not supported."); + return EXIT_FAILURE; + } + + switch(color_type) + { + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + break; + + default: + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + error_printf("Png color type not supported."); + return EXIT_FAILURE; + } + + // Fill asset def. + asset_header_def->start = 0; + asset_header_def->end = sizeof(width) + sizeof(height) + height * width * sizeof(uint16_t); + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + + return EXIT_SUCCESS; +} + +int parse_png_for_content_and_write(const char *input_file_name, FILE *output_file) +{ + FILE *input_file = fopen(input_file_name, "rb"); + + if(!input_file) + { + error_printf("Failed to open input file."); + return EXIT_FAILURE; + } + + // Check png autenticity. + unsigned char sig[8]; + if(fread(sig, sizeof(unsigned char), 8, input_file) != 8) + { + fclose(input_file); + error_printf("Failed to read input file."); + return EXIT_FAILURE; + } + + if(!png_check_sig(sig, 8)) + { + fclose(input_file); + error_printf("Png file is not valid."); + return EXIT_FAILURE; + } + + // PNG structs. + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if(!png_ptr) + { + fclose(input_file); + error_printf("Failed to allocate png ptr."); + return EXIT_FAILURE; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if(!info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + fclose(input_file); + error_printf("Failed to allocate png info."); + return EXIT_FAILURE; + } + + // Fill structs and load data. + png_init_io(png_ptr, input_file); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + uint32_t width = png_get_image_width(png_ptr, info_ptr); + uint32_t height = png_get_image_height(png_ptr, info_ptr); + size_t row_length = png_get_rowbytes(png_ptr, info_ptr); + + // Write image size. + if(fwrite(&width, sizeof(width), 1, output_file) != 1) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + if(fwrite(&height, sizeof(height), 1, output_file) != 1) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + // Prepare storage. + png_byte src_pixels[height * row_length]; + png_bytep src_row_ptrs[height]; + for(png_uint_32 i = 0; i < height; i++) + src_row_ptrs[i] = &src_pixels[i * row_length]; + + // Read pixels. + png_read_image(png_ptr, src_row_ptrs); + + uint16_t dst_pixels[width * height * sizeof(uint16_t)]; + + for(uint32_t i = 0; i < height; i++) + { + for(uint32_t j = 0; j < width; j += 1) + { + uint8_t r, g, b; + + if(src_pixels[i * row_length + j * 4 + 3]) + { + r = src_pixels[i * row_length + j * 4] >> 3; + g = src_pixels[i * row_length + j * 4 + 1] >> 2; + b = src_pixels[i * row_length + j * 4 + 2] >> 3; + } + else + { + r = 0x1F; + g = 0x00; + b = 0x1F; + } + + uint16_t pixel = ((r) << 11) | ((g) << 5) | b; + + dst_pixels[i * width + j] = pixel; + +// printf("\033[48;2;%d;%d;%dm ", r << 3, g << 2, b << 3); + } +// puts("\033[m"); + } + + if(fwrite(&dst_pixels, sizeof(uint16_t), width * height, output_file) != width * height) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(input_file); + + return EXIT_SUCCESS; +} diff --git a/assets/asset_builder/src/main.c b/assets/asset_builder/src/main.c index e166891..920fa83 100644 --- a/assets/asset_builder/src/main.c +++ b/assets/asset_builder/src/main.c @@ -21,12 +21,11 @@ int main(int argc, char *argv[]) asset_file_header_t asset_file_header; asset_file_header.assets_number = argc - 2; asset_file_header.header_size = sizeof(asset_file_header.assets_number) + sizeof(uint32_t) * asset_file_header.assets_number; - asset_file_header.assets_header_def = malloc(asset_file_header.assets_number * sizeof(asset_header_def_t)); + asset_file_header.assets_header_def = calloc(asset_file_header.assets_number, sizeof(asset_header_def_t)); if(!asset_file_header.assets_header_def) { error_printf("Failed to allocate memory."); goto end; - } // Set assets name. diff --git a/assets/asset_builder/src/map.c b/assets/asset_builder/src/map.c new file mode 100644 index 0000000..e7b3d60 --- /dev/null +++ b/assets/asset_builder/src/map.c @@ -0,0 +1,536 @@ +#include "map.h" + +#include +#include +#include +#include +#include "asset_file.h" +#include "errors.h" + +int parse_map_for_header(const char *input_file_name, asset_header_def_t *asset_header_def) +{ + json_object *root = json_object_from_file(input_file_name); + if (!root) + { + error_printf("Failed to load input file."); + return EXIT_FAILURE; + } + + if(json_object_object_length(root) != 8) + { + json_object_put(root); + error_printf("Map file doesn't contain 8 elements at its root."); + return EXIT_FAILURE; + } + + json_object *tmp_obj; + + if(!json_object_object_get_ex(root, "MapWidth", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"MapWidth\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_int)) + { + error_printf("Map key \"MapWidth\" is not of type int."); + return EXIT_FAILURE; + } + + int map_width = json_object_get_int(tmp_obj); + + if(!json_object_object_get_ex(root, "MapHeight", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"MapHeight\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_int)) + { + error_printf("Map key \"MapHeight\" is not of type int."); + return EXIT_FAILURE; + } + + int map_height = json_object_get_int(tmp_obj); + + json_object *entities; + + if(!json_object_object_get_ex(root, "Entities", &entities)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"Entities\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(entities, json_type_array)) + { + json_object_put(root); + error_printf("Map object \"Entities\" is not an array."); + return EXIT_FAILURE; + } + + uint32_t entities_nb = json_object_array_length(entities); + + asset_header_def->start = 0; + asset_header_def->end = sizeof(map_width) + sizeof(map_height) + + map_width * map_height * sizeof(uint16_t) * 4 + + map_width * map_height * sizeof(uint8_t) + + sizeof(entities_nb); + + for(uint32_t i = 0; i < entities_nb; i++) + { + json_object *entity = json_object_array_get_idx(entities, i); + + if(!json_object_is_type(entity, json_type_object)) + { + error_printf("Map entity is not of type object."); + return EXIT_FAILURE; + } + + asset_header_def->end += sizeof(uint32_t); + + json_object *components; + + if(!json_object_object_get_ex(entity, "Components", &components)) + { + error_printf("Entity doesn't have key \"Components\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(components, json_type_array)) + { + error_printf("Component is not of type array."); + return EXIT_FAILURE; + } + + uint32_t components_nb = json_object_array_length(components); + + asset_header_def->end += sizeof(components_nb); + + for(uint32_t j = 0; j < components_nb; j++) + { + json_object *component = json_object_array_get_idx(components, j); + + if(!json_object_is_type(component, json_type_object)) + { + error_printf("Entity component is not of type object."); + return EXIT_FAILURE; + } + + asset_header_def->end += sizeof(uint32_t); + + json_object *attributes; + + if(!json_object_object_get_ex(component, "Attributes", &attributes)) + { + error_printf("Component doesn't have key \"Attributes\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(attributes, json_type_array)) + { + error_printf("Attributes is not of type array."); + return EXIT_FAILURE; + } + + uint32_t attributes_nb = json_object_array_length(attributes); + + for(uint32_t k = 0; k < attributes_nb; k++) + { + json_object *attribute = json_object_array_get_idx(attributes, k); + + switch(json_object_get_type(attribute)) + { + case json_type_int: + asset_header_def->end += sizeof(uint32_t); + break; + + case json_type_double: + asset_header_def->end += sizeof(float); + break; + + case json_type_boolean: + asset_header_def->end += sizeof(bool); + break; + + case json_type_string: + asset_header_def->end += json_object_get_string_len(attribute) + 1; + break; + + default: + error_printf("Attribute type is not supported : %s", json_type_to_name(json_object_get_type(attribute))); + return EXIT_FAILURE; + } + } + } + } + + json_object_put(root); + + return EXIT_SUCCESS; +} + +typedef enum component_type_t { +#define COMPONENT(NAME, ...) NAME, +#include "components.def" +} component_type_t; + +int parse_map_for_content_and_write(const char *input_file_name, FILE *output_file) +{ + json_object *root = json_object_from_file(input_file_name); + if (!root) + { + error_printf("Failed to load input file."); + return EXIT_FAILURE; + } + + json_object *tmp_obj; + + if(!json_object_object_get_ex(root, "MapWidth", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"MapWidth\"."); + return EXIT_FAILURE; + } + + int map_width = json_object_get_int(tmp_obj); + + if(fwrite(&map_width, sizeof(map_width), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + if(!json_object_object_get_ex(root, "MapHeight", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"MapHeight\"."); + return EXIT_FAILURE; + } + + int map_height = json_object_get_int(tmp_obj); + + if(fwrite(&map_height, sizeof(map_height), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + // Background Layer 1 + if(!json_object_object_get_ex(root, "BackgroundLayer1", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"BackgroundLayer1\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_array)) + { + json_object_put(root); + error_printf("Map background layer 1 is not of type array."); + return EXIT_FAILURE; + } + + uint16_t layer_data[map_width * map_height]; + + for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) + { + json_object *tile = json_object_array_get_idx(tmp_obj, i); + layer_data[i] = json_object_get_int(tile); + } + + if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + // Background Layer 2 + if(!json_object_object_get_ex(root, "BackgroundLayer2", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"BackgroundLayer2\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_array)) + { + json_object_put(root); + error_printf("Map background layer 1 is not of type array."); + return EXIT_FAILURE; + } + + for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) + { + json_object *tile = json_object_array_get_idx(tmp_obj, i); + layer_data[i] = json_object_get_int(tile); + } + + if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + // Background Layer 3 + if(!json_object_object_get_ex(root, "BackgroundLayer3", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"BackgroundLayer3\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_array)) + { + json_object_put(root); + error_printf("Map background layer 1 is not of type array."); + return EXIT_FAILURE; + } + + for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) + { + json_object *tile = json_object_array_get_idx(tmp_obj, i); + layer_data[i] = json_object_get_int(tile); + } + + if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + // Foreground + if(!json_object_object_get_ex(root, "Foreground", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"Foreground\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_array)) + { + json_object_put(root); + error_printf("Map background layer 1 is not of type array."); + return EXIT_FAILURE; + } + + for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) + { + json_object *tile = json_object_array_get_idx(tmp_obj, i); + layer_data[i] = json_object_get_int(tile); + } + + if(fwrite(&layer_data, sizeof(uint16_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + // Hitboxes + if(!json_object_object_get_ex(root, "Hitboxes", &tmp_obj)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"Hitboxes\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_array)) + { + json_object_put(root); + error_printf("Map background layer 1 is not of type array."); + return EXIT_FAILURE; + } + + uint8_t hitboxes_layer[map_width * map_height]; + + for(size_t i = 0; i < (size_t)map_width * (size_t)map_height; i++) + { + json_object *tile = json_object_array_get_idx(tmp_obj, i); + hitboxes_layer[i] = json_object_get_int(tile); + } + + if(fwrite(&hitboxes_layer, sizeof(uint8_t), map_width * map_height, output_file) != (size_t)map_width * (size_t)map_height) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + json_object *entities; + + if(!json_object_object_get_ex(root, "Entities", &entities)) + { + json_object_put(root); + error_printf("Map file doesn't contain key \"Entities\"."); + return EXIT_FAILURE; + } + + uint32_t entities_nb = json_object_array_length(entities); + + if(fwrite(&entities_nb, sizeof(entities_nb), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + for(uint32_t i = 0; i < entities_nb; i++) + { + json_object *entity = json_object_array_get_idx(entities, i); + + if(!json_object_object_get_ex(entity, "ID", &tmp_obj)) + { + json_object_put(root); + error_printf("Entity doesn't have key \"ID\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_int)) + { + json_object_put(root); + error_printf("Entity ID is not of type int."); + return EXIT_FAILURE; + } + + uint32_t entity_id = json_object_get_int(tmp_obj); + + if(fwrite(&entity_id, sizeof(entity_id), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + json_object *components; + + if(!json_object_object_get_ex(entity, "Components", &components)) + { + json_object_put(root); + error_printf("Entity doesn't have key \"Components\"."); + return EXIT_FAILURE; + } + + uint32_t components_nb = json_object_array_length(components); + + if(fwrite(&components_nb, sizeof(components_nb), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + for(uint32_t j = 0; j < components_nb; j++) + { + json_object *component = json_object_array_get_idx(components, j); + + json_object *attributes; + + if(!json_object_object_get_ex(component, "Type", &tmp_obj)) + { + json_object_put(root); + error_printf("Component doesn't have key \"Type\"."); + return EXIT_FAILURE; + } + + if(!json_object_is_type(tmp_obj, json_type_string)) + { + json_object_put(root); + error_printf("Component type is not of type string."); + return EXIT_FAILURE; + } + + component_type_t component_type; +#define COMPONENT(NAME, ...) \ + if(!strcmp(#NAME, json_object_get_string(tmp_obj))) \ + component_type = NAME; +#include "components.def" + + if(fwrite(&component_type, sizeof(uint32_t), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + + if(!json_object_object_get_ex(component, "Attributes", &attributes)) + { + json_object_put(root); + error_printf("Component doesn't have key \"Attributes\"."); + return EXIT_FAILURE; + } + + uint32_t attributes_nb = json_object_array_length(attributes); + + for(uint32_t k = 0; k < attributes_nb; k++) + { + json_object *attribute = json_object_array_get_idx(attributes, k); + + switch(json_object_get_type(attribute)) + { + case json_type_int: + { + int value = json_object_get_int(attribute); + if(fwrite(&value, sizeof(value), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + break; + } + + case json_type_double: + { + float value = json_object_get_double(attribute); + if(fwrite(&value, sizeof(value), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + break; + } + + case json_type_boolean: + { + bool value = json_object_get_boolean(attribute); + if(fwrite(&value, sizeof(value), 1, output_file) != 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + break; + } + + case json_type_string: + { + const char *str = json_object_get_string(attribute); + if(fwrite(str, sizeof(char), strlen(str) + 1, output_file) != strlen(str) + 1) + { + json_object_put(root); + error_printf("Failed to write to output file : %d", errno); + return EXIT_FAILURE; + } + break; + } + + default: + return EXIT_FAILURE; + } + } + } + } + + json_object_put(root); + + return EXIT_SUCCESS; +} diff --git a/assets/maps/dungeon_room_1.map b/assets/maps/dungeon_room_1.map index c7d7bef..466b7ed 100644 --- a/assets/maps/dungeon_room_1.map +++ b/assets/maps/dungeon_room_1.map @@ -134,7 +134,7 @@ { "Type": "DOOR_COMPONENT", "Attributes": [ - "0", + 0, false ] } diff --git a/assets/maps/dungeon_room_1.tmx b/assets/maps/dungeon_room_1.tmx index d9b0fa0..7cdc359 100644 --- a/assets/maps/dungeon_room_1.tmx +++ b/assets/maps/dungeon_room_1.tmx @@ -131,7 +131,7 @@ - + diff --git a/shell.nix b/shell.nix index 5b890f5..f10305f 100644 --- a/shell.nix +++ b/shell.nix @@ -10,6 +10,7 @@ stdenv.mkDerivation { ]; buildInputs = [ libpng + json_c sdl3 ncurses ]; diff --git a/src/Makefile b/src/Makefile index 52a6ecc..2da5858 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ SRC_LDFLAGS = -O3 else SRC_CFLAGS = --std=c17 --pedantic -O1 -g -DDEBUG=2 \ -Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \ - -Wformat=2 -Wswitch-default -Wswitch-enum -Wcast-align \ + -Wformat=2 -Wswitch-default -Wswitch -Wcast-align \ -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \ -Wstrict-prototypes -Winline -Wundef -Wnested-externs \ -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \