Map loading
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -38,5 +38,4 @@ else
|
||||
end
|
||||
|
||||
localeSet(DUSK_LOCALE_EN_US)
|
||||
sceneSet('scene/initial.dsf')
|
||||
-- mapLoad('map/testmap/testmap.dmf')
|
||||
sceneSet('scene/initial.dsf')
|
||||
@@ -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)
|
||||
@@ -1 +0,0 @@
|
||||
print('Test Map Script Run')
|
||||
@@ -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
|
||||
@@ -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
|
||||
},
|
||||
};
|
||||
@@ -10,4 +10,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||
assetpaletteimage.c
|
||||
assetlanguage.c
|
||||
assetscript.c
|
||||
assetmap.c
|
||||
assetmapchunk.c
|
||||
)
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
10
src/script/module/map/CMakeLists.txt
Normal file
10
src/script/module/map/CMakeLists.txt
Normal 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
|
||||
)
|
||||
60
src/script/module/map/modulemap.c
Normal file
60
src/script/module/map/modulemap.c
Normal 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;
|
||||
}
|
||||
48
src/script/module/map/modulemap.h
Normal file
48
src/script/module/map/modulemap.h
Normal 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);
|
||||
@@ -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 ( \
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user