Map loading
All checks were successful
Build Dusk / run-tests (push) Successful in 1m15s
Build Dusk / build-linux (push) Successful in 1m33s
Build Dusk / build-psp (push) Successful in 1m56s

This commit is contained in:
2026-02-03 19:20:50 -06:00
parent 13dba8b604
commit 5cea284906
25 changed files with 415 additions and 120 deletions

View File

@@ -209,7 +209,7 @@ errorret_t mapChunkLoad(chunk_t* chunk) {
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
// Get chunk filepath.
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dcf",
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dmc",
MAP.dirPath,
chunk->position.x,
chunk->position.y,

View File

@@ -38,5 +38,4 @@ else
end
localeSet(DUSK_LOCALE_EN_US)
sceneSet('scene/initial.dsf')
-- mapLoad('map/testmap/testmap.dmf')
sceneSet('scene/initial.dsf')

View File

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

View File

@@ -1 +0,0 @@
print('Test Map Script Run')

View File

@@ -5,10 +5,15 @@ module('color')
module('text')
module('screen')
module('time')
module('map')
module('glm')
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
text = "Hello World"
screenSetBackground(colorBlack())
mapLoad('map/testmap/testmap.dmf')
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
mapCamera = cameraCreate()
text = "Hello World"
function sceneDispose()
end
@@ -17,19 +22,23 @@ function sceneUpdate()
end
function sceneRender()
cameraPushMatrix(camera)
-- Map Test
cameraPushMatrix(mapCamera)
mapCamera.position = vec3(300, 300, 300)
mapRender()
cameraPopMatrix()
-- UI Test
cameraPushMatrix(camera)
camera.bottom = screenGetHeight()
camera.right = screenGetWidth()
width, height = textMeasure(text)
x = (screenGetWidth() - width)
x = math.sin(TIME.time * 2) * (x / 2) + (x / 2)
y = (screenGetHeight() - height) / 2
y = math.cos(TIME.time * 3) * (y) + (y)
textDraw(x, y, text)
textDraw(x, y, text, colorMagenta())
cameraPopMatrix()
end

View File

@@ -10,6 +10,8 @@
#include "type/assetalphaimage.h"
#include "type/assetlanguage.h"
#include "type/assetscript.h"
#include "type/assetmap.h"
#include "type/assetmapchunk.h"
#include <zip.h>
typedef enum {
@@ -19,6 +21,8 @@ typedef enum {
ASSET_TYPE_ALPHA_IMAGE,
ASSET_TYPE_LANGUAGE,
ASSET_TYPE_SCRIPT,
ASSET_TYPE_MAP,
ASSET_TYPE_MAP_CHUNK,
ASSET_TYPE_COUNT,
} assettype_t;
@@ -73,4 +77,16 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = {
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
.custom = assetScriptHandler
},
[ASSET_TYPE_MAP] = {
.header = "DMF",
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
.custom = assetMapHandler
},
[ASSET_TYPE_MAP_CHUNK] = {
.header = "DMC",
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
.custom = assetMapChunkHandler
},
};

View File

@@ -10,4 +10,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
assetpaletteimage.c
assetlanguage.c
assetscript.c
assetmap.c
assetmapchunk.c
)

View File

