From 7940f4c487c1c299083a7fd4c67a445584825ac3 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 26 Dec 2025 15:01:43 +1000 Subject: [PATCH] Map refactoring to prep for loading --- assets/CMakeLists.txt | 8 ++- assets/{script => }/init.lua | 0 assets/{script => scene}/CMakeLists.txt | 2 +- assets/scene/map.lua | 1 + src/engine/engine.c | 2 +- src/rpg/rpgcamera.c | 2 + src/rpg/world/map.c | 65 +++++++++++++++++++++---- src/rpg/world/map.h | 22 +++++++++ src/scene/scene/scenemap.c | 4 ++ src/scene/scenemanager.c | 17 ++++++- src/script/module/modulescene.h | 1 - 11 files changed, 108 insertions(+), 16 deletions(-) rename assets/{script => }/init.lua (100%) rename assets/{script => scene}/CMakeLists.txt (83%) create mode 100644 assets/scene/map.lua diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index b7a735e..b2527f4 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -11,7 +11,11 @@ add_subdirectory(palette) # Languages need to be added before anything that uses text. add_subdirectory(locale) +# Rest, order doesn't matter +add_asset(SCRIPT init.lua) + +# Subdirs add_subdirectory(entity) -add_subdirectory(script) add_subdirectory(map) -add_subdirectory(ui) \ No newline at end of file +add_subdirectory(ui) +add_subdirectory(scene) \ No newline at end of file diff --git a/assets/script/init.lua b/assets/init.lua similarity index 100% rename from assets/script/init.lua rename to assets/init.lua diff --git a/assets/script/CMakeLists.txt b/assets/scene/CMakeLists.txt similarity index 83% rename from assets/script/CMakeLists.txt rename to assets/scene/CMakeLists.txt index 6042a69..9424ff4 100644 --- a/assets/script/CMakeLists.txt +++ b/assets/scene/CMakeLists.txt @@ -3,4 +3,4 @@ # This software is released under the MIT License. # https://opensource.org/licenses/MIT -add_asset(SCRIPT init.lua) \ No newline at end of file +add_asset(SCRIPT map.lua) \ No newline at end of file diff --git a/assets/scene/map.lua b/assets/scene/map.lua new file mode 100644 index 0000000..a4c5bff --- /dev/null +++ b/assets/scene/map.lua @@ -0,0 +1 @@ +print('map') \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index 46e4659..5d4514f 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -41,7 +41,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { // Run the initial script. scriptcontext_t ctx; errorChain(scriptContextInit(&ctx)); - errorChain(scriptContextExecFile(&ctx, "script/init.dsf")); + errorChain(scriptContextExecFile(&ctx, "init.dsf")); scriptContextDispose(&ctx); errorOk(); diff --git a/src/rpg/rpgcamera.c b/src/rpg/rpgcamera.c index 355cc13..0955506 100644 --- a/src/rpg/rpgcamera.c +++ b/src/rpg/rpgcamera.c @@ -18,6 +18,8 @@ void rpgCameraInit(void) { } errorret_t rpgCameraUpdate(void) { + if(!mapIsLoaded()) errorOk(); + chunkpos_t chunkPos; switch(RPG_CAMERA.mode) { diff --git a/src/rpg/world/map.c b/src/rpg/world/map.c index d0e4a99..dc45fa8 100644 --- a/src/rpg/world/map.c +++ b/src/rpg/world/map.c @@ -10,32 +10,66 @@ #include "assert/assert.h" #include "asset/asset.h" #include "rpg/entity/entity.h" +#include "util/string.h" map_t MAP; errorret_t mapInit() { memoryZero(&MAP, sizeof(map_t)); + errorOk(); +} + +bool_t mapIsLoaded() { + return MAP.filePath[0] != '\0'; +} + +errorret_t mapLoad(const char_t *path, const chunkpos_t position) { + assertStrLenMin(path, 1, "Map file path cannot be empty"); + assertStrLenMax(path, MAP_FILE_PATH_MAX - 1, "Map file path too long"); + + if(stringCompare(MAP.filePath, path) == 0) { + // Same map, no need to reload + errorOk(); + } + + chunkindex_t i; - // Init the first chunks. - chunkindex_t index = 0; + // Unload all loaded chunks + if(mapIsLoaded()) { + for(i = 0; i < MAP_CHUNK_COUNT; i++) { + mapChunkUnload(&MAP.chunks[i]); + } + } + + // Store the map file path + stringCopy(MAP.filePath, path, MAP_FILE_PATH_MAX); + + // Reset map position + MAP.chunkPosition = position; + + // Perform "initial load" + i = 0; for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) { for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) { for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) { - chunk_t *chunk = &MAP.chunks[index]; - chunk->position.x = x; - chunk->position.y = y; - chunk->position.z = z; - MAP.chunkOrder[index] = chunk; + chunk_t *chunk = &MAP.chunks[i]; + chunk->position.x = x + position.x; + chunk->position.y = y + position.y; + chunk->position.z = z + position.z; + MAP.chunkOrder[i] = chunk; errorChain(mapChunkLoad(chunk)); - index++; + i++; } } } + // Execute map script. errorOk(); } errorret_t mapPositionSet(const chunkpos_t newPos) { + if(!mapIsLoaded()) errorThrow("No map loaded"); + const chunkpos_t curPos = MAP.chunkPosition; if(chunkPositionIsEqual(curPos, newPos)) { errorOk(); @@ -131,6 +165,7 @@ void mapChunkUnload(chunk_t* chunk) { entity_t *entity = &ENTITIES[chunk->entities[i]]; entity->type = ENTITY_TYPE_NULL; } + for(uint8_t i = 0; i < chunk->meshCount; i++) { if(chunk->meshes[i].vertexCount == 0) continue; meshDispose(&chunk->meshes[i]); @@ -138,28 +173,37 @@ void mapChunkUnload(chunk_t* chunk) { } errorret_t mapChunkLoad(chunk_t* chunk) { + if(!mapIsLoaded()) errorThrow("No map loaded"); + char_t buffer[64]; + // TODO: Can probably move this to asset load logic? chunk->meshCount = 0; memoryZero(chunk->meshes, sizeof(chunk->meshes)); memorySet(chunk->entities, 0xFF, sizeof(chunk->entities)); - snprintf(buffer, sizeof(buffer), "map/map/%d_%d_%d.dcf", + // Get chunk filepath. + snprintf(buffer, sizeof(buffer), "%s/%d_%d_%d.dcf", + MAP.filePath, chunk->position.x, chunk->position.y, chunk->position.z ); + // Chunk available? if(!assetFileExists(buffer)) { memoryZero(chunk->tiles, sizeof(chunk->tiles)); errorOk(); } + // Load. errorChain(assetLoad(buffer, chunk)); errorOk(); } chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { + if(!mapIsLoaded()) return -1; + chunkpos_t relPos = { position.x - MAP.chunkPosition.x, position.y - MAP.chunkPosition.y, @@ -180,10 +224,13 @@ chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { chunk_t* mapGetChunk(const uint8_t index) { if(index >= MAP_CHUNK_COUNT) return NULL; + if(!mapIsLoaded()) return NULL; return MAP.chunkOrder[index]; } tile_t mapGetTile(const worldpos_t position) { + if(!mapIsLoaded()) return TILE_SHAPE_NULL; + chunkpos_t chunkPos; worldPosToChunkPos(&position, &chunkPos); chunkindex_t chunkIndex = mapGetChunkIndexAt(chunkPos); diff --git a/src/rpg/world/map.h b/src/rpg/world/map.h index bb494e2..f8e7730 100644 --- a/src/rpg/world/map.h +++ b/src/rpg/world/map.h @@ -8,7 +8,10 @@ #pragma once #include "rpg/world/chunk.h" +#define MAP_FILE_PATH_MAX 128 + typedef struct map_s { + char_t filePath[MAP_FILE_PATH_MAX]; chunk_t chunks[MAP_CHUNK_COUNT]; chunk_t *chunkOrder[MAP_CHUNK_COUNT]; chunkpos_t chunkPosition; @@ -23,6 +26,25 @@ extern map_t MAP; */ errorret_t mapInit(); +/** + * Checks if a map is loaded. + * + * @return true if a map is loaded, false otherwise. + */ +bool_t mapIsLoaded(); + +/** + * Loads a map from the given file path. + * + * @param path The file path. + * @param position The initial chunk position. + * @return An error code. + */ +errorret_t mapLoad( + const char_t *path, + const chunkpos_t position +); + /** * Updates the map. */ diff --git a/src/scene/scene/scenemap.c b/src/scene/scene/scenemap.c index 7d047e8..e1739a0 100644 --- a/src/scene/scene/scenemap.c +++ b/src/scene/scene/scenemap.c @@ -89,6 +89,8 @@ void sceneMapEntityGetPosition(const entity_t *entity, vec3 outPosition) { } void sceneMapRender(scenedata_t *data) { + if(!mapIsLoaded()) return; + // Look at target. vec3 cameraTarget; switch(RPG_CAMERA.mode) { @@ -166,6 +168,8 @@ void sceneMapRenderEntity(entity_t *entity) { } void sceneMapRenderMap() { + assertTrue(mapIsLoaded(), "No map loaded to render"); + // For each chunk. for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) { chunk_t *chunk = MAP.chunkOrder[i]; diff --git a/src/scene/scenemanager.c b/src/scene/scenemanager.c index bc011c0..aff10b3 100644 --- a/src/scene/scenemanager.c +++ b/src/scene/scenemanager.c @@ -10,6 +10,8 @@ #include "assert/assert.h" #include "display/framebuffer.h" #include "util/string.h" +#include "asset/asset.h" +#include "script/scriptmanager.h" scenemanager_t SCENE_MANAGER; @@ -60,9 +62,20 @@ errorret_t sceneManagerSetScene(scene_t *scene) { SCENE_MANAGER.current = scene; - if(scene && scene->init) { + if(scene && (scene->flags & SCENE_FLAG_INITIALIZED) == 0) { scene->flags |= SCENE_FLAG_INITIALIZED; - errorChain(scene->init(&SCENE_MANAGER.sceneData)); + + if(scene->init) errorChain(scene->init(&SCENE_MANAGER.sceneData)); + + // Execute scene script if it exists + char_t buffer[256]; + snprintf(buffer, sizeof(buffer), "scene/%s.dsf", scene->name); + if(assetFileExists(buffer)) { + scriptcontext_t ctx; + scriptContextInit(&ctx); + errorChain(scriptContextExecFile(&ctx, buffer)); + scriptContextDispose(&ctx); + } } errorOk(); diff --git a/src/script/module/modulescene.h b/src/script/module/modulescene.h index aabc2d5..d06c526 100644 --- a/src/script/module/modulescene.h +++ b/src/script/module/modulescene.h @@ -28,7 +28,6 @@ int32_t moduleSceneSetScene(lua_State *L) { errorret_t err = sceneManagerSetScene(scene); if(err.code != ERROR_OK) { - luaL_error(L, "Failed to set scene '%s'", sceneName); return 0; }