/** * Copyright (c) 2024 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "assetmap.h" #include "asset/asset.h" #include "assert/assert.h" #include "util/memory.h" void assetMapLoadEntity( assetjson_t *jEnt, map_t *map ) { int32_t x = (int32_t)assetJsonGetObjectValue(jEnt, "x")->number; int32_t y = (int32_t)assetJsonGetObjectValue(jEnt, "y")->number; entitytype_t type = (entitytype_t)assetJsonGetObjectValue( jEnt, "type" )->number; entity_t *ent = mapEntityAdd(map); entityInit(ent, type, map); entityPositionSet(ent, x, y); assetjson_t *val; switch(type) { case ENTITY_TYPE_NPC: val = assetJsonGetObjectValue(jEnt, "name"); if(val != NULL) { assertTrue( val->type == ASSET_JSON_DATA_TYPE_STRING, "assetMapLoad: NPC name is not a string!" ); npcNameSet(&ent->npc, val->string); } val = assetJsonGetObjectValue(jEnt, "text"); if(val != NULL) { assertTrue( val->type == ASSET_JSON_DATA_TYPE_STRING, "assetMapLoad: NPC text is not a string!" ); npcTextSet(&ent->npc, val->string); } break; case ENTITY_TYPE_SIGN: val = assetJsonGetObjectValue(jEnt, "text"); if(val != NULL) { assertTrue( val->type == ASSET_JSON_DATA_TYPE_STRING, "assetMapLoad: Sign text is not a string!" ); signTextAppend(&ent->sign, val->string); } val = assetJsonGetObjectValue(jEnt, "texts"); if(val != NULL) { assertTrue( val->type == ASSET_JSON_DATA_TYPE_ARRAY, "assetMapLoad: Sign texts is not an array!" ); assertTrue( val->array.length <= SIGN_TEXT_COUNT_MAX, "assetMapLoad: Too many sign texts!" ); for(int32_t i = 0; i < val->array.length; i++) { assetjson_t *subVal = val->array.value[i]; assertTrue( subVal->type == ASSET_JSON_DATA_TYPE_STRING, "assetMapLoad: Sign text is not a string!" ); signTextAppend(&ent->sign, subVal->string); } } break; case ENTITY_TYPE_DOOR: val = assetJsonGetObjectValue(jEnt, "door"); if(val != NULL) { assetjson_t *door = assetJsonGetObjectValue(val, "x"); x = (int32_t)door->number; assertTrue( door->type == ASSET_JSON_DATA_TYPE_NUMBER, "assetMapLoad: Door x is not a number!" ); door = assetJsonGetObjectValue(val, "y"); y = (int32_t)door->number; assertTrue( door->type == ASSET_JSON_DATA_TYPE_NUMBER, "assetMapLoad: Door y is not a number!" ); entitydirection_t direction = (entitydirection_t)( assetJsonGetObjectValue(val, "direction")->number ); door = assetJsonGetObjectValue(val, "map"); maplist_t list; if(door == NULL) { list = map->list; } else if(door->type == ASSET_JSON_DATA_TYPE_STRING) { list = mapListGet(door->string); } else if(door->type == ASSET_JSON_DATA_TYPE_NUMBER) { list = (maplist_t)door->number; } else { assertUnreachable("assetMapLoad: Door map not string or number!"); } doorDestinationSet(&ent->door, x, y, direction, list); } break; default: break; } } void assetMapLoad( const char_t *path, map_t *map ) { assertNotNull(map, "assetMapLoad: Map is NULL!"); // Read in the string data. assetOpen(path); size_t length = assetGetSize(); char_t *buffer = memoryAllocate(sizeof(char_t) * (length + 1)); size_t read = assetRead((uint8_t*)buffer, length); buffer[length] = '\0'; assertTrue(read == length, "assetMapLoad: Failed to read map data!"); assetClose(); // Begin parsing JSON data. assetjson_t *json; read = assetJsonParse(buffer, &json); memoryFree(buffer); assertTrue( json->type == ASSET_JSON_DATA_TYPE_OBJECT, "assetMapLoad: Map data is not an object!" ); int32_t width = (int32_t)assetJsonGetObjectValue(json, "width")->number; int32_t height = (int32_t)assetJsonGetObjectValue(json, "height")->number; assetjson_t *layers = assetJsonGetObjectValue(json, "layers"); assertTrue( layers->type == ASSET_JSON_DATA_TYPE_ARRAY, "assetMapLoad: Layers is not an array!" ); int32_t layerCount = layers->array.length; assertTrue(layerCount == MAP_LAYERS_MAX, "assetMapLoad: No layers found!"); mapInit(map, mapListGet(path), width, height, layerCount); // Load tile data. for(int32_t i = 0; i < layerCount; i++) { assetjson_t *layer = layers->array.value[i]; assertTrue( layer->type == ASSET_JSON_DATA_TYPE_OBJECT, "assetMapLoad: Layer is not an object!" ); assetjson_t *tiles = assetJsonGetObjectValue(layer, "tiles"); assertTrue( tiles->type == ASSET_JSON_DATA_TYPE_ARRAY, "assetMapLoad: Tiles is not an array!" ); assertTrue( tiles->array.length == width * height, "assetMapLoad: Tile count does not match map size!" ); for(int32_t j = 0; j < width * height; j++) { map->tiles[j] = (tile_t)tiles->array.value[j]->number; } } // Load entity data assetjson_t *entities = assetJsonGetObjectValue(json, "entities"); if(entities != NULL) { assertTrue( entities->type == ASSET_JSON_DATA_TYPE_ARRAY, "assetMapLoad: Entities is not an array!" ); for(int32_t i = 0; i < entities->array.length; i++) { assetjson_t *jEnt = entities->array.value[i]; assertTrue( jEnt->type == ASSET_JSON_DATA_TYPE_OBJECT, "assetMapLoad: Entity is not an object!" ); assetMapLoadEntity(jEnt, map); } } // Load trigger data assetjson_t *triggers = assetJsonGetObjectValue(json, "triggers"); if(triggers != NULL) { assertTrue( triggers->type == ASSET_JSON_DATA_TYPE_ARRAY, "assetMapLoad: Triggers is not an array!" ); for(int32_t i = 0; i < triggers->array.length; i++) { assetjson_t *jTrig = triggers->array.value[i]; assertTrue( jTrig->type == ASSET_JSON_DATA_TYPE_OBJECT, "assetMapLoad: Trigger is not an object!" ); int32_t x = (int32_t)assetJsonGetObjectValue(jTrig, "x")->number; int32_t y = (int32_t)assetJsonGetObjectValue(jTrig, "y")->number; int32_t width = (int32_t)assetJsonGetObjectValue(jTrig, "width")->number; int32_t height = (int32_t)assetJsonGetObjectValue( jTrig, "height" )->number; triggertype_t type = (triggertype_t)assetJsonGetObjectValue( jTrig, "type" )->number; trigger_t *trigger = mapTriggerAdd(map); triggerInit(trigger, type, x, y, width, height); } } assetJsonDispose(json); }