@@ -9,11 +9,7 @@
#include "assert/assert.h"
#include "util/memory.h"
errorret_t assetMapLoad(void *data, void *output) {
assertNotNull(data, "Data cannot be NULL");
assertNotNull(output, "Output cannot be NULL");
assertUnreachable("map not finished");
errorret_t assetMapHandler(assetcustom_t custom) {
printf("Map Loaded from asset!\n");
errorOk();
}

View File

@@ -7,8 +7,8 @@
#pragma once
#include "error/error.h"
#include "rpg/overworld/map.h"
#include "display/mesh/mesh.h"
typedef struct assetcustom_s assetcustom_t;
/**
* Loads a map asset from the given data pointer into the output map structure.
@@ -17,4 +17,4 @@
* @param output Pointer to the map_t to load the map into.
* @return An error code.
*/
errorret_t assetMapLoad(void *data, void *output);
errorret_t assetMapHandler(assetcustom_t custom);

View File

@@ -7,7 +7,7 @@
#include "asset/asset.h"
#include "assert/assert.h"
#include "rpg/entity/entity.h"
#include "map/mapchunk.h"
#pragma pack(push, 1)
typedef struct {
@@ -19,7 +19,7 @@ typedef struct {
#pragma pack(push, 1)
typedef struct {
tile_t tile;
maptile_t tile;
} assetchunktiledata_t;
#pragma pack(pop)
@@ -31,18 +31,18 @@ typedef struct {
#pragma pack(push, 1)
typedef struct {
entitytype_t entityType;
uint8_t entityType;
uint8_t localX;
uint8_t localY;
uint8_t localZ;
} assetchunkentityheader_t;
#pragma pack(pop)
errorret_t assetChunkLoad(assetcustom_t custom) {
errorret_t assetMapChunkHandler(assetcustom_t custom) {
assertNotNull(custom.output, "Output pointer cannot be NULL");
assertNotNull(custom.zipFile, "Zip file pointer cannot be NULL");
chunk_t *chunk = (chunk_t *)custom.output;
mapchunk_t *chunk = (mapchunk_t *)custom.output;
assertTrue(chunk->meshCount == 0, "Chunk is not in a good state");
// Read header
@@ -143,36 +143,36 @@ errorret_t assetChunkLoad(assetcustom_t custom) {
}
// Read entity data
for(uint8_t i = 0; i < header.entityCount; i++) {
assetchunkentityheader_t entityHeader;
bytesRead = zip_fread(
custom.zipFile, &entityHeader, sizeof(assetchunkentityheader_t)
);
if(bytesRead != sizeof(assetchunkentityheader_t)) {
zip_fclose(custom.zipFile);
errorThrow("Failed to read chunk entity header.");
}
// for(uint8_t i = 0; i < header.entityCount; i++) {
// assetchunkentityheader_t entityHeader;
// bytesRead = zip_fread(
// custom.zipFile, &entityHeader, sizeof(assetchunkentityheader_t)
// );
// if(bytesRead != sizeof(assetchunkentityheader_t)) {
// zip_fclose(custom.zipFile);
// errorThrow("Failed to read chunk entity header.");
// }
uint8_t entityIndex = entityGetAvailable();
if(entityIndex == 0xFF) {
zip_fclose(custom.zipFile);
errorThrow("No available entity slots.");
}
// uint8_t entityIndex = entityGetAvailable();
// if(entityIndex == 0xFF) {
// zip_fclose(custom.zipFile);
// errorThrow("No available entity slots.");
// }
entity_t *entity = &ENTITIES[entityIndex];
entityInit(entity, (entitytype_t)entityHeader.entityType);
entity->position.x = (
(chunk->position.x * CHUNK_WIDTH) + entityHeader.localX
);
entity->position.y = (
(chunk->position.y * CHUNK_HEIGHT) + entityHeader.localY
);
entity->position.z = (
(chunk->position.z * CHUNK_DEPTH) + entityHeader.localZ
);
// entity_t *entity = &ENTITIES[entityIndex];
// entityInit(entity, (entitytype_t)entityHeader.entityType);
// entity->position.x = (
// (chunk->position.x * CHUNK_WIDTH) + entityHeader.localX
// );
// entity->position.y = (
// (chunk->position.y * CHUNK_HEIGHT) + entityHeader.localY
// );
// entity->position.z = (
// (chunk->position.z * CHUNK_DEPTH) + entityHeader.localZ
// );
chunk->entities[i] = entityIndex;
}
// chunk->entities[i] = entityIndex;
// }
errorOk();
}

View File

@@ -7,14 +7,13 @@
#pragma once
#include "error/error.h"
#include "rpg/overworld/chunk.h"
typedef struct assetcustom_s assetcustom_t;
/**
* Handles loading of chunk data from a chunk asset file.
* Handles loading of map chunk data from a map chunk asset file.
*
* @param custom The custom asset loading parameters.
* @return An error code.
*/
errorret_t assetChunkLoad(assetcustom_t custom);
errorret_t assetMapChunkHandler(assetcustom_t custom);

View File

@@ -30,6 +30,7 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
if(stringCompare(MAP.filePath, path) == 0) {
// Same map, no need to reload
errorChain(mapPositionSet(position));
errorOk();
}
@@ -58,6 +59,9 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
if(last == NULL) errorThrow("Map file name has no extension");
*last = '\0'; // Terminate to remove extension
// Load map itself
errorChain(assetLoad(MAP.filePath, &MAP));
// Reset map position
MAP.chunkPosition = position;
@@ -77,19 +81,6 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position) {
}
}
// Execute map script.
// char_t scriptPath[MAP_FILE_PATH_MAX + 16];
// stringFormat(
// scriptPath, sizeof(scriptPath), "%s/%s.dsf",
// MAP.dirPath, MAP.fileName
// );
// if(assetFileExists(scriptPath)) {
// scriptcontext_t ctx;
// errorChain(scriptContextInit(&ctx));
// errorChain(scriptContextExecFile(&ctx, scriptPath));
// scriptContextDispose(&ctx);
// }
errorOk();
}
@@ -181,6 +172,15 @@ void mapUpdate() {
#endif
}
void mapRender() {
if(!mapIsLoaded()) return;
textureBind(NULL);
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
mapChunkRender(&MAP.chunks[i]);
}
}
void mapDispose() {
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
mapChunkUnload(&MAP.chunks[i]);
@@ -211,7 +211,7 @@ errorret_t mapChunkLoad(mapchunk_t* chunk) {
memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
// Get chunk filepath.
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dcf",
snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dmc",
MAP.dirPath,
chunk->position.x,
chunk->position.y,

View File

@@ -50,6 +50,11 @@ errorret_t mapLoad(const char_t *path, const chunkpos_t position);
*/
void mapUpdate();
/**
* Renders the map.
*/
void mapRender();
/**
* Disposes of the map.
*/

View File

@@ -17,4 +17,10 @@ uint32_t mapChunkGetTileindex(const chunkpos_t position) {
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b) {
return (a.x == b.x) && (a.y == b.y) && (a.z == b.z);
}
void mapChunkRender(const mapchunk_t *chunk) {
for(uint8_t i = 0; i < chunk->meshCount; i++) {
meshDraw(&chunk->meshes[i], 0, -1);
}
}

View File

@@ -35,4 +35,11 @@ uint32_t mapChunkGetTileindex(const chunkpos_t position);
* @param b The second chunk position.
* @return true if equal, false otherwise.
*/
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b);
bool_t mapChunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b);
/**
* Renders the given map chunk.
*
* @param chunk The map chunk to render.
*/
void mapChunkRender(const mapchunk_t *chunk);

View File

@@ -9,6 +9,7 @@ add_subdirectory(event)
add_subdirectory(input)
add_subdirectory(item)
add_subdirectory(locale)
add_subdirectory(map)
add_subdirectory(system)
add_subdirectory(scene)
add_subdirectory(story)

View File

@@ -185,7 +185,25 @@ int moduleCameraIndex(lua_State *l) {
if(cam->viewType == CAMERA_VIEW_TYPE_MATRIX) {
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT) {
// TODO: Push vec3
if(stringCompare(key, "position") == 0) {
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
memoryCopy(v, &cam->lookat.position, sizeof(vec3));
luaL_getmetatable(l, "vec3_mt");
lua_setmetatable(l, -2);
return 1;
} else if(stringCompare(key, "target") == 0) {
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
memoryCopy(v, &cam->lookat.target, sizeof(vec3));
luaL_getmetatable(l, "vec3_mt");
lua_setmetatable(l, -2);
return 1;
} else if(stringCompare(key, "up") == 0) {
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
memoryCopy(v, &cam->lookat.up, sizeof(vec3));
luaL_getmetatable(l, "vec3_mt");
lua_setmetatable(l, -2);
return 1;
}
} else if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT) {
} else if(cam->viewType == CAMERA_VIEW_TYPE_2D) {
@@ -267,5 +285,24 @@ int moduleCameraNewIndex(lua_State *l) {
}
}
if(cam->viewType == CAMERA_VIEW_TYPE_LOOKAT) {
if(stringCompare(key, "position") == 0) {
vec3 *v = (vec3 *)luaL_checkudata(l, 3, "vec3_mt");
assertNotNull(v, "Vec3 pointer cannot be NULL.");
memoryCopy(&cam->lookat.position, v, sizeof(vec3));
return 0;
} else if(stringCompare(key, "target") == 0) {
vec3 *v = (vec3 *)luaL_checkudata(l, 3, "vec3_mt");
assertNotNull(v, "Vec3 pointer cannot be NULL.");
memoryCopy(&cam->lookat.target, v, sizeof(vec3));
return 0;
} else if(stringCompare(key, "up") == 0) {
vec3 *v = (vec3 *)luaL_checkudata(l, 3, "vec3_mt");
assertNotNull(v, "Vec3 pointer cannot be NULL.");
memoryCopy(&cam->lookat.up, v, sizeof(vec3));
return 0;
}
}
return 0;
}

