230 lines
6.7 KiB
C
230 lines
6.7 KiB
C
/**
|
|
* 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);
|
|
} |