diff --git a/assets/init.lua b/assets/init.lua index 7599ea96..37945756 100644 --- a/assets/init.lua +++ b/assets/init.lua @@ -73,6 +73,4 @@ elseif LINUX then else print("Unknown platform, no default input bindings set.") -end - -sceneSet('scene/main_menu/main_menu.lua') \ No newline at end of file +end \ No newline at end of file diff --git a/assets/scene/main_menu/main_menu.lua b/assets/scene/main_menu/main_menu.lua deleted file mode 100644 index 0b147735..00000000 --- a/assets/scene/main_menu/main_menu.lua +++ /dev/null @@ -1,46 +0,0 @@ -module('spritebatch') -module('camera') -module('color') -module('ui') -module('screen') -module('time') -module('text') -module('tileset') -module('texture') -module('input') -module('shader') -module('locale') - -screenSetBackground(colorCornflowerBlue()) -camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) - -text = localeGetText('cart.item_count', 52, 2) - -function sceneDispose() -end - -function sceneUpdate() -end - -function sceneRender() - -- Update camera - camera.top = screenGetHeight() - camera.right = screenGetWidth() - - shaderBind(SHADER_UNLIT) - proj = cameraGetProjectionMatrix(camera) - shaderSetMatrix(SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj) - view = cameraGetViewMatrix(camera) - shaderSetMatrix(SHADER_UNLIT, SHADER_UNLIT_VIEW, view) - - -- shaderSetTexture(SHADER_UNLIT, SHADER_UNLIT_TEXTURE, nil) - -- spriteBatchPush( - -- 32, 32, - -- 64, 64, - -- colorWhite() - -- ) - -- spriteBatchFlush() - - textDraw(10, 10, text, colorWhite()) - spriteBatchFlush() -end \ No newline at end of file diff --git a/assets/test.json b/assets/test.json deleted file mode 100644 index 94ce3664..00000000 --- a/assets/test.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "Dominic", - "age": 31, - "likes": [ - "thing1", - "thing2" - ], - "options": { - "someParam": true, - "someSubObject": { - "someSubSubParam": 52 - }, - "someArray": [ - 1, - 2, - 3 - ] - } -} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 72fa6c04..f29a2216 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,8 +4,7 @@ # https://opensource.org/licenses/MIT add_subdirectory(dusk) -# add_subdirectory(duskrpg) -add_subdirectory(dusktrivia) +add_subdirectory(duskrpg) if(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "knulli") add_subdirectory(dusklinux) diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt index 28221cf1..ff8c5acb 100644 --- a/src/dusk/CMakeLists.txt +++ b/src/dusk/CMakeLists.txt @@ -67,6 +67,7 @@ add_subdirectory(asset) add_subdirectory(log) add_subdirectory(display) add_subdirectory(engine) +add_subdirectory(entity) add_subdirectory(error) add_subdirectory(event) add_subdirectory(input) diff --git a/src/dusk/display/display.c b/src/dusk/display/display.c index b8ad73b7..45fb9420 100644 --- a/src/dusk/display/display.c +++ b/src/dusk/display/display.c @@ -23,24 +23,6 @@ #include "script/module/display/moduleshader.h" display_t DISPLAY = { 0 }; - mesh_t mesh; - meshvertex_t vertices[3] = { - { - .color = { 255, 0, 0, 255 }, - .uv = { 0.0f, 0.0f }, - .pos = { 0.0f, 0.5f, 0.0f } - }, - { - .color = { 0, 255, 0, 255 }, - .uv = { 0.5f, 1.0f }, - .pos = { -0.5f, -0.5f, 0.0f } - }, - { - .color = { 0, 0, 255, 255 }, - .uv = { 1.0f, 0.0f }, - .pos = { 0.5f, -0.5f, 0.0f } - } - }; errorret_t displayInit(void) { memoryZero(&DISPLAY, sizeof(DISPLAY)); @@ -68,8 +50,6 @@ errorret_t displayInit(void) { errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, mat)); errorChain(shaderSetTexture(&SHADER_UNLIT, SHADER_UNLIT_TEXTURE, NULL)); - errorChain(meshInit(&mesh, MESH_PRIMITIVE_TYPE_TRIANGLES, 3, vertices)); - errorOk(); } diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index e0bceca6..7dfa5e55 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -16,9 +16,11 @@ #include "ui/ui.h" #include "script/scriptmanager.h" #include "assert/assert.h" +#include "entity/entitymanager.h" #include "game/game.h" -#include "asset/loader/json/assetjsonloader.h" +#include "entity/component/display/entityposition.h" +#include "entity/component/display/entitycamera.h" engine_t ENGINE; @@ -37,9 +39,17 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { errorChain(displayInit()); errorChain(uiInit()); errorChain(sceneInit()); + entityManagerInit(); errorChain(gameInit()); - // Run the initial script. + entityid_t ent0 = entityAdd(); + entityAddComponent(ent0, ENTITY_POSITION_DATA); + entityAddComponent(ent0, ENTITY_CAMERA_DATA); + + entityid_t ent1 = entityAdd(); + entityAddComponent(ent0, ENTITY_POSITION_DATA); + + // Run the init script. scriptcontext_t ctx; errorChain(scriptContextInit(&ctx)); errorChain(scriptContextExecFile(&ctx, "init.lua")); @@ -69,6 +79,7 @@ void engineExit(void) { errorret_t engineDispose(void) { sceneDispose(); errorChain(gameDispose()); + entityManagerDispose(); localeManagerDispose(); uiDispose(); errorChain(displayDispose()); diff --git a/src/dusk/entity/CMakeLists.txt b/src/dusk/entity/CMakeLists.txt new file mode 100644 index 00000000..c13c4338 --- /dev/null +++ b/src/dusk/entity/CMakeLists.txt @@ -0,0 +1,15 @@ +# 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 + entity.c + entitycomponent.c + entitymanager.c +) + +# Subdirectories +add_subdirectory(component) \ No newline at end of file diff --git a/src/duskrpg/map/CMakeLists.txt b/src/dusk/entity/component/CMakeLists.txt similarity index 62% rename from src/duskrpg/map/CMakeLists.txt rename to src/dusk/entity/component/CMakeLists.txt index 914f254b..c57bc7a8 100644 --- a/src/duskrpg/map/CMakeLists.txt +++ b/src/dusk/entity/component/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2025 Dominic Masters +# Copyright (c) 2026 Dominic Masters # # This software is released under the MIT License. # https://opensource.org/licenses/MIT @@ -6,8 +6,7 @@ # Sources target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC - mapchunk.c - map.c - worldpos.c - maptile.c -) \ No newline at end of file +) + +# Subdirectories +add_subdirectory(display) \ No newline at end of file diff --git a/src/duskrpg/script/module/map/CMakeLists.txt b/src/dusk/entity/component/display/CMakeLists.txt similarity index 81% rename from src/duskrpg/script/module/map/CMakeLists.txt rename to src/dusk/entity/component/display/CMakeLists.txt index 58b11490..8039daa8 100644 --- a/src/duskrpg/script/module/map/CMakeLists.txt +++ b/src/dusk/entity/component/display/CMakeLists.txt @@ -1,10 +1,12 @@ # 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 -) \ No newline at end of file + entityposition.c +) + +# Subdirectories \ No newline at end of file diff --git a/src/dusk/entity/component/display/entitycamera.c b/src/dusk/entity/component/display/entitycamera.c new file mode 100644 index 00000000..40e42167 --- /dev/null +++ b/src/dusk/entity/component/display/entitycamera.c @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entitycamera.h" + +ENTITY_COMPONENT_DEFINE(entitycamera_t, entityCameraInit, NULL) + +void entityCameraInit(const entityandentitycomponentid_t id) { + entityid_t entityId = + + // Default to perspective camera with default values. + data->projType = CAMERA_PROJECTION_TYPE_PERSPECTIVE; + data->perspective.fov = glm_rad(45.0f); + data->nearClip = 0.1f; + data->farClip = 10000.0f; +} \ No newline at end of file diff --git a/src/dusk/entity/component/display/entitycamera.h b/src/dusk/entity/component/display/entitycamera.h new file mode 100644 index 00000000..c99ca91a --- /dev/null +++ b/src/dusk/entity/component/display/entitycamera.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entity/entitymanager.h" +#include "display/camera/camera.h" + +#define ENTITY_CAMERA_COUNT_MAX 2 + +typedef struct { + union { + struct { + float_t fov; + } perspective; + + struct { + float_t left; + float_t right; + float_t top; + float_t bottom; + } orthographic; + }; + + float_t nearClip; + float_t farClip; + + cameraprojectiontype_t projType; +} entitycamera_t; + +/** + * Initializes the camera component for an entity. + * + * @param id The component entity id. + */ +void entityCameraInit(const entityandentitycomponentid_t id); \ No newline at end of file diff --git a/src/dusk/entity/component/display/entityposition.c b/src/dusk/entity/component/display/entityposition.c new file mode 100644 index 00000000..1182fc97 --- /dev/null +++ b/src/dusk/entity/component/display/entityposition.c @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entityposition.h" +#include "util/memory.h" + +entityposition_t ENTITY_POSITION_DATA[ENTITY_COUNT_MAX]; + +void entityPositionInit(const entityid_t id, entityposition_t *data) { + memoryZero(data, sizeof(entityposition_t)); + + glm_mat4_identity(data->transform); +} + +void entityPositionLookAt( + const entityid_t id, + const vec3 target, + const vec3 up, + const vec3 eye +) { + glm_lookat(eye, target, up, ENTITY_POSITION_DATA[id].transform); +} \ No newline at end of file diff --git a/src/dusk/entity/component/display/entityposition.h b/src/dusk/entity/component/display/entityposition.h new file mode 100644 index 00000000..42a3c85c --- /dev/null +++ b/src/dusk/entity/component/display/entityposition.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entity/entity.h" + +typedef struct { + mat4 transform; +} entityposition_t; + +/** + * Initializes the position component for an entity. + * + * @param id The component entity id. + */ +void entityPositionInit(const entityandentitycomponentid_t id); + +/** + * Sets the position component of an entity to look at a target point. + * + * @param id The component entity id. + * @param target The target point to look at. + * @param up The up vector to use for the look at calculation. + * @param eye The eye position to use for the look at calculation. + */ +void entityPositionLookAt( + const entityandentitycomponentid_t id, + const vec3 target, + const vec3 up, + const vec3 eye +); \ No newline at end of file diff --git a/src/dusk/entity/entity.c b/src/dusk/entity/entity.c new file mode 100644 index 00000000..d3c170f8 --- /dev/null +++ b/src/dusk/entity/entity.c @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entitymanager.h" +#include "util/memory.h" +#include "assert/assert.h" + +entityid_t entityAdd() { + entityid_t id = 0xFF; + + // Quick search for an available slot. + for(uint8_t i = 0; i < ENTITY_COUNT_MAX; i++) { + if((ENTITY_MANAGER.entities[i].state & ENTITY_STATE_ACTIVE) != 0) { + continue; + } + + id = i; + break; + } + + if(id >= ENTITY_COUNT_MAX) { + assertUnreachable("No available entity slots."); + return 0xFF; + } + + // Init the entity. + entity_t *entity = &ENTITY_MANAGER.entities[id]; + memoryZero(entity, sizeof(entity_t)); + entity->state |= ENTITY_STATE_ACTIVE; + return id; +} + +entitycomponentid_t entityAddComponent( + const entityid_t id, + void *componentData +) { + entitycomponentid_t compId = entityComponentGetByData(componentData); + assertTrue(compId != 0xFF, "Component not found in entity manager."); + + // Find empty entity slot. + entitycomponent_t *comp = &ENTITY_MANAGER.components[compId]; + uint8_t x = 0xFF;// Entity slot within the component + for(uint8_t i = 0; i < comp->entityMax; i++) { + if(comp->entities[i] != 0xFF) { + continue; + } + x = i; + break; + } + assertTrue(x != 0xFF, "No available component entity slots."); + + // Set the entity id. + entity_t *entity = &ENTITY_MANAGER.entities[id]; + assertTrue( + entity->componentCount < ENTITY_COMPONENT_COUNT_MAX, + "Entity has too many components." + ); + comp->entities[x] = id; + entity->components[entity->componentCount++] = compId; + + if(comp->init != NULL) { + void *data = (uint8_t *)comp->data + (comp->dataSize * x); + comp->init(id, data); + } + return id; +} + +void entityRemove(const entityid_t id) { + assertTrue(id < ENTITY_COUNT_MAX, "Invalid entity ID."); + + entity_t *entity = &ENTITY_MANAGER.entities[id]; + entity->state &= ~ENTITY_STATE_ACTIVE; + + // Remove components. + for(uint8_t i = 0; i < entity->componentCount; i++) { + entitycomponentid_t compId = entity->components[i]; + entitycomponent_t *comp = &ENTITY_MANAGER.components[compId]; + + // Find the component slot for this entity. + uint8_t x = 0xFF; + for(uint8_t j = 0; j < comp->entityMax; j++) { + if(comp->entities[j] == id) { + x = j; + break; + } + } + assertTrue(x != 0xFF, "Entity does not have this component."); + + // Clear the component slot. + comp->entities[x] = 0xFF; + + // Dispose + if(comp->dispose != NULL) { + void *data = (uint8_t *)comp->data + (comp->dataSize * x); + comp->dispose(id, data); + } + } +} + +entityid_t entityGetId(const entityandentitycomponentid_t id) { + +} \ No newline at end of file diff --git a/src/dusk/entity/entity.h b/src/dusk/entity/entity.h new file mode 100644 index 00000000..408583f4 --- /dev/null +++ b/src/dusk/entity/entity.h @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entitybase.h" + +#define ENTITY_STATE_ACTIVE (1 << 0) + +typedef struct { + entitycomponentid_t components[ENTITY_COMPONENT_COUNT_MAX]; + uint8_t componentCount; + uint8_t state; +} entity_t; + +/** + * Adds an entity to the entity manager and initializes it. + * + * @return The ID of the added entity. + */ +entityid_t entityAdd(); + +/** + * Adds a component to an entity. + * + * @param id The ID of the entity to add the component to. + * @param componentData The data of the component to add. + * @return The ID of the added component. + */ +entitycomponentid_t entityAddComponent( + const entityid_t id, + void *componentData +); + +/** + * Disposes of an entity with the given ID, this will dispose of its components. + * + * @param id The ID of the entity to dispose. + */ +void entityRemove(const entityid_t id); + +/** + * Gets an entity id by the entity and entity component id provided. + * + * @param id Id to get the entity id for. + * @return The entity id. + */ +entityid_t entityGetId(const entityandentitycomponentid_t id); \ No newline at end of file diff --git a/src/dusk/entity/entitybase.h b/src/dusk/entity/entitybase.h new file mode 100644 index 00000000..2ff48601 --- /dev/null +++ b/src/dusk/entity/entitybase.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#define ENTITY_COUNT_MAX 256 +#define ENTITY_COMPONENT_COUNT_MAX 16 +#define ENTITY_MANAGER_COMPONENT_COUNT_MAX 64 + +typedef uint8_t entityid_t; +typedef uint8_t entitycomponentid_t; +typedef uint16_t entityandentitycomponentid_t; \ No newline at end of file diff --git a/src/dusk/entity/entitycomponent.c b/src/dusk/entity/entitycomponent.c new file mode 100644 index 00000000..018b898c --- /dev/null +++ b/src/dusk/entity/entitycomponent.c @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + + +#include "entitymanager.h" +#include "util/memory.h" +#include "assert/assert.h" + +entitycomponentid_t entityComponentInit( + void *data, + const size_t dataSize, + const uint8_t entityCountMax, + void (*init)(const entityid_t id, void *data), + void (*dispose)(const entityid_t id, void *data) +) { + assertNotNull(data, "Component data cannot be null."); + assertTrue(dataSize > 0, "Component data size must be greater than 0."); + assertTrue(entityCountMax > 0, "Component entity count max be at least 1"); + + // Get next available component slot. + entitycomponentid_t componentIndex = 0xFF; + for(uint8_t i = 0; i data = data; + component->dataSize = dataSize; + component->entityMax = entityCountMax; + component->init = init; + component->dispose = dispose; + + // Fill with 0xFF + memorySet(component->entities, 0xFF, sizeof(entityid_t) * ENTITY_COUNT_MAX); + + return componentIndex; +} + +entitycomponentid_t entityComponentGetByData(const void *data) { + assertNotNull(data, "Component data cannot be null."); + + for(uint8_t i = 0; i < ENTITY_MANAGER_COMPONENT_COUNT_MAX; i++) { + if(ENTITY_MANAGER.components[i].data == data) { + return i; + } + } + + return 0xFF; +} + +void * entityComponentGetData( + const entitycomponentid_t componentId, + const entityid_t entityId +) { + assertTrue( + componentId < ENTITY_MANAGER_COMPONENT_COUNT_MAX, + "Component ID is out of bounds." + ); + assertTrue( + entityId < ENTITY_COUNT_MAX, + "Entity ID is out of bounds." + ); + entitycomponent_t *comp = &ENTITY_MANAGER.components[componentId]; + for(uint8_t i = 0; i < comp->entityMax; i++) { + if(comp->entities[i] == entityId) { + return (uint8_t *)comp->data + (comp->dataSize * i); + } + } + assertUnreachable("Entity does not have the component."); + return NULL; +} \ No newline at end of file diff --git a/src/dusk/entity/entitycomponent.h b/src/dusk/entity/entitycomponent.h new file mode 100644 index 00000000..21f823c4 --- /dev/null +++ b/src/dusk/entity/entitycomponent.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entitybase.h" + +typedef struct { + size_t dataSize; + entityid_t entities[ENTITY_COUNT_MAX]; + uint8_t entityMax; + + void (*init)(const entityid_t id, void *data); + void (*dispose)(const entityid_t id, void *data); +} entitycomponent_t; + +#define ENTITY_COMPONENT_DEFINE(name, stc, init, dispose) \ + static const entitycomponent_t name = { \ + .dataSize = sizeof(*stc), \ + .entities = {0}, \ + .entityMax = ENTITY_COUNT_MAX, \ + .init = init, \ + .dispose = dispose \ + } + +/** + * Adds a component to the entity manager / Initializes a component slot. + * + * @param data The data of the component. + * @param dataSize The size of the component data. + * @param entityCountMax The maximum number of entities that can have this component. + * @param init The function to initialize the component for an entity. + * @param dispose The function to dispose of the component for an entity. + * @return The ID of the added component. + */ +entitycomponentid_t entityComponentInit( + void *data, + const size_t dataSize, + const uint8_t entityCountMax, + void (*init)(const entityid_t id, void *data), + void (*dispose)(const entityid_t id, void *data) +); + +/** + * Gets the component ID of a component by its data pointer. + * + * @param data The data pointer of the component. + * @return The ID of the component, or 0xFF if not found. + */ +entitycomponentid_t entityComponentGetByData(const void *data); + +/** + * Gets the component data for a given component and entity ID. + * + * @param componentId The ID of the component. + * @param entityId The ID of the entity. + * @return The component data. + */ +void * entityComponentGetData( + const entitycomponentid_t componentId, + const entityid_t entityId +); \ No newline at end of file diff --git a/src/dusk/entity/entitymanager.c b/src/dusk/entity/entitymanager.c new file mode 100644 index 00000000..9cf5e805 --- /dev/null +++ b/src/dusk/entity/entitymanager.c @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entitymanager.h" +#include "util/memory.h" +#include "assert/assert.h" + +#include "entity/component/display/entityposition.h" +#include "entity/component/display/entitycamera.h" + +entitymanager_t ENTITY_MANAGER; + +void entityManagerInit(void) { + memoryZero(&ENTITY_MANAGER, sizeof(entitymanager_t)); + + // Init components. + entityComponentInit( + ENTITY_POSITION_DATA, + sizeof(entityposition_t), + ENTITY_COUNT_MAX, + NULL, NULL + ); + + entityComponentInit( + ENTITY_CAMERA_DATA, + sizeof(entitycamera_t), + ENTITY_CAMERA_COUNT_MAX, + entityCameraInit, NULL + ); +} + +void entityManagerDispose(void) { + for(uint8_t i = 0; i < ENTITY_COUNT_MAX; i++) { + if((ENTITY_MANAGER.entities[i].state & ENTITY_STATE_ACTIVE) == 0) { + continue; + } + + entityRemove(i); + } +} \ No newline at end of file diff --git a/src/dusk/entity/entitymanager.h b/src/dusk/entity/entitymanager.h new file mode 100644 index 00000000..1ef2124e --- /dev/null +++ b/src/dusk/entity/entitymanager.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entity.h" +#include "entitycomponent.h" + +typedef struct { + entity_t entities[ENTITY_COUNT_MAX]; + entitycomponent_t components[ENTITY_MANAGER_COMPONENT_COUNT_MAX]; +} entitymanager_t; + +extern entitymanager_t ENTITY_MANAGER; + +/** + * Initializes the entity manager. + */ +void entityManagerInit(void); + +/** + * Disposes of the entity manager, this will dispose active entities. + */ +void entityManagerDispose(void); \ No newline at end of file diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index 1fef150b..0abfb406 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -16,7 +16,6 @@ scene_t SCENE; errorret_t sceneInit(void) { memoryZero(&SCENE, sizeof(scene_t)); - errorChain(scriptContextInit(&SCENE.scriptContext)); errorOk(); } @@ -26,69 +25,21 @@ errorret_t sceneUpdate(void) { errorOk(); } #endif - - lua_getglobal(SCENE.scriptContext.luaState, "sceneUpdate"); - if(!lua_isfunction(SCENE.scriptContext.luaState, -1)) { - lua_pop(SCENE.scriptContext.luaState, 1); - errorOk(); - } - - if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); - lua_pop(SCENE.scriptContext.luaState, 1); - errorThrow("Failed to call function '%s': %s", "sceneUpdate", strErr); - } errorOk(); } errorret_t sceneRender(void) { - lua_getglobal(SCENE.scriptContext.luaState, "sceneRender"); - if(!lua_isfunction(SCENE.scriptContext.luaState, -1)) { - lua_pop(SCENE.scriptContext.luaState, 1); - errorOk(); - } - - if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); - lua_pop(SCENE.scriptContext.luaState, 1); - errorThrow("Failed to call function '%s': %s", "sceneRender", strErr); - } + // For each camera + errorOk(); } errorret_t sceneSet(const char_t *script) { - // Cleanup old script context. - lua_getglobal(SCENE.scriptContext.luaState, "sceneDispose"); - if(lua_isfunction(SCENE.scriptContext.luaState, -1)) { - if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); - lua_pop(SCENE.scriptContext.luaState, 1); - errorThrow("Failed to call function '%s': %s", "sceneDispose", strErr); - } - } else { - lua_pop(SCENE.scriptContext.luaState, 1); - } - scriptContextDispose(&SCENE.scriptContext); - - // Create a new script context. - errorChain(scriptContextInit(&SCENE.scriptContext)); - errorChain(scriptContextExecFile(&SCENE.scriptContext, script)); errorOk(); } void sceneDispose(void) { - lua_getglobal(SCENE.scriptContext.luaState, "sceneDispose"); - if(lua_isfunction(SCENE.scriptContext.luaState, -1)) { - if(lua_pcall(SCENE.scriptContext.luaState, 0, 0, 0) != LUA_OK) { - const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1); - lua_pop(SCENE.scriptContext.luaState, 1); - logDebug("Failed to call function '%s': %s\n", "sceneDispose", strErr); - } - } else { - lua_pop(SCENE.scriptContext.luaState, 1); - } - - scriptContextDispose(&SCENE.scriptContext); + } \ No newline at end of file diff --git a/src/dusk/scene/scene.h b/src/dusk/scene/scene.h index 4f870630..6e0a079d 100644 --- a/src/dusk/scene/scene.h +++ b/src/dusk/scene/scene.h @@ -6,10 +6,10 @@ */ #pragma once -#include "script/scriptcontext.h" +#include "error/error.h" typedef struct { - scriptcontext_t scriptContext; + void *nothing; } scene_t; extern scene_t SCENE; diff --git a/src/dusk/script/module/display/moduletexture.c b/src/dusk/script/module/display/moduletexture.c index 197886da..b819b292 100644 --- a/src/dusk/script/module/display/moduletexture.c +++ b/src/dusk/script/module/display/moduletexture.c @@ -30,6 +30,10 @@ void moduleTexture(scriptcontext_t *ctx) { lua_setfield(l, -2, "__gc"); } + // Texture formats + lua_pushnumber(l, TEXTURE_FORMAT_RGBA); + lua_setglobal(l, "TEXTURE_FORMAT_RGBA"); + lua_register(ctx->luaState, "textureLoad", moduleTextureLoad); } diff --git a/src/dusk/script/module/display/moduletileset.c b/src/dusk/script/module/display/moduletileset.c index 46c6b273..de13430b 100644 --- a/src/dusk/script/module/display/moduletileset.c +++ b/src/dusk/script/module/display/moduletileset.c @@ -10,6 +10,7 @@ #include "display/texture/tileset.h" #include "util/memory.h" #include "util/string.h" +#include "asset/loader/display/assettilesetloader.h" void moduleTileset(scriptcontext_t *ctx) { assertNotNull(ctx, "Script context cannot be NULL"); @@ -24,7 +25,7 @@ void moduleTileset(scriptcontext_t *ctx) { } lua_pop(ctx->luaState, 1); // Pop the metatable - // lua_register(ctx->luaState, "tilesetGetByName", moduleTilesetGetByName); + lua_register(ctx->luaState, "tilesetLoad", moduleTilesetLoad); lua_register(ctx->luaState, "tilesetTileGetUV", moduleTilesetTileGetUV); lua_register( ctx->luaState, "tilesetPositionGetUV", moduleTilesetPositionGetUV @@ -71,34 +72,6 @@ int moduleTilesetToString(lua_State *l) { return 1; } -// int moduleTilesetGetByName(lua_State *l) { -// assertNotNull(l, "Lua state cannot be NULL."); - -// if(!lua_isstring(l, 1)) { -// lua_pushnil(l); -// return 1; -// } - -// const char_t *name = lua_tostring(l, 1); -// if(name == NULL || name[0] == '\0') { -// luaL_error(l, "Invalid tileset name."); -// return 1; -// } - -// const tileset_t *ts = tilesetGetByName(name); -// if(ts == NULL) { -// lua_pushnil(l); -// return 1; -// } - -// // Lua does not own this reference -// lua_pushlightuserdata(l, (void *)ts); -// luaL_getmetatable(l, "tileset_mt"); -// lua_setmetatable(l, -2); - -// return 1; -// } - int moduleTilesetTileGetUV(lua_State *l) { assertNotNull(l, "Lua state cannot be NULL."); @@ -157,4 +130,35 @@ int moduleTilesetPositionGetUV(lua_State *l) { luaL_getmetatable(l, "vec4_mt"); lua_setmetatable(l, -2); return 1; +} + +int moduleTilesetLoad(lua_State *l) { + assertNotNull(l, "Lua state cannot be NULL."); + + if(!lua_isstring(l, 1)) { + luaL_error(l, "First argument must be a string filename."); + return 0; + } + + const char_t *filename = lua_tostring(l, 1); + assertNotNull(filename, "Filename cannot be NULL."); + assertStrLenMin(filename, 1, "Filename cannot be empty."); + + // Create texture owned to lua + tileset_t *tileset = (tileset_t *)lua_newuserdata(l, sizeof(tileset_t)); + memoryZero(tileset, sizeof(tileset_t)); + + errorret_t ret = assetTilesetLoad(filename, tileset); + if(ret.code != ERROR_OK) { + errorCatch(errorPrint(ret)); + luaL_error(l, "Failed to load tileset asset: %s", filename); + return 0; + } + + // Set metatable + luaL_getmetatable(l, "tileset_mt"); + lua_setmetatable(l, -2); + + // Return the tileset + return 1; } \ No newline at end of file diff --git a/src/dusk/script/module/display/moduletileset.h b/src/dusk/script/module/display/moduletileset.h index ad466927..5489e089 100644 --- a/src/dusk/script/module/display/moduletileset.h +++ b/src/dusk/script/module/display/moduletileset.h @@ -31,14 +31,6 @@ int moduleTilesetIndex(lua_State *l); */ int moduleTilesetToString(lua_State *l); -/** - * Lua function to get a tileset by name. - * - * @param l The Lua state. - * @return The number of return values on the Lua stack. - */ -int moduleTilesetGetByName(lua_State *l); - /** * Lua function to get the UV coordinates for a tile index in a tileset. * @@ -53,4 +45,12 @@ int moduleTilesetTileGetUV(lua_State *l); * @param l The Lua state. * @return The number of return values on the Lua stack. */ -int moduleTilesetPositionGetUV(lua_State *l); \ No newline at end of file +int moduleTilesetPositionGetUV(lua_State *l); + +/** + * Lua function to load a tileset from a texture and tile dimensions. + * + * @param l The Lua state. + * @return The number of return values on the Lua stack. + */ +int moduleTilesetLoad(lua_State *l); \ No newline at end of file diff --git a/src/duskrpg/CMakeLists.txt b/src/duskrpg/CMakeLists.txt index 4e447bcb..8fe7a502 100644 --- a/src/duskrpg/CMakeLists.txt +++ b/src/duskrpg/CMakeLists.txt @@ -10,7 +10,7 @@ target_include_directories(${DUSK_LIBRARY_TARGET_NAME} ) # Subdirs +add_subdirectory(game) add_subdirectory(item) -add_subdirectory(map) add_subdirectory(story) add_subdirectory(script) \ No newline at end of file diff --git a/src/dusktrivia/game/CMakeLists.txt b/src/duskrpg/game/CMakeLists.txt similarity index 80% rename from src/dusktrivia/game/CMakeLists.txt rename to src/duskrpg/game/CMakeLists.txt index be80fa06..3121dec3 100644 --- a/src/dusktrivia/game/CMakeLists.txt +++ b/src/duskrpg/game/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2026 Dominic Masters -# +# Copyright (c) 2025 Dominic Masters +# # This software is released under the MIT License. # https://opensource.org/licenses/MIT diff --git a/src/dusktrivia/game/game.c b/src/duskrpg/game/game.c similarity index 100% rename from src/dusktrivia/game/game.c rename to src/duskrpg/game/game.c diff --git a/src/dusktrivia/game/game.h b/src/duskrpg/game/game.h similarity index 71% rename from src/dusktrivia/game/game.h rename to src/duskrpg/game/game.h index 45d1c717..18677fda 100644 --- a/src/dusktrivia/game/game.h +++ b/src/duskrpg/game/game.h @@ -9,21 +9,21 @@ #include "error/error.h" /** - * Initializes the game. + * Initializes the game systems and loads the initial game state. * * @return An error code indicating success or failure. */ errorret_t gameInit(void); /** - * Updates the game state. Should be called every frame. + * Updates the game state. This should be called every frame. * * @return An error code indicating success or failure. */ errorret_t gameUpdate(void); /** - * Disposes of game resources. Should be called when the game is shutting down. + * Disposes of game resources and shuts down the game systems. * * @return An error code indicating success or failure. */ diff --git a/src/duskrpg/map/map.c b/src/duskrpg/map/map.c deleted file mode 100644 index 1c0a7c46..00000000 --- a/src/duskrpg/map/map.c +++ /dev/null @@ -1,272 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "map.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "asset/asset.h" -#include "display/texture/texture.h" -// #include "entity/entity.h" -#include "util/string.h" -#include "time/time.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 - errorChain(mapPositionSet(position)); - 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); - - // Determine directory path (it is dirname) - stringCopy(MAP.dirPath, path, MAP_FILE_PATH_MAX); - char_t *last = stringFindLastChar(MAP.dirPath, '/'); - if(last == NULL) errorThrow("Invalid map file path"); - - // Store filename, sans extension - stringCopy(MAP.fileName, last + 1, MAP_FILE_PATH_MAX); - *last = '\0'; // Terminate to get directory path - - last = stringFindLastChar(MAP.fileName, '.'); - 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; - - // 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++) { - mapchunk_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)); - i++; - } - } - } - - errorOk(); -} - -errorret_t mapPositionSet(const chunkpos_t newPos) { - if(!mapIsLoaded()) errorThrow("No map loaded"); - - const chunkpos_t curPos = MAP.chunkPosition; - if(mapChunkPositionIsEqual(curPos, newPos)) { - errorOk(); - } - - // Determine which chunks remain loaded - chunkindex_t chunksRemaining[MAP_CHUNK_COUNT] = {0}; - chunkindex_t chunksFreed[MAP_CHUNK_COUNT] = {0}; - - uint32_t remainingCount = 0; - uint32_t freedCount = 0; - - for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { - // Will this chunk remain loaded? - mapchunk_t *chunk = &MAP.chunks[i]; - if( - chunk->position.x >= newPos.x && - chunk->position.x < newPos.x + MAP_CHUNK_WIDTH && - - chunk->position.y >= newPos.y && - chunk->position.y < newPos.y + MAP_CHUNK_HEIGHT && - - chunk->position.z >= newPos.z && - chunk->position.z < newPos.z + MAP_CHUNK_DEPTH - ) { - // Stays loaded - chunksRemaining[remainingCount++] = i; - continue; - } - - // Not remaining loaded - chunksFreed[freedCount++] = i; - } - - // Unload the freed chunks - for(chunkindex_t i = 0; i < freedCount; i++) { - mapchunk_t *chunk = &MAP.chunks[chunksFreed[i]]; - mapChunkUnload(chunk); - } - - // This can probably be optimized later, for now we check each chunk and see - // if it needs loading or not, and update the chunk order - chunkindex_t orderIndex = 0; - for(chunkunit_t zOff = 0; zOff < MAP_CHUNK_DEPTH; zOff++) { - for(chunkunit_t yOff = 0; yOff < MAP_CHUNK_HEIGHT; yOff++) { - for(chunkunit_t xOff = 0; xOff < MAP_CHUNK_WIDTH; xOff++) { - const chunkpos_t newChunkPos = { - newPos.x + xOff, newPos.y + yOff, newPos.z + zOff - }; - - // Is this chunk already loaded (was not unloaded earlier)? - chunkindex_t chunkIndex = -1; - for(chunkindex_t i = 0; i < remainingCount; i++) { - mapchunk_t *chunk = &MAP.chunks[chunksRemaining[i]]; - if(!mapChunkPositionIsEqual(chunk->position, newChunkPos)) continue; - chunkIndex = chunksRemaining[i]; - break; - } - - // Need to load this chunk - if(chunkIndex == -1) { - // Find a freed chunk to reuse - chunkIndex = chunksFreed[--freedCount]; - mapchunk_t *chunk = &MAP.chunks[chunkIndex]; - chunk->position = newChunkPos; - errorChain(mapChunkLoad(chunk)); - } - - MAP.chunkOrder[orderIndex++] = &MAP.chunks[chunkIndex]; - } - } - } - - // Update map position - MAP.chunkPosition = newPos; - - errorOk(); -} - -void mapUpdate() { - #ifdef DUSK_TIME_DYNAMIC - if(!TIME.dynamicUpdate) return; - #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]); - } -} - -void mapChunkUnload(mapchunk_t* chunk) { - // for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { - // if(chunk->entities[i] == 0xFF) break; - // 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]); - } -} - -errorret_t mapChunkLoad(mapchunk_t* chunk) { - if(!mapIsLoaded()) errorThrow("No map loaded"); - - char_t buffer[160]; - - // 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)); - - // Get chunk filepath. - snprintf(buffer, sizeof(buffer), "%s/chunks/%d_%d_%d.dmc", - MAP.dirPath, - 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, - position.z - MAP.chunkPosition.z - }; - - if( - relPos.x < 0 || relPos.y < 0 || relPos.z < 0 || - relPos.x >= MAP_CHUNK_WIDTH || - relPos.y >= MAP_CHUNK_HEIGHT || - relPos.z >= MAP_CHUNK_DEPTH - ) { - return -1; - } - - return chunkPosToIndex(&relPos); -} - -mapchunk_t* mapGetChunk(const uint8_t index) { - if(index >= MAP_CHUNK_COUNT) return NULL; - if(!mapIsLoaded()) return NULL; - return MAP.chunkOrder[index]; -} - -maptile_t mapGetTile(const worldpos_t position) { - if(!mapIsLoaded()) return TILE_SHAPE_NULL; - - chunkpos_t chunkPos; - worldPosToChunkPos(&position, &chunkPos); - chunkindex_t chunkIndex = mapGetChunkIndexAt(chunkPos); - if(chunkIndex == -1) return TILE_SHAPE_NULL; - - mapchunk_t *chunk = mapGetChunk(chunkIndex); - assertNotNull(chunk, "Chunk pointer cannot be NULL"); - chunktileindex_t tileIndex = worldPosToChunkTileIndex(&position); - return chunk->tiles[tileIndex]; -} \ No newline at end of file diff --git a/src/duskrpg/map/map.h b/src/duskrpg/map/map.h deleted file mode 100644 index 24a615ae..00000000 --- a/src/duskrpg/map/map.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "mapchunk.h" - -#define MAP_FILE_PATH_MAX 128 - -typedef struct map_s { - char_t filePath[MAP_FILE_PATH_MAX]; - char_t dirPath[MAP_FILE_PATH_MAX]; - char_t fileName[MAP_FILE_PATH_MAX]; - - mapchunk_t chunks[MAP_CHUNK_COUNT]; - mapchunk_t *chunkOrder[MAP_CHUNK_COUNT]; - chunkpos_t chunkPosition; -} map_t; - -extern map_t MAP; - -/** - * Initializes the map. - * - * @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(); - -/** - * 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. - */ -void mapUpdate(); - -/** - * Renders the map. - */ -void mapRender(); - -/** - * Disposes of the map. - */ -void mapDispose(); - -/** - * Sets the map position and updates chunks accordingly. - * - * @param newPos The new chunk position. - * @return An error code. - */ -errorret_t mapPositionSet(const chunkpos_t newPos); - -/** - * Unloads a chunk. - * - * @param chunk The chunk to unload. - */ -void mapChunkUnload(mapchunk_t* chunk); - -/** - * Loads a chunk. - * - * @param chunk The chunk to load. - * @return An error code. - */ -errorret_t mapChunkLoad(mapchunk_t* chunk); - -/** - * Gets the index of a chunk, within the world, at the given position. - * - * @param position The chunk position. - * @return The index of the chunk, or -1 if out of bounds. - */ -chunkindex_t mapGetChunkIndexAt(const chunkpos_t position); - -/** - * Gets a chunk by its index. - * - * @param chunkIndex The index of the chunk. - * @return A pointer to the chunk. - */ -mapchunk_t * mapGetChunk(const uint8_t chunkIndex); - -/** - * Gets the tile at the given world position. - * - * @param position The world position. - * @return The tile at that position, or TILE_NULL if the chunk is unloaded. - */ -maptile_t mapGetTile(const worldpos_t position); \ No newline at end of file diff --git a/src/duskrpg/map/mapchunk.c b/src/duskrpg/map/mapchunk.c deleted file mode 100644 index 5af06ab4..00000000 --- a/src/duskrpg/map/mapchunk.c +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "mapchunk.h" - -uint32_t mapChunkGetTileindex(const chunkpos_t position) { - return ( - (position.z * CHUNK_WIDTH * CHUNK_HEIGHT) + - (position.y * CHUNK_WIDTH) + - position.x - ); -} - -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); - } -} \ No newline at end of file diff --git a/src/duskrpg/map/mapchunk.h b/src/duskrpg/map/mapchunk.h deleted file mode 100644 index c65304d4..00000000 --- a/src/duskrpg/map/mapchunk.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "maptile.h" -#include "worldpos.h" -#include "display/mesh/quad.h" - -typedef struct chunk_s { - chunkpos_t position; - maptile_t tiles[CHUNK_TILE_COUNT]; - - uint8_t meshCount; - meshvertex_t vertices[CHUNK_VERTEX_COUNT_MAX]; - mesh_t meshes[CHUNK_MESH_COUNT_MAX]; - uint8_t entities[CHUNK_ENTITY_COUNT_MAX]; -} mapchunk_t; - -/** - * Gets the tile index for a tile position within a chunk. - * - * @param position The position within the chunk. - * @return The tile index within the chunk. - */ -uint32_t mapChunkGetTileindex(const chunkpos_t position); - -/** - * Checks if two chunk positions are equal. - * - * @param a The first chunk position. - * @param b The second chunk position. - * @return true if equal, false otherwise. - */ -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); \ No newline at end of file diff --git a/src/duskrpg/map/maptile.c b/src/duskrpg/map/maptile.c deleted file mode 100644 index 15280a83..00000000 --- a/src/duskrpg/map/maptile.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "maptile.h" - -bool_t mapTileIsWalkable(const maptile_t tile) { - switch(tile) { - case TILE_SHAPE_NULL: - return false; - - default: - return true; - } -} - -bool_t mapTileIsRamp(const maptile_t tile) { - switch(tile) { - case TILE_SHAPE_RAMP_NORTH: - case TILE_SHAPE_RAMP_SOUTH: - case TILE_SHAPE_RAMP_EAST: - case TILE_SHAPE_RAMP_WEST: - case TILE_SHAPE_RAMP_NORTHEAST: - case TILE_SHAPE_RAMP_NORTHWEST: - case TILE_SHAPE_RAMP_SOUTHEAST: - case TILE_SHAPE_RAMP_SOUTHWEST: - return true; - - default: - return false; - } -} \ No newline at end of file diff --git a/src/duskrpg/map/maptile.h b/src/duskrpg/map/maptile.h deleted file mode 100644 index a18ece5b..00000000 --- a/src/duskrpg/map/maptile.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "duskdefs.h" -// #include "rpg/entity/entitydir.h" - -typedef uint8_t maptile_t; - -/** - * Returns whether or not the given tile is walkable. - * - * @param tile The tile to check. - * @return bool_t True if walkable, false if not. - */ -bool_t mapTileIsWalkable(const maptile_t tile); - -/** - * Returns whether or not the given tile is a ramp tile. - * - * @param tile The tile to check. - * @return bool_t True if ramp, false if not. - */ -bool_t mapTileIsRamp(const maptile_t tile); \ No newline at end of file diff --git a/src/duskrpg/map/worldpos.c b/src/duskrpg/map/worldpos.c deleted file mode 100644 index 3cdd7100..00000000 --- a/src/duskrpg/map/worldpos.c +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "worldpos.h" -#include "assert/assert.h" - -bool_t worldPosIsEqual(const worldpos_t a, const worldpos_t b) { - return a.x == b.x && a.y == b.y && a.z == b.z; -} - -void chunkPosToWorldPos(const chunkpos_t* chunkPos, worldpos_t* out) { - assertNotNull(chunkPos, "Chunk position pointer cannot be NULL"); - assertNotNull(out, "Output world position pointer cannot be NULL"); - - out->x = (worldunit_t)(chunkPos->x * CHUNK_WIDTH); - out->y = (worldunit_t)(chunkPos->y * CHUNK_HEIGHT); - out->z = (worldunit_t)(chunkPos->z * CHUNK_DEPTH); -} - -void worldPosToChunkPos(const worldpos_t* worldPos, chunkpos_t* out) { - assertNotNull(worldPos, "World position pointer cannot be NULL"); - assertNotNull(out, "Output chunk position pointer cannot be NULL"); - - if(worldPos->x < 0) { - out->x = (chunkunit_t)((worldPos->x - (CHUNK_WIDTH - 1)) / CHUNK_WIDTH); - } else { - out->x = (chunkunit_t)(worldPos->x / CHUNK_WIDTH); - } - - if(worldPos->y < 0) { - out->y = (chunkunit_t)((worldPos->y - (CHUNK_HEIGHT - 1)) / CHUNK_HEIGHT); - } else { - out->y = (chunkunit_t)(worldPos->y / CHUNK_HEIGHT); - } - - if(worldPos->z < 0) { - out->z = (chunkunit_t)((worldPos->z - (CHUNK_DEPTH - 1)) / CHUNK_DEPTH); - } else { - out->z = (chunkunit_t)(worldPos->z / CHUNK_DEPTH); - } -} - -chunktileindex_t worldPosToChunkTileIndex(const worldpos_t* worldPos) { - assertNotNull(worldPos, "World position pointer cannot be NULL"); - - uint8_t localX, localY, localZ; - if(worldPos->x < 0) { - localX = (uint8_t)( - (CHUNK_WIDTH - 1) - ((-worldPos->x - 1) % CHUNK_WIDTH) - ); - } else { - localX = (uint8_t)(worldPos->x % CHUNK_WIDTH); - } - - if(worldPos->y < 0) { - localY = (uint8_t)( - (CHUNK_HEIGHT - 1) - ((-worldPos->y - 1) % CHUNK_HEIGHT) - ); - } else { - localY = (uint8_t)(worldPos->y % CHUNK_HEIGHT); - } - - if(worldPos->z < 0) { - localZ = (uint8_t)( - (CHUNK_DEPTH - 1) - ((-worldPos->z - 1) % CHUNK_DEPTH) - ); - } else { - localZ = (uint8_t)(worldPos->z % CHUNK_DEPTH); - } - - chunktileindex_t chunkTileIndex = (chunktileindex_t)( - (localZ * CHUNK_WIDTH * CHUNK_HEIGHT) + - (localY * CHUNK_WIDTH) + - localX - ); - assertTrue( - chunkTileIndex < CHUNK_TILE_COUNT, - "Calculated chunk tile index is out of bounds" - ); - return chunkTileIndex; -} - -chunkindex_t chunkPosToIndex(const chunkpos_t* pos) { - assertNotNull(pos, "Chunk position pointer cannot be NULL"); - - chunkindex_t chunkIndex = (chunkindex_t)( - (pos->z * MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT) + - (pos->y * MAP_CHUNK_WIDTH) + - pos->x - ); - - return chunkIndex; -} \ No newline at end of file diff --git a/src/duskrpg/map/worldpos.h b/src/duskrpg/map/worldpos.h deleted file mode 100644 index a9432e4e..00000000 --- a/src/duskrpg/map/worldpos.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "duskdefs.h" - -#define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) - -#define MAP_CHUNK_WIDTH 3 -#define MAP_CHUNK_HEIGHT 3 -#define MAP_CHUNK_DEPTH 3 -#define MAP_CHUNK_COUNT (MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT * MAP_CHUNK_DEPTH) - -typedef int16_t worldunit_t; -typedef int16_t chunkunit_t; -typedef int16_t chunkindex_t; -typedef uint32_t chunktileindex_t; - -typedef int32_t worldunits_t; -typedef int32_t chunkunits_t; - -typedef struct worldpos_s { - worldunit_t x, y, z; -} worldpos_t; - -typedef struct chunkpos_t { - chunkunit_t x, y, z; -} chunkpos_t; - -/** - * Compares two world positions for equality. - * - * @param a The first world position. - * @param b The second world position. - * @return true if equal, false otherwise. - */ -bool_t worldPosIsEqual(const worldpos_t a, const worldpos_t b); - -/** - * Converts a world position to a chunk position. - * - * @param worldPos The world position. - * @param out The output chunk position. - */ -void chunkPosToWorldPos(const chunkpos_t* chunkPos, worldpos_t* out); - -/** - * Converts a chunk position to a world position. - * - * @param worldPos The world position. - * @param out The output chunk position. - */ -void worldPosToChunkPos(const worldpos_t* worldPos, chunkpos_t* out); - -/** - * Converts a position in world-space to an index inside a chunk that the tile - * resides in. - * - * @param worldPos The world position. - * @return The tile index within the chunk. - */ -chunktileindex_t worldPosToChunkTileIndex(const worldpos_t* worldPos); - -/** - * Converts a chunk position to a world position. - * - * @param worldPos The world position. - * @param out The output chunk position. - */ -chunkindex_t chunkPosToIndex(const chunkpos_t* pos); \ No newline at end of file diff --git a/src/duskrpg/script/module/CMakeLists.txt b/src/duskrpg/script/module/CMakeLists.txt index ad8bff24..1c70c1d9 100644 --- a/src/duskrpg/script/module/CMakeLists.txt +++ b/src/duskrpg/script/module/CMakeLists.txt @@ -5,5 +5,4 @@ # Subdirectories add_subdirectory(item) -add_subdirectory(map) add_subdirectory(story) \ No newline at end of file diff --git a/src/duskrpg/script/module/map/modulemap.c b/src/duskrpg/script/module/map/modulemap.c deleted file mode 100644 index 08fd4d9a..00000000 --- a/src/duskrpg/script/module/map/modulemap.c +++ /dev/null @@ -1,60 +0,0 @@ -/** - * 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; -} \ No newline at end of file diff --git a/src/duskrpg/script/module/map/modulemap.h b/src/duskrpg/script/module/map/modulemap.h deleted file mode 100644 index ff08cce8..00000000 --- a/src/duskrpg/script/module/map/modulemap.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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); \ No newline at end of file diff --git a/src/duskrpg/script/scriptgame.h b/src/duskrpg/script/scriptgame.h index 3e460b45..de516489 100644 --- a/src/duskrpg/script/scriptgame.h +++ b/src/duskrpg/script/scriptgame.h @@ -8,9 +8,7 @@ #pragma once #include "script/module/item/moduleitem.h" #include "script/module/story/modulestoryflag.h" -#include "script/module/map/modulemap.h" #define SCRIPT_GAME_LIST \ { .name = "item", .callback = moduleItem }, \ - { .name = "storyflag", .callback = moduleStoryFlag }, \ - { .name = "map", .callback = moduleMap }, \ No newline at end of file + { .name = "storyflag", .callback = moduleStoryFlag }, \ No newline at end of file diff --git a/src/dusktrivia/CMakeLists.txt b/src/dusktrivia/CMakeLists.txt deleted file mode 100644 index f0d950aa..00000000 --- a/src/dusktrivia/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Includes -target_include_directories(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - ${CMAKE_CURRENT_LIST_DIR} -) - -# Subdirs -add_subdirectory(game) -add_subdirectory(script) \ No newline at end of file diff --git a/src/dusktrivia/script/CMakeLists.txt b/src/dusktrivia/script/CMakeLists.txt deleted file mode 100644 index 26438bbd..00000000 --- a/src/dusktrivia/script/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Subdirs -add_subdirectory(module) \ No newline at end of file diff --git a/src/dusktrivia/script/module/CMakeLists.txt b/src/dusktrivia/script/module/CMakeLists.txt deleted file mode 100644 index 2e6d0d14..00000000 --- a/src/dusktrivia/script/module/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2026 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Subdirectories \ No newline at end of file diff --git a/src/dusktrivia/script/scriptgame.h b/src/dusktrivia/script/scriptgame.h deleted file mode 100644 index 127e1eb3..00000000 --- a/src/dusktrivia/script/scriptgame.h +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once \ No newline at end of file