From a495179e5fc0baa2a83e5e25687f231806427022 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 5 Dec 2025 14:41:13 -0600 Subject: [PATCH] Prog --- assets/script/test.lua | 8 +- src/engine/engine.c | 15 +--- src/rpg/rpg.c | 14 +-- src/script/func/scriptfunccamera.h | 16 ++++ src/script/func/scriptfuncentity.h | 135 +++++++++++++++++++++++++++++ src/script/func/scriptfuncsystem.h | 38 ++++++++ src/script/scriptcontext.c | 37 +++----- src/script/scriptcontext.h | 8 -- src/script/scriptmanager.h | 3 +- tools/assetstool/processscript.py | 6 +- tools/dusk/defs.py | 4 +- 11 files changed, 226 insertions(+), 58 deletions(-) create mode 100644 src/script/func/scriptfunccamera.h create mode 100644 src/script/func/scriptfuncentity.h create mode 100644 src/script/func/scriptfuncsystem.h diff --git a/assets/script/test.lua b/assets/script/test.lua index 9ba9463..a29fe4e 100644 --- a/assets/script/test.lua +++ b/assets/script/test.lua @@ -1,7 +1,3 @@ -function testFunction() - print("Hello from testFunction!") -end +player = entityAdd(ENTITY_TYPE_PLAYER, 3, 6, 1) -function doAdd(a, b) - return a + b -end \ No newline at end of file +print("Player entity ID: " .. player) \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index a318591..a235611 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -34,25 +34,18 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { inputInit(); errorChain(assetInit()); errorChain(localeManagerInit()); + errorChain(scriptManagerInit()); errorChain(displayInit()); errorChain(uiInit()); errorChain(rpgInit()); errorChain(sceneManagerInit()); - errorChain(scriptManagerInit()); + + // Run the initial script. + scriptcontext_t testCtx; errorChain(scriptContextInit(&testCtx)); errorChain(scriptContextExecFile(&testCtx, "script/test.dsf")); - errorChain(scriptContextCallFunc(&testCtx, "testFunction", NULL, 0, NULL)); - - scriptvalue_t args[2] = { - { .type = SCRIPT_VALUE_TYPE_INT, .value.intValue = 5 }, - { .type = SCRIPT_VALUE_TYPE_INT, .value.intValue = 7 } - }; - scriptvalue_t ret = { .type = SCRIPT_VALUE_TYPE_INT }; - errorChain(scriptContextCallFunc(&testCtx, "doAdd", args, 2, &ret)); - printf("doAdd returned: %d\n", ret.value.intValue); - scriptContextDispose(&testCtx); errorOk(); diff --git a/src/rpg/rpg.c b/src/rpg/rpg.c index 01f4393..e97368d 100644 --- a/src/rpg/rpg.c +++ b/src/rpg/rpg.c @@ -27,13 +27,13 @@ errorret_t rpgInit(void) { rpgTextboxInit(); // TEST: Create some entities. - uint8_t entIndex = entityGetAvailable(); - assertTrue(entIndex != 0xFF, "No available entity slots!."); - entity_t *ent = &ENTITIES[entIndex]; - entityInit(ent, ENTITY_TYPE_PLAYER); - RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY; - RPG_CAMERA.followEntity.followEntityId = ent->id; - ent->position.x = 2, ent->position.y = 2; + // uint8_t entIndex = entityGetAvailable(); + // assertTrue(entIndex != 0xFF, "No available entity slots!."); + // entity_t *ent = &ENTITIES[entIndex]; + // entityInit(ent, ENTITY_TYPE_PLAYER); + // RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY; + // RPG_CAMERA.followEntity.followEntityId = ent->id; + // ent->position.x = 2, ent->position.y = 2; // All Good! errorOk(); diff --git a/src/script/func/scriptfunccamera.h b/src/script/func/scriptfunccamera.h new file mode 100644 index 0000000..de86975 --- /dev/null +++ b/src/script/func/scriptfunccamera.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/scriptcontext.h" +#include "assert/assert.h" + + + +void scriptFuncCamera(scriptcontext_t *context) { + assertNotNull(context, "Script context cannot be NULL"); +} \ No newline at end of file diff --git a/src/script/func/scriptfuncentity.h b/src/script/func/scriptfuncentity.h new file mode 100644 index 0000000..ea0d3a7 --- /dev/null +++ b/src/script/func/scriptfuncentity.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/scriptcontext.h" +#include "rpg/entity/entity.h" +#include "assert/assert.h" + +int32_t scriptFuncEntityAdd(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + assertTrue(lua_isinteger(L, 1), "Expected integer entity type"); + + lua_Integer entityType = luaL_checkinteger(L, 1); + assertTrue( + entityType >= ENTITY_TYPE_NULL && entityType < ENTITY_TYPE_COUNT, + "Invalid entity type passed to scriptFuncEntityAdd" + ); + + // Pop entity + uint8_t available = entityGetAvailable(); + if(available == 0xFF) { + lua_pushnil(L); + return 1; + } + + entity_t *ent = &ENTITIES[available]; + entityInit(ent, (entitytype_t)entityType); + + // May include X, Y and/or Z + if(lua_isinteger(L, 2)) { + lua_Integer xPos = luaL_checkinteger(L, 2); + ent->position.x = (int32_t)xPos; + } + if(lua_isinteger(L, 3)) { + lua_Integer yPos = luaL_checkinteger(L, 3); + ent->position.y = (int32_t)yPos; + } + if(lua_isinteger(L, 4)) { + lua_Integer zPos = luaL_checkinteger(L, 4); + ent->position.z = (int32_t)zPos; + } + + // Send entity id. + lua_pushinteger(L, ent->id); + return 1; +} + +int32_t scriptFuncEntitySetX(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + assertTrue(lua_isinteger(L, 1), "Expected integer entity id"); + assertTrue(lua_isinteger(L, 2), "Expected integer x position"); + + lua_Integer entityId = luaL_checkinteger(L, 1); + lua_Integer xPos = luaL_checkinteger(L, 2); + + assertTrue( + entityId >= 0 && entityId < ENTITY_COUNT, + "Invalid entity id passed to scriptFuncEntitySetX" + ); + + entity_t *ent = &ENTITIES[entityId]; + assertTrue( + ent->type != ENTITY_TYPE_NULL, + "Cannot set position of NULL entity in scriptFuncEntitySetX" + ); + + ent->position.x = (int32_t)xPos; + + return 0; +} + +int32_t scriptFuncEntitySetY(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + assertTrue(lua_isinteger(L, 1), "Expected integer entity id"); + assertTrue(lua_isinteger(L, 2), "Expected integer y position"); + + lua_Integer entityId = luaL_checkinteger(L, 1); + lua_Integer yPos = luaL_checkinteger(L, 2); + + assertTrue( + entityId >= 0 && entityId < ENTITY_COUNT, + "Invalid entity id passed to scriptFuncEntitySetY" + ); + + entity_t *ent = &ENTITIES[entityId]; + assertTrue( + ent->type != ENTITY_TYPE_NULL, + "Cannot set position of NULL entity in scriptFuncEntitySetY" + ); + + ent->position.y = (int32_t)yPos; + + return 0; +} + +int32_t scriptFuncEntitySetZ(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + assertTrue(lua_isinteger(L, 1), "Expected integer entity id"); + assertTrue(lua_isinteger(L, 2), "Expected integer z position"); + + lua_Integer entityId = luaL_checkinteger(L, 1); + lua_Integer zPos = luaL_checkinteger(L, 2); + + assertTrue( + entityId >= 0 && entityId < ENTITY_COUNT, + "Invalid entity id passed to scriptFuncEntitySetZ" + ); + + entity_t *ent = &ENTITIES[entityId]; + assertTrue( + ent->type != ENTITY_TYPE_NULL, + "Cannot set position of NULL entity in scriptFuncEntitySetZ" + ); + + ent->position.z = (int32_t)zPos; + + return 0; +} + +void scriptFuncEntity(scriptcontext_t *context) { + assertNotNull(context, "Script context cannot be NULL"); + + scriptContextRegFunc(context, "entityAdd", scriptFuncEntityAdd); + scriptContextRegFunc(context, "entitySetX", scriptFuncEntitySetX); + scriptContextRegFunc(context, "entitySetY", scriptFuncEntitySetY); + scriptContextRegFunc(context, "entitySetZ", scriptFuncEntitySetZ); +} \ No newline at end of file diff --git a/src/script/func/scriptfuncsystem.h b/src/script/func/scriptfuncsystem.h new file mode 100644 index 0000000..c022377 --- /dev/null +++ b/src/script/func/scriptfuncsystem.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/scriptcontext.h" +#include "debug/debug.h" +#include "assert/assert.h" + +int32_t scriptContextPrint(lua_State *L) { + assertNotNull(L, "Lua state cannot be NULL"); + + int n = lua_gettop(L); + luaL_Buffer b; + luaL_buffinit(L, &b); + + for (int i = 1; i <= n; ++i) { + size_t len; + const char *s = luaL_tolstring(L, i, &len); // converts any value to string + luaL_addlstring(&b, s, len); + lua_pop(L, 1); // pop result of luaL_tolstring + if (i < n) luaL_addlstring(&b, "\t", 1); + } + + luaL_pushresult(&b); + const char *msg = lua_tostring(L, -1); + debugPrint("%s\n", msg); + return 0; // no values returned to Lua +} + +void scriptFuncSystem(scriptcontext_t *context) { + assertNotNull(context, "Script context cannot be NULL"); + + scriptContextRegFunc(context, "print", scriptContextPrint); +} \ No newline at end of file diff --git a/src/script/scriptcontext.c b/src/script/scriptcontext.c index ef68d5e..361edda 100644 --- a/src/script/scriptcontext.c +++ b/src/script/scriptcontext.c @@ -11,6 +11,10 @@ #include "util/memory.h" #include "debug/debug.h" +#include "script/func/scriptfunccamera.h" +#include "script/func/scriptfuncentity.h" +#include "script/func/scriptfuncsystem.h" + errorret_t scriptContextInit(scriptcontext_t *context) { assertNotNull(context, "Script context cannot be NULL"); @@ -23,8 +27,9 @@ errorret_t scriptContextInit(scriptcontext_t *context) { } luaL_openlibs(context->luaState); - // Register shared functions - scriptContextRegFunc(context, "print", scriptContextPrint); + // Register functions + scriptFuncSystem(context); + scriptFuncEntity(context); errorOk(); } @@ -112,6 +117,13 @@ errorret_t scriptContextCallFunc( retValue->value.floatValue = (float)lua_tonumber(context->luaState, -1); break; + case SCRIPT_VALUE_TYPE_BOOL: + if(!lua_isboolean(context->luaState, -1)) { + errorThrow("Expected boolean return value from '%s'", fnName); + } + retValue->value.boolValue = lua_toboolean(context->luaState, -1); + break; + // case SCRIPT_VALUE_TYPE_STRING: // if(!lua_isstring(context->luaState, -1)) { // errorThrow("Expected string return value from '%s'", fnName); @@ -164,27 +176,6 @@ errorret_t scriptContextExecFile(scriptcontext_t *ctx, const char_t *fname) { errorOk(); } -int32_t scriptContextPrint(lua_State *L) { - assertNotNull(L, "Lua state cannot be NULL"); - - int n = lua_gettop(L); - luaL_Buffer b; - luaL_buffinit(L, &b); - - for (int i = 1; i <= n; ++i) { - size_t len; - const char *s = luaL_tolstring(L, i, &len); // converts any value to string - luaL_addlstring(&b, s, len); - lua_pop(L, 1); // pop result of luaL_tolstring - if (i < n) luaL_addlstring(&b, "\t", 1); - } - - luaL_pushresult(&b); - const char *msg = lua_tostring(L, -1); - debugPrint("%s\n", msg); - return 0; // no values returned to Lua -} - void scriptContextDispose(scriptcontext_t *context) { assertNotNull(context, "Script context cannot be NULL"); assertNotNull(context->luaState, "Lua state is not initialized"); diff --git a/src/script/scriptcontext.h b/src/script/scriptcontext.h index 97b9568..b78eb57 100644 --- a/src/script/scriptcontext.h +++ b/src/script/scriptcontext.h @@ -74,14 +74,6 @@ errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script); */ errorret_t scriptContextExecFile(scriptcontext_t *ctx, const char_t *fname); -/** - * Overridden print function for Lua scripts to output to debug. - * - * @param L The Lua state. - * @return The number of return values. - */ -int32_t scriptContextPrint(lua_State *L); - /** * Dispose of a script context. * diff --git a/src/script/scriptmanager.h b/src/script/scriptmanager.h index 9566095..04ebe8e 100644 --- a/src/script/scriptmanager.h +++ b/src/script/scriptmanager.h @@ -7,9 +7,10 @@ #pragma once #include "error/error.h" +#include "scriptcontext.h" typedef struct scriptmanager_s { - void *nothing; + scriptcontext_t mainContext; } scriptmanager_t; extern scriptmanager_t SCRIPT_MANAGER; diff --git a/tools/assetstool/processscript.py b/tools/assetstool/processscript.py index 26eddd5..a3aebcf 100644 --- a/tools/assetstool/processscript.py +++ b/tools/assetstool/processscript.py @@ -3,7 +3,7 @@ import os from assetstool.args import args from assetstool.assetcache import assetCache, assetGetCache from assetstool.assethelpers import getAssetRelativePath -from dusk.defs import defs +from dusk.defs import fileDefs def processScript(asset): cache = assetGetCache(asset['path']) @@ -16,6 +16,10 @@ def processScript(asset): # TODO: I will precompile or minify the Lua code here in the future + # Replace all definitions in the code + for key, val in fileDefs.items(): + luaCode = luaCode.replace(key, str(val)) + # Create output Dusk Script File (DSF) data data = "" data += "DSF" diff --git a/tools/dusk/defs.py b/tools/dusk/defs.py index c85219d..5f5c795 100644 --- a/tools/dusk/defs.py +++ b/tools/dusk/defs.py @@ -1,4 +1,4 @@ -from dotenv import load_dotenv +from dotenv import load_dotenv, dotenv_values import os import sys @@ -13,6 +13,8 @@ if not os.path.isfile(duskDefsPath): load_dotenv(dotenv_path=duskDefsPath) defs = {key: os.getenv(key) for key in os.environ.keys()} +fileDefs = dotenv_values(dotenv_path=duskDefsPath) + # Parsed out definitions CHUNK_WIDTH = int(defs.get('CHUNK_WIDTH')) CHUNK_HEIGHT = int(defs.get('CHUNK_HEIGHT'))