diff --git a/assets/map/map/0_0.json b/assets/map/map/0_0_0.json similarity index 100% rename from assets/map/map/0_0.json rename to assets/map/map/0_0_0.json diff --git a/src/asset/asset.c b/src/asset/asset.c index 1c8be10..68f126a 100644 --- a/src/asset/asset.c +++ b/src/asset/asset.c @@ -167,6 +167,14 @@ errorret_t assetInit(void) { errorOk(); } +bool_t assetFileExists(const char_t *filename) { + assertStrLenMax(filename, FILENAME_MAX, "Filename too long."); + + zip_int64_t idx = zip_name_locate(ASSET.zip, filename, 0); + if(idx < 0) return false; + return true; +} + errorret_t assetLoad(const char_t *filename, void *output) { assertStrLenMax(filename, FILENAME_MAX, "Filename too long."); assertNotNull(output, "Output pointer cannot be NULL."); diff --git a/src/asset/asset.h b/src/asset/asset.h index 6d6b8e0..c482053 100644 --- a/src/asset/asset.h +++ b/src/asset/asset.h @@ -69,6 +69,14 @@ static asset_t ASSET; */ errorret_t assetInit(void); +/** + * Checks if an asset file exists. + * + * @param filename The filename of the asset to check. + * @return true if the asset file exists, false otherwise. + */ +bool_t assetFileExists(const char_t *filename); + /** * Loads an asset by its filename, the output type depends on the asset type. * diff --git a/src/asset/type/assetchunk.c b/src/asset/type/assetchunk.c index 533446e..4be78ef 100644 --- a/src/asset/type/assetchunk.c +++ b/src/asset/type/assetchunk.c @@ -32,6 +32,12 @@ errorret_t assetChunkLoad(assetcustom_t custom) { assertNotNull(custom.zipFile, "Zip file pointer cannot be NULL"); chunk_t *chunk = (chunk_t *)custom.output; + printf( + "Loading chunk asset at position (%d, %d, %d)...\n", + chunk->position.x, + chunk->position.y, + chunk->position.z + ); // Read header assetchunkheader_t header; diff --git a/src/engine/engine.c b/src/engine/engine.c index 2bd7a51..f536d65 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -42,8 +42,8 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { errorret_t engineUpdate(void) { timeUpdate(); inputUpdate(); - - rpgUpdate(); + + errorChain(rpgUpdate()); uiUpdate(); sceneManagerUpdate(); errorChain(displayUpdate()); diff --git a/src/rpg/rpg.c b/src/rpg/rpg.c index b6ad820..1ad3c11 100644 --- a/src/rpg/rpg.c +++ b/src/rpg/rpg.c @@ -20,7 +20,7 @@ errorret_t rpgInit(void) { // Init cutscene subsystem cutsceneSystemInit(); - mapInit(); + errorChain(mapInit()); rpgCameraInit(); rpgTextboxInit(); @@ -41,9 +41,11 @@ errorret_t rpgInit(void) { errorOk(); } -void rpgUpdate(void) { +errorret_t rpgUpdate(void) { #if TIME_FIXED == 0 - if(TIME.dynamicUpdate) return; + if(TIME.dynamicUpdate) { + errorOk(); + } #endif // TODO: Do not update if the scene is not the map scene? @@ -57,9 +59,10 @@ void rpgUpdate(void) { } while(++ent < &ENTITIES[ENTITY_COUNT]); cutsceneSystemUpdate(); - rpgCameraUpdate(); + errorChain(rpgCameraUpdate()); + errorOk(); } void rpgDispose(void) { - + mapDispose(); } \ No newline at end of file diff --git a/src/rpg/rpg.h b/src/rpg/rpg.h index d9ee07c..7460dfb 100644 --- a/src/rpg/rpg.h +++ b/src/rpg/rpg.h @@ -21,8 +21,10 @@ errorret_t rpgInit(void); /** * Update the RPG subsystem. + * + * @return An error code. */ -void rpgUpdate(void); +errorret_t rpgUpdate(void); /** * Dispose of the RPG subsystem. diff --git a/src/rpg/rpgcamera.c b/src/rpg/rpgcamera.c index 18de59a..355cc13 100644 --- a/src/rpg/rpgcamera.c +++ b/src/rpg/rpgcamera.c @@ -17,7 +17,7 @@ void rpgCameraInit(void) { memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t)); } -void rpgCameraUpdate(void) { +errorret_t rpgCameraUpdate(void) { chunkpos_t chunkPos; switch(RPG_CAMERA.mode) { @@ -27,7 +27,9 @@ void rpgCameraUpdate(void) { case RPG_CAMERA_MODE_FOLLOW_ENTITY: { entity_t *entity = &ENTITIES[RPG_CAMERA.followEntity.followEntityId]; - if(entity->type == ENTITY_TYPE_NULL) return; + if(entity->type == ENTITY_TYPE_NULL) { + errorOk(); + } // Update map position to match camera. By default map wants to know the // top left but we want to set the center, so we need to sub half map size @@ -39,9 +41,10 @@ void rpgCameraUpdate(void) { assertUnreachable("Invalid RPG camera mode"); } - mapPositionSet((chunkpos_t){ + errorChain(mapPositionSet((chunkpos_t){ .x = chunkPos.x - (MAP_CHUNK_WIDTH / 2), .y = chunkPos.y - (MAP_CHUNK_HEIGHT / 2), .z = chunkPos.z - (MAP_CHUNK_DEPTH / 2) - }); + })); + errorOk(); } \ No newline at end of file diff --git a/src/rpg/rpgcamera.h b/src/rpg/rpgcamera.h index 4338d03..07cf991 100644 --- a/src/rpg/rpgcamera.h +++ b/src/rpg/rpgcamera.h @@ -7,6 +7,7 @@ #pragma once #include "rpg/world/worldpos.h" +#include "error/error.h" typedef enum { RPG_CAMERA_MODE_FREE, @@ -33,5 +34,7 @@ void rpgCameraInit(void); /** * Updates the RPG camera. + * + * @return An error code. */ -void rpgCameraUpdate(void); \ No newline at end of file +errorret_t rpgCameraUpdate(void); \ No newline at end of file diff --git a/src/rpg/world/map.c b/src/rpg/world/map.c index 5c2dbda..33f22e6 100644 --- a/src/rpg/world/map.c +++ b/src/rpg/world/map.c @@ -12,7 +12,7 @@ map_t MAP; -void mapInit() { +errorret_t mapInit() { memoryZero(&MAP, sizeof(map_t)); // Init the default chunks. In future I'll probably make this based on where @@ -26,16 +26,20 @@ void mapInit() { chunk->position.y = y; chunk->position.z = z; MAP.chunkOrder[index] = chunk; - mapChunkLoad(chunk); + errorChain(mapChunkLoad(chunk)); index++; } } } + + errorOk(); } -void mapPositionSet(const chunkpos_t newPos) { +errorret_t mapPositionSet(const chunkpos_t newPos) { const chunkpos_t curPos = MAP.chunkPosition; - if(chunkPositionIsEqual(curPos, newPos)) return; + if(chunkPositionIsEqual(curPos, newPos)) { + errorOk(); + } // Determine which chunks remain loaded chunkindex_t chunksRemaining[MAP_CHUNK_COUNT] = {0}; @@ -97,7 +101,7 @@ void mapPositionSet(const chunkpos_t newPos) { chunkIndex = chunksFreed[--freedCount]; chunk_t *chunk = &MAP.chunks[chunkIndex]; chunk->position = newChunkPos; - mapChunkLoad(chunk); + errorChain(mapChunkLoad(chunk)); } MAP.chunkOrder[orderIndex++] = &MAP.chunks[chunkIndex]; @@ -107,22 +111,44 @@ void mapPositionSet(const chunkpos_t newPos) { // Update map position MAP.chunkPosition = newPos; + + errorOk(); } void mapUpdate() { } +void mapDispose() { + for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { + mapChunkUnload(&MAP.chunks[i]); + } +} + void mapChunkUnload(chunk_t* chunk) { - printf("Unloading chunk at (%d, %d, %d)\n", + for(uint8_t i = 0; i < chunk->meshCount; i++) { + meshDispose(&chunk->meshes[i]); + } +} + +errorret_t mapChunkLoad(chunk_t* chunk) { + char_t buffer[64]; + + chunk->meshCount = 0; + + snprintf(buffer, sizeof(buffer), "map/map/%d_%d_%d.dcf", chunk->position.x, chunk->position.y, chunk->position.z ); -} -void mapChunkLoad(chunk_t* chunk) { - errorCatch(errorPrint(assetLoad("map/map/0_0.dcf", chunk))); + if(!assetFileExists(buffer)) { + memoryZero(chunk->tiles, sizeof(chunk->tiles)); + errorOk(); + } + + errorChain(assetLoad(buffer, chunk)); + errorOk(); } chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { diff --git a/src/rpg/world/map.h b/src/rpg/world/map.h index 6e1f33a..bb494e2 100644 --- a/src/rpg/world/map.h +++ b/src/rpg/world/map.h @@ -18,20 +18,28 @@ extern map_t MAP; /** * Initializes the map. + * + * @return An error code. */ -void mapInit(); +errorret_t mapInit(); /** * Updates the map. */ void mapUpdate(); +/** + * Disposes of the map. + */ +void mapDispose(); + /** * Sets the map position and updates chunks accordingly. * * @param newPos The new chunk position. + * @return An error code. */ -void mapPositionSet(const chunkpos_t newPos); +errorret_t mapPositionSet(const chunkpos_t newPos); /** * Unloads a chunk. @@ -44,8 +52,9 @@ void mapChunkUnload(chunk_t* chunk); * Loads a chunk. * * @param chunk The chunk to load. + * @return An error code. */ -void mapChunkLoad(chunk_t* chunk); +errorret_t mapChunkLoad(chunk_t* chunk); /** * Gets the index of a chunk, within the world, at the given position. diff --git a/tools/assetstool/processmap.py b/tools/assetstool/processmap.py index ff81202..e7b049f 100644 --- a/tools/assetstool/processmap.py +++ b/tools/assetstool/processmap.py @@ -14,16 +14,13 @@ TILE_WIDTH = 16.0 TILE_HEIGHT = 16.0 TILE_DEPTH = 11.36 -def createQuadForTile(tileIndex, x=0, y=0, z=0): +def processTile(tileIndex, x=0, y=0, z=0): vertices = [] indices = [] # Tile 0, nothing if tileIndex == 0: - return { - 'vertices': vertices, - 'indices': indices - } + return None # Determine color for checkerboard pattern color = (255,255,255) if (x + y) % 2 == 0 else (0,0,0) @@ -82,8 +79,8 @@ def processChunk(path): z = i // (CHUNK_WIDTH * CHUNK_HEIGHT) # Add tile 3D model - result = createQuadForTile(tile, x, y, z) - if len(result['vertices']) > 0: + result = processTile(tile, x, y, z) + if result is not None and len(result['vertices']) > 0: base = len(baseModel['vertices']) quad_indices = [base + idx for idx in result['indices']] baseModel['vertices'].extend(result['vertices'])