Reintroduce multiple maps: per-map chunk directories + map_t name/mapSetMap

Move chunk assets from a single flat assetsraw/chunks (and assets/chunks)
into per-map assetsraw/maps/<map>/chunks (assets/maps/<map>/chunks), so
terrain mesh/model output no longer collides across maps sharing chunk
coordinates. map_t gains a name[MAP_NAME_MAX] field plus mapSetMap()/
mapIsLoaded() (checks name[0] == '\0') in place of the old bool loaded
flag; mapInit() now just resets state and mapSetMap() does the chunk
grid load. Updated the chunk asset tool and the map editor's dev
server/client to match.
This commit is contained in:
2026-09-07 21:28:07 -05:00
parent b3623c84a5
commit db42bca44b
32 changed files with 125 additions and 47 deletions
+26 -9
View File
@@ -28,7 +28,25 @@ void mapChunkLoadingSlotClear(chunk_t *chunk) {
errorret_t mapInit() {
memoryZero(&MAP, sizeof(map_t));
MAP.loaded = true;
errorOk();
}
bool_t mapIsLoaded() {
return MAP.name[0] != '\0';
}
errorret_t mapSetMap(const char_t *map) {
assertNotNull(map, "mapSetMap: map name cannot be NULL");
assertStrLenMax(map, MAP_NAME_MAX, "Map name too long");
if(mapIsLoaded()) {
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
mapChunkUnload(&MAP.chunks[i]);
}
}
memoryZero(&MAP, sizeof(map_t));
stringCopy(MAP.name, map, MAP_NAME_MAX);
chunkindex_t i = 0;
for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) {
@@ -47,10 +65,6 @@ errorret_t mapInit() {
errorOk();
}
bool_t mapIsLoaded() {
return MAP.loaded;
}
errorret_t mapPositionSet(const chunkpos_t newPos) {
if(!mapIsLoaded()) errorThrow("No map loaded");
if(chunkPositionIsEqual(newPos, MAP.chunkPosition)) errorOk();
@@ -132,6 +146,7 @@ errorret_t mapDispose() {
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
mapChunkUnload(&MAP.chunks[i]);
}
MAP.name[0] = '\0';
errorOk();
}
@@ -203,10 +218,11 @@ errorret_t mapChunkLoad(chunk_t *chunk) {
chunk->meshCount = 0;
char_t name[64];
char_t name[MAP_FILE_PATH_MAX];
stringFormat(
name, sizeof(name),
"chunks/%d_%d_%d.dcf",
"maps/%s/chunks/%d_%d_%d.dcf",
MAP.name,
(int32_t)chunk->position.x,
(int32_t)chunk->position.y,
(int32_t)chunk->position.z
@@ -241,10 +257,11 @@ void mapChunkLoadNext() {
MAP.loadQueueCount--;
MAP.loadingChunks[slot] = chunk;
char_t name[64];
char_t name[MAP_FILE_PATH_MAX];
stringFormat(
name, sizeof(name),
"chunks/%d_%d_%d.dcf",
"maps/%s/chunks/%d_%d_%d.dcf",
MAP.name,
(int32_t)chunk->position.x,
(int32_t)chunk->position.y,
(int32_t)chunk->position.z
+21 -4
View File
@@ -12,12 +12,18 @@
#define MAP_FILE_PATH_MAX 128
// Buffer size for a map's name, including the null terminator - so map
// names are at most 9 characters.
#define MAP_NAME_MAX 10
// Number of chunks that may be mid-load (asset locked & awaiting onLoaded/
// onError) at the same time - everything past this waits in loadQueue.
#define MAP_CHUNK_LOAD_CONCURRENCY 2
typedef struct map_s {
bool_t loaded;
// Name of the currently loaded map, or an empty string if none is
// loaded (see mapIsLoaded).
char_t name[MAP_NAME_MAX];
chunk_t chunks[MAP_CHUNK_COUNT];
chunk_t *chunkOrder[MAP_CHUNK_COUNT];
@@ -31,19 +37,30 @@ typedef struct map_s {
extern map_t MAP;
/**
* Initializes the map.
*
* Initializes the map subsystem. No map is loaded until mapSetMap is
* called.
*
* @return An error code.
*/
errorret_t mapInit();
/**
* Checks if a map is loaded.
*
*
* @return true if a map is loaded, false otherwise.
*/
bool_t mapIsLoaded();
/**
* Sets the active map by name, unloading the previously loaded map (if
* any) first, then starts loading the new map's chunks around chunk
* position (0, 0, 0).
*
* @param map The map's name, at most MAP_NAME_MAX - 1 characters.
* @return An error code.
*/
errorret_t mapSetMap(const char_t *map);
/**
* Updates the map.
*
+1 -2
View File
@@ -31,10 +31,9 @@ errorret_t rpgInit(void) {
cutsceneSystemInit();
errorChain(mapInit());
rpgCameraInit();
// Init test world
errorChain(mapPositionSet((chunkpos_t){ 0, 0, 0 }));
errorChain(mapSetMap("overworld"));
// The player is the one entity that isn't sourced from map/chunk data -
// every other entity (NPCs, items) and map area comes from the loaded