View File

@@ -13,39 +13,122 @@
void moduleGLM(scriptcontext_t *context) {
assertNotNull(context, "Context cannot be NULL.");
// scriptStructRegister(
// context,
// "vec3_mt",
// moduleGLMVec3Getter,
// NULL
// );
// Create metatable for vec3 structure.
if(luaL_newmetatable(context->luaState, "vec3_mt")) {
// Metatable methods
lua_pushcfunction(context->luaState, moduleVec3Index);
lua_setfield(context->luaState, -2, "__index");
lua_pushcfunction(context->luaState, moduleVec3NewIndex);
lua_setfield(context->luaState, -2, "__newindex");
lua_pushcfunction(context->luaState, moduleVec3ToString);
lua_setfield(context->luaState, -2, "__tostring");
lua_pop(context->luaState, 1);
}
lua_register(context->luaState, "vec3", moduleVec3Create);
}
// void moduleGLMVec3Getter(
// const scriptcontext_t *context,
// const char_t *key,
// const void *structPtr,
// scriptvalue_t *outValue
// ) {
// assertNotNull(context, "Script context cannot be NULL.");
// assertNotNull(key, "Key cannot be NULL.");
// assertNotNull(structPtr, "Structure pointer cannot be NULL.");
// assertNotNull(outValue, "Output value cannot be NULL.");
int moduleVec3Create(lua_State *l) {
assertNotNull(l, "Lua state cannot be NULL.");
// printf("Getting vec3 field %s\n", key);
vec3 *v = (vec3 *)lua_newuserdata(l, sizeof(vec3));
memoryZero(v, sizeof(vec3));
// vec3 *v = (vec3 *)structPtr;
// if(stringCompare(key, "x") == 0) {
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
// outValue->value.floatValue = (*v)[0];
// return;
// } else if(stringCompare(key, "y") == 0) {
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
// outValue->value.floatValue = (*v)[1];
// return;
// } else if(stringCompare(key, "z") == 0) {
// outValue->type = SCRIPT_VALUE_TYPE_FLOAT;
// outValue->value.floatValue = (*v)[2];
// return;
// }
// }
// May be expecting between 1 and 3 values.
int top = lua_gettop(l);
if(top >= 1) {
if(!lua_isnumber(l, 1)) {
luaL_error(l, "Vec3 x component must be a number.");
}
(*v)[0] = (float_t)lua_tonumber(l, 1);
}
if(top >= 2) {
if(!lua_isnumber(l, 2)) {
luaL_error(l, "Vec3 y component must be a number.");
}
(*v)[1] = (float_t)lua_tonumber(l, 2);
}
if(top >= 3) {
if(!lua_isnumber(l, 3)) {
luaL_error(l, "Vec3 z component must be a number.");
}
(*v)[2] = (float_t)lua_tonumber(l, 3);
}
// Set metatable
luaL_getmetatable(l, "vec3_mt");
lua_setmetatable(l, -2);
return 1;
}
int moduleVec3Index(lua_State *l) {
assertNotNull(l, "Lua state cannot be NULL.");
const char_t *key = lua_tostring(l, 2);
assertStrLenMin(key, 1, "Key cannot be empty.");
vec3 *vec = (vec3 *)luaL_checkudata(l, 1, "vec3_mt");
assertNotNull(vec, "Vec3 pointer cannot be NULL.");
if(stringCompare(key, "x") == 0) {
lua_pushnumber(l, (*vec)[0]);
return 1;
} else if(stringCompare(key, "y") == 0) {
lua_pushnumber(l, (*vec)[1]);
return 1;
} else if(stringCompare(key, "z") == 0) {
lua_pushnumber(l, (*vec)[2]);
return 1;
}
}
int moduleVec3NewIndex(lua_State *l) {
assertNotNull(l, "Lua state cannot be NULL.");
const char_t *key = luaL_checkstring(l, 2);
assertStrLenMin(key, 1, "Key cannot be empty.");
vec3 *vec = (vec3 *)luaL_checkudata(l, 1, "vec3_mt");
assertNotNull(vec, "Vec3 pointer cannot be NULL.");
if(stringCompare(key, "x") == 0) {
if(!lua_isnumber(l, 3)) {
luaL_error(l, "Vec3 x component must be a number.");
}
(*vec)[0] = (float_t)lua_tonumber(l, 3);
return 0;
} else if(stringCompare(key, "y") == 0) {
if(!lua_isnumber(l, 3)) {
luaL_error(l, "Vec3 y component must be a number.");
}
(*vec)[1] = (float_t)lua_tonumber(l, 3);
return 0;
} else if(stringCompare(key, "z") == 0) {
if(!lua_isnumber(l, 3)) {
luaL_error(l, "Vec3 z component must be a number.");
}
(*vec)[2] = (float_t)lua_tonumber(l, 3);
return 0;
}
luaL_error(l, "Invalid key for vec3: %s", key);
return 0;
}
int moduleVec3ToString(lua_State *l) {
assertNotNull(l, "Lua state cannot be NULL.");
vec3 *vec = (vec3 *)luaL_checkudata(l, 1, "vec3_mt");
assertNotNull(vec, "Vec3 pointer cannot be NULL.");
char buf[128];
snprintf(
buf, sizeof(buf),
"vec3(%.3f, %.3f, %.3f)",
(*vec)[0], (*vec)[1], (*vec)[2]
);
lua_pushstring(l, buf);
return 1;
}

View File

@@ -16,16 +16,33 @@
void moduleGLM(scriptcontext_t *context);
/**
* Getter function for the vec3 structure.
* Creates a new vec3 structure in Lua.
*
* @param context The script context.
* @param key The key to get.
* @param structPtr Pointer to the vec3 structure.
* @param outValue Pointer to store the output value.
* @param l The Lua state.
* @return Number of return values on the Lua stack.
*/
void moduleGLMVec3Getter(
const scriptcontext_t *context,
const char_t *key,
const void *structPtr,
scriptvalue_t *outValue
);
int moduleVec3Create(lua_State *l);
/**
* Lua __index metamethod for vec3 structure.
*
* @param l The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleVec3Index(lua_State *l);
/**
* Lua __newindex metamethod for vec3 structure.
*
* @param l The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleVec3NewIndex(lua_State *l);
/**
* Lua __tostring metamethod for vec3 structure.
*
* @param l The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleVec3ToString(lua_State *l);

View File

@@ -39,10 +39,10 @@ int moduleTextDraw(lua_State *L) {
// Optional color
color_t *color = NULL;
if(lua_gettop(L) < 6 || lua_isnil(L, 6)) {
if(lua_gettop(L) < 4 || lua_isnil(L, 4)) {
// Allow NULL
} else if(lua_isuserdata(L, 6)) {
color = (color_t*)luaL_checkudata(L, 6, "color_mt");
} else if(lua_isuserdata(L, 4)) {
color = (color_t*)luaL_checkudata(L, 4, "color_mt");
} else {
return luaL_error(L, "Sprite color must be a color struct or nil");
}

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
modulemap.c
)

View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "modulemap.h"
#include "assert/assert.h"
#include "map/map.h"
void moduleMap(scriptcontext_t *ctx) {
assertNotNull(ctx, "Script context cannot be NULL");
// Register map functions
lua_register(ctx->luaState, "mapIsLoaded", moduleMapIsLoaded);
lua_register(ctx->luaState, "mapGetTile", moduleMapGetTile);
lua_register(ctx->luaState, "mapRender", moduleMapRender);
lua_register(ctx->luaState, "mapLoad", moduleMapLoad);
}
int moduleMapIsLoaded(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL.");
lua_pushboolean(L, mapIsLoaded());
return 1;
}
int moduleMapGetTile(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL.");
return 1;
}
int moduleMapRender(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL.");
mapRender();
return 0;
}
int moduleMapLoad(lua_State *L) {
assertNotNull(L, "Lua state cannot be NULL.");
if(!lua_isstring(L, 1)) {
luaL_error(L, "Expected string as first argument (file path).");
return 0;
}
const char_t *path = lua_tostring(L, 1);
// Optional position.
chunkpos_t position = {0, 0, 0};
errorret_t err = mapLoad(path, position);
if(err.code != ERROR_OK) {
errorCatch(errorPrint(err));
luaL_error(L, "Failed to load map!");
return 0;
}
return 0;
}

View File

@@ -0,0 +1,48 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/scriptcontext.h"
/**
* Register map functions to the given script context.
*
* @param context The script context to register map functions to.
*/
void moduleMap(scriptcontext_t *context);
/**
* Script function to check if a map is loaded.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleMapIsLoaded(lua_State *L);
/**
* Script function to get the tile at a given world position.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleMapGetTile(lua_State *L);
/**
* Script function to render the map.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleMapRender(lua_State *L);
/**
* Script function to load a map from a given file path.
*
* @param L The Lua state.
* @return Number of return values on the Lua stack.
*/
int moduleMapLoad(lua_State *L);

View File

@@ -22,6 +22,7 @@
#include "script/module/display/moduletext.h"
#include "script/module/display/modulescreen.h"
#include "script/module/story/modulestoryflag.h"
#include "script/module/map/modulemap.h"
#include "util/string.h"
const scriptmodule_t SCRIPT_MODULE_LIST[] = {
@@ -41,6 +42,7 @@ const scriptmodule_t SCRIPT_MODULE_LIST[] = {
{ .name = "text", .callback = moduleText },
{ .name = "screen", .callback = moduleScreen },
{ .name = "storyflag", .callback = moduleStoryFlag },
{ .name = "map", .callback = moduleMap },
};
#define SCRIPT_MODULE_COUNT ( \

View File

@@ -51,7 +51,7 @@ def processChunk(chunk):
# Generate binary buffer for efficient output
buffer = bytearray()
buffer.extend(b'DCF')# Header
buffer.extend(b'DMC')# Header
buffer.extend(len(chunk.tiles).to_bytes(4, 'little')) # Number of tiles
buffer.extend(len(models).to_bytes(1, 'little')) # Number of models
buffer.extend(len(chunk.entities).to_bytes(1, 'little')) # Number of entities
@@ -92,7 +92,7 @@ def processChunk(chunk):
# Write out map file
relative = getAssetRelativePath(chunk.getFilename())
fileNameWithoutExt = os.path.splitext(os.path.basename(relative))[0]
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dcf")
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dmc")
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, "wb") as f: