Map refactoring to prep for loading
Some checks failed
Build Dusk / build-linux (push) Successful in 1m35s
Build Dusk / build-psp (push) Failing after 1m46s

This commit is contained in:
2025-12-26 15:01:43 +10:00
parent b16dbaceec
commit 7940f4c487
11 changed files with 108 additions and 16 deletions

View File

@@ -11,7 +11,11 @@ add_subdirectory(palette)
# Languages need to be added before anything that uses text. # Languages need to be added before anything that uses text.
add_subdirectory(locale) add_subdirectory(locale)
# Rest, order doesn't matter
add_asset(SCRIPT init.lua)
# Subdirs
add_subdirectory(entity) add_subdirectory(entity)
add_subdirectory(script)
add_subdirectory(map) add_subdirectory(map)
add_subdirectory(ui) add_subdirectory(ui)
add_subdirectory(scene)

View File

@@ -3,4 +3,4 @@
# This software is released under the MIT License. # This software is released under the MIT License.
# https://opensource.org/licenses/MIT # https://opensource.org/licenses/MIT
add_asset(SCRIPT init.lua) add_asset(SCRIPT map.lua)

1
assets/scene/map.lua Normal file
View File

@@ -0,0 +1 @@
print('map')

View File

@@ -41,7 +41,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
// Run the initial script. // Run the initial script.
scriptcontext_t ctx; scriptcontext_t ctx;
errorChain(scriptContextInit(&ctx)); errorChain(scriptContextInit(&ctx));
errorChain(scriptContextExecFile(&ctx, "script/init.dsf")); errorChain(scriptContextExecFile(&ctx, "init.dsf"));
scriptContextDispose(&ctx); scriptContextDispose(&ctx);
errorOk(); errorOk();

View File

@@ -18,6 +18,8 @@ void rpgCameraInit(void) {
} }
errorret_t rpgCameraUpdate(void) { errorret_t rpgCameraUpdate(void) {
if(!mapIsLoaded()) errorOk();
chunkpos_t chunkPos; chunkpos_t chunkPos;
switch(RPG_CAMERA.mode) { switch(RPG_CAMERA.mode) {

View File

@@ -10,32 +10,66 @@
#include "assert/assert.h" #include "assert/assert.h"
#include "asset/asset.h" #include "asset/asset.h"
#include "rpg/entity/entity.h" #include "rpg/entity/entity.h"
#include "util/string.h"
map_t MAP; map_t MAP;
errorret_t mapInit() { errorret_t mapInit() {
memoryZero(&MAP, sizeof(map_t)); memoryZero(&MAP, sizeof(map_t));
errorOk();
}
// Init the first chunks. bool_t mapIsLoaded() {
chunkindex_t index = 0; 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;
// 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 z = 0; z < MAP_CHUNK_DEPTH; z++) {
for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) { for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) {
for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) { for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) {
chunk_t *chunk = &MAP.chunks[index]; chunk_t *chunk = &MAP.chunks[i];
chunk->position.x = x; chunk->position.x = x + position.x;
chunk->position.y = y; chunk->position.y = y + position.y;
chunk->position.z = z; chunk->position.z = z + position.z;
MAP.chunkOrder[index] = chunk; MAP.chunkOrder[i] = chunk;
errorChain(mapChunkLoad(chunk)); errorChain(mapChunkLoad(chunk));
index++; i++;
} }
} }
} }
// Execute map script.
errorOk(); errorOk();
} }
errorret_t mapPositionSet(const chunkpos_t newPos) { errorret_t mapPositionSet(const chunkpos_t newPos) {
if(!mapIsLoaded()) errorThrow("No map loaded");
const chunkpos_t curPos = MAP.chunkPosition; const chunkpos_t curPos = MAP.chunkPosition;
if(chunkPositionIsEqual(curPos, newPos)) { if(chunkPositionIsEqual(curPos, newPos)) {
errorOk(); errorOk();
@@ -131,6 +165,7 @@ void mapChunkUnload(chunk_t* chunk) {
entity_t *entity = &ENTITIES[chunk->entities[i]]; entity_t *entity = &ENTITIES[chunk->entities[i]];
entity->type = ENTITY_TYPE_NULL; entity->type = ENTITY_TYPE_NULL;
} }
for(uint8_t i = 0; i < chunk->meshCount; i++) { for(uint8_t i = 0; i < chunk->meshCount; i++) {
if(chunk->meshes[i].vertexCount == 0) continue; if(chunk->meshes[i].vertexCount == 0) continue;
meshDispose(&chunk->meshes[i]); meshDispose(&chunk->meshes[i]);
@@ -138,28 +173,37 @@ void mapChunkUnload(chunk_t* chunk) {
} }
errorret_t mapChunkLoad(chunk_t* chunk) { errorret_t mapChunkLoad(chunk_t* chunk) {
if(!mapIsLoaded()) errorThrow("No map loaded");
char_t buffer[64]; char_t buffer[64];
// TODO: Can probably move this to asset load logic?
chunk->meshCount = 0; chunk->meshCount = 0;
memoryZero(chunk->meshes, sizeof(chunk->meshes)); memoryZero(chunk->meshes, sizeof(chunk->meshes));
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities)); 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.x,
chunk->position.y, chunk->position.y,
chunk->position.z chunk->position.z
); );
// Chunk available?
if(!assetFileExists(buffer)) { if(!assetFileExists(buffer)) {
memoryZero(chunk->tiles, sizeof(chunk->tiles)); memoryZero(chunk->tiles, sizeof(chunk->tiles));
errorOk(); errorOk();
} }
// Load.
errorChain(assetLoad(buffer, chunk)); errorChain(assetLoad(buffer, chunk));
errorOk(); errorOk();
} }
chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) {
if(!mapIsLoaded()) return -1;
chunkpos_t relPos = { chunkpos_t relPos = {
position.x - MAP.chunkPosition.x, position.x - MAP.chunkPosition.x,
position.y - MAP.chunkPosition.y, position.y - MAP.chunkPosition.y,
@@ -180,10 +224,13 @@ chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) {
chunk_t* mapGetChunk(const uint8_t index) { chunk_t* mapGetChunk(const uint8_t index) {
if(index >= MAP_CHUNK_COUNT) return NULL; if(index >= MAP_CHUNK_COUNT) return NULL;
if(!mapIsLoaded()) return NULL;
return MAP.chunkOrder[index]; return MAP.chunkOrder[index];
} }
tile_t mapGetTile(const worldpos_t position) { tile_t mapGetTile(const worldpos_t position) {
if(!mapIsLoaded()) return TILE_SHAPE_NULL;
chunkpos_t chunkPos; chunkpos_t chunkPos;
worldPosToChunkPos(&position, &chunkPos); worldPosToChunkPos(&position, &chunkPos);
chunkindex_t chunkIndex = mapGetChunkIndexAt(chunkPos); chunkindex_t chunkIndex = mapGetChunkIndexAt(chunkPos);

View File

@@ -8,7 +8,10 @@
#pragma once #pragma once
#include "rpg/world/chunk.h" #include "rpg/world/chunk.h"
#define MAP_FILE_PATH_MAX 128
typedef struct map_s { typedef struct map_s {
char_t filePath[MAP_FILE_PATH_MAX];
chunk_t chunks[MAP_CHUNK_COUNT]; chunk_t chunks[MAP_CHUNK_COUNT];
chunk_t *chunkOrder[MAP_CHUNK_COUNT]; chunk_t *chunkOrder[MAP_CHUNK_COUNT];
chunkpos_t chunkPosition; chunkpos_t chunkPosition;
@@ -23,6 +26,25 @@ extern map_t MAP;
*/ */
errorret_t mapInit(); 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. * Updates the map.
*/ */

View File

@@ -89,6 +89,8 @@ void sceneMapEntityGetPosition(const entity_t *entity, vec3 outPosition) {
} }
void sceneMapRender(scenedata_t *data) { void sceneMapRender(scenedata_t *data) {
if(!mapIsLoaded()) return;
// Look at target. // Look at target.
vec3 cameraTarget; vec3 cameraTarget;
switch(RPG_CAMERA.mode) { switch(RPG_CAMERA.mode) {
@@ -166,6 +168,8 @@ void sceneMapRenderEntity(entity_t *entity) {
} }
void sceneMapRenderMap() { void sceneMapRenderMap() {
assertTrue(mapIsLoaded(), "No map loaded to render");
// For each chunk. // For each chunk.
for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) { for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) {
chunk_t *chunk = MAP.chunkOrder[i]; chunk_t *chunk = MAP.chunkOrder[i];

View File

@@ -10,6 +10,8 @@
#include "assert/assert.h" #include "assert/assert.h"
#include "display/framebuffer.h" #include "display/framebuffer.h"
#include "util/string.h" #include "util/string.h"
#include "asset/asset.h"
#include "script/scriptmanager.h"
scenemanager_t SCENE_MANAGER; scenemanager_t SCENE_MANAGER;
@@ -60,9 +62,20 @@ errorret_t sceneManagerSetScene(scene_t *scene) {
SCENE_MANAGER.current = scene; SCENE_MANAGER.current = scene;
if(scene && scene->init) { if(scene && (scene->flags & SCENE_FLAG_INITIALIZED) == 0) {
scene->flags |= SCENE_FLAG_INITIALIZED; 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(); errorOk();

View File

@@ -28,7 +28,6 @@ int32_t moduleSceneSetScene(lua_State *L) {
errorret_t err = sceneManagerSetScene(scene); errorret_t err = sceneManagerSetScene(scene);
if(err.code != ERROR_OK) { if(err.code != ERROR_OK) {
luaL_error(L, "Failed to set scene '%s'", sceneName); luaL_error(L, "Failed to set scene '%s'", sceneName);
return 0; return 0;
} }