we ball I guess

This commit is contained in:
2026-06-07 19:51:54 -05:00
parent f8c9d33df2
commit 51388c90d5
42 changed files with 2233 additions and 30 deletions
+1
View File
@@ -20,6 +20,7 @@ console_t CONSOLE;
void consoleInit(void) {
memoryZero(&CONSOLE, sizeof(console_t));
CONSOLE.visible = true;
#ifdef DUSK_CONSOLE_POSIX
threadMutexInit(&CONSOLE.printMutex);
+8 -1
View File
@@ -10,6 +10,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
)
# Subdirs
add_subdirectory(animation)
add_subdirectory(asset)
add_subdirectory(console)
add_subdirectory(display)
@@ -17,7 +18,13 @@ add_subdirectory(engine)
add_subdirectory(entity)
add_subdirectory(event)
add_subdirectory(input)
add_subdirectory(item)
add_subdirectory(locale)
add_subdirectory(math)
add_subdirectory(overworld)
add_subdirectory(require)
add_subdirectory(save)
add_subdirectory(scene)
add_subdirectory(system)
add_subdirectory(story)
add_subdirectory(system)
add_subdirectory(ui)
@@ -0,0 +1,10 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
moduleanimation.c
moduleeasing.c
)
@@ -0,0 +1,88 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "moduleanimation.h"
#include "animation/animation.h"
typedef struct {
keyframe_t keyframes[MODULE_ANIMATION_KEYFRAME_MAX];
animation_t anim;
} moduleanimationdata_t;
scriptproto_t MODULE_ANIMATION_PROTO;
moduleBaseFunction(moduleAnimationCtor) {
if(argc < 1 || !jerry_value_is_array(args[0])) {
return moduleBaseThrow(
"Animation: expected array of keyframe objects"
);
}
uint32_t len = jerry_array_length(args[0]);
if(len == 0) {
return moduleBaseThrow(
"Animation: keyframe array must not be empty"
);
}
const uint16_t count = len > (uint32_t)MODULE_ANIMATION_KEYFRAME_MAX
? (uint16_t)MODULE_ANIMATION_KEYFRAME_MAX
: (uint16_t)len;
moduleanimationdata_t *d = (moduleanimationdata_t *)memoryAllocate(
sizeof(moduleanimationdata_t)
);
for(uint16_t i = 0; i < count; i++) {
jerry_value_t elem = jerry_object_get_index(args[0], (uint32_t)i);
jerry_value_t jtm = moduleBaseGetProp(elem, "time");
jerry_value_t jvl = moduleBaseGetProp(elem, "value");
jerry_value_t jea = moduleBaseGetProp(elem, "easing");
d->keyframes[i].time = moduleBaseValueFloat(jtm);
d->keyframes[i].value = moduleBaseValueFloat(jvl);
d->keyframes[i].easing = jerry_value_is_number(jea)
? (easingtype_t)moduleBaseValueInt(jea)
: EASING_LINEAR;
jerry_value_free(jea);
jerry_value_free(jvl);
jerry_value_free(jtm);
jerry_value_free(elem);
}
animationInit(&d->anim, d->keyframes, count);
jerry_object_set_native_ptr(
callInfo->this_value, &MODULE_ANIMATION_PROTO.info, d
);
return jerry_undefined();
}
moduleBaseFunction(moduleAnimationGetValue) {
moduleBaseRequireArgs(1);
moduleBaseRequireNumber(0);
moduleanimationdata_t *d = (moduleanimationdata_t *)scriptProtoGetValue(
&MODULE_ANIMATION_PROTO, callInfo->this_value
);
if(!d) return jerry_undefined();
return jerry_number(
(double)animationGetValue(&d->anim, moduleBaseArgFloat(0))
);
}
void moduleAnimationInit(void) {
scriptProtoInit(
&MODULE_ANIMATION_PROTO, "Animation",
sizeof(moduleanimationdata_t), moduleAnimationCtor
);
scriptProtoDefineFunc(
&MODULE_ANIMATION_PROTO, "getValue", moduleAnimationGetValue
);
}
void moduleAnimationDispose(void) {
scriptProtoDispose(&MODULE_ANIMATION_PROTO);
}
@@ -0,0 +1,42 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
#include "util/memory.h"
/** Maximum keyframes per Animation instance. */
#define MODULE_ANIMATION_KEYFRAME_MAX 64
extern scriptproto_t MODULE_ANIMATION_PROTO;
/**
* new Animation(keyframes) — creates an Animation from a JS array of
* `{time, value, easing?}` descriptor objects.
*
* @param args[0] Array of keyframe descriptors.
*/
moduleBaseFunction(moduleAnimationCtor);
/**
* animation.getValue(time) — interpolates the animation at `time`.
*
* @param args[0] Time in seconds (number).
* @return Interpolated float value.
*/
moduleBaseFunction(moduleAnimationGetValue);
/**
* Initializes the Animation module and registers the Animation constructor.
*/
void moduleAnimationInit(void);
/**
* Disposes the Animation module.
*/
void moduleAnimationDispose(void);
@@ -0,0 +1,51 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "moduleeasing.h"
#include "animation/easing.h"
scriptproto_t MODULE_EASING_PROTO;
moduleBaseFunction(moduleEasingApply) {
moduleBaseRequireArgs(2);
moduleBaseRequireNumber(0);
moduleBaseRequireNumber(1);
const int32_t type = moduleBaseArgInt(0);
if(type < 0 || type >= (int32_t)EASING_COUNT) {
return moduleBaseThrow("Easing.apply: invalid easing type");
}
const float_t t = moduleBaseArgFloat(1);
return jerry_number((double)easingApply((easingtype_t)type, t));
}
void moduleEasingInit(void) {
scriptProtoInit(&MODULE_EASING_PROTO, "Easing", 0, NULL);
scriptProtoDefineStaticFunc(
&MODULE_EASING_PROTO, "apply", moduleEasingApply
);
moduleBaseSetInt("EASING_LINEAR", EASING_LINEAR);
moduleBaseSetInt("EASING_IN_SINE", EASING_IN_SINE);
moduleBaseSetInt("EASING_OUT_SINE", EASING_OUT_SINE);
moduleBaseSetInt("EASING_IN_OUT_SINE", EASING_IN_OUT_SINE);
moduleBaseSetInt("EASING_IN_QUAD", EASING_IN_QUAD);
moduleBaseSetInt("EASING_OUT_QUAD", EASING_OUT_QUAD);
moduleBaseSetInt("EASING_IN_OUT_QUAD", EASING_IN_OUT_QUAD);
moduleBaseSetInt("EASING_IN_CUBIC", EASING_IN_CUBIC);
moduleBaseSetInt("EASING_OUT_CUBIC", EASING_OUT_CUBIC);
moduleBaseSetInt("EASING_IN_OUT_CUBIC", EASING_IN_OUT_CUBIC);
moduleBaseSetInt("EASING_IN_QUART", EASING_IN_QUART);
moduleBaseSetInt("EASING_OUT_QUART", EASING_OUT_QUART);
moduleBaseSetInt("EASING_IN_OUT_QUART", EASING_IN_OUT_QUART);
moduleBaseSetInt("EASING_IN_BACK", EASING_IN_BACK);
moduleBaseSetInt("EASING_OUT_BACK", EASING_OUT_BACK);
moduleBaseSetInt("EASING_IN_OUT_BACK", EASING_IN_OUT_BACK);
}
void moduleEasingDispose(void) {
scriptProtoDispose(&MODULE_EASING_PROTO);
}
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
extern scriptproto_t MODULE_EASING_PROTO;
/**
* Easing.apply(type, t) — applies easing function `type` to normalized
* time `t` and returns the eased value.
*
* @param args[0] Easing type constant (EASING_*).
* @param args[1] Normalized input time in [0, 1].
* @return Eased value as a number.
*/
moduleBaseFunction(moduleEasingApply);
/**
* Initializes the Easing module and injects all EASING_* constants.
*/
void moduleEasingInit(void);
/**
* Disposes the Easing module.
*/
void moduleEasingDispose(void);
@@ -6,6 +6,7 @@
*/
#include "modulephysics.h"
#include "util/memory.h"
scriptproto_t MODULE_PHYSICS_PROTO;
@@ -64,8 +65,29 @@ moduleBaseFunction(modulePhysicsSetShape) {
moduleBaseRequireArgs(1);
jscomponent_t *c = modulePhysicsSelf(callInfo);
if(!c) return jerry_undefined();
physicsshape_t shape = entityPhysicsGetShape(c->entityId, c->componentId);
physicsshape_t shape;
memoryZero(&shape, sizeof(physicsshape_t));
shape.type = (physicshapetype_t)moduleBaseArgInt(0);
switch(shape.type) {
case PHYSICS_SHAPE_CUBE:
shape.data.cube.halfExtents[0] = 0.5f;
shape.data.cube.halfExtents[1] = 0.5f;
shape.data.cube.halfExtents[2] = 0.5f;
break;
case PHYSICS_SHAPE_SPHERE:
shape.data.sphere.radius = 0.5f;
break;
case PHYSICS_SHAPE_CAPSULE:
shape.data.capsule.radius = 0.5f;
shape.data.capsule.halfHeight = 0.5f;
break;
case PHYSICS_SHAPE_PLANE:
shape.data.plane.normal[1] = 1.0f;
shape.data.plane.distance = 0.0f;
break;
default:
break;
}
entityPhysicsSetShape(c->entityId, c->componentId, shape);
return jerry_undefined();
}
@@ -0,0 +1,10 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
moduleitem.c
modulebackpack.c
)
@@ -0,0 +1,122 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "modulebackpack.h"
#include "moduleitem.h"
#include "item/backpack.h"
scriptproto_t MODULE_BACKPACK_PROTO;
moduleBaseFunction(moduleBackpackGetIsFull) {
return jerry_boolean(inventoryIsFull(&BACKPACK));
}
moduleBaseFunction(moduleBackpackGetCount) {
moduleBaseRequireArgs(1);
moduleItemRequireId(0, "Backpack.getCount");
const itemid_t id = (itemid_t)moduleBaseArgInt(0);
return jerry_number((double)inventoryGetCount(&BACKPACK, id));
}
moduleBaseFunction(moduleBackpackHas) {
moduleBaseRequireArgs(1);
moduleItemRequireId(0, "Backpack.has");
const itemid_t id = (itemid_t)moduleBaseArgInt(0);
return jerry_boolean(inventoryItemExists(&BACKPACK, id));
}
moduleBaseFunction(moduleBackpackIsItemFull) {
moduleBaseRequireArgs(1);
moduleItemRequireId(0, "Backpack.isItemFull");
const itemid_t id = (itemid_t)moduleBaseArgInt(0);
return jerry_boolean(inventoryItemFull(&BACKPACK, id));
}
moduleBaseFunction(moduleBackpackSet) {
moduleBaseRequireArgs(2);
moduleItemRequireId(0, "Backpack.set");
moduleBaseRequireNumber(1);
const int32_t qty = moduleBaseArgInt(1);
if(qty < 0 || qty > (int32_t)ITEM_STACK_QUANTITY_MAX) {
return moduleBaseThrow("Backpack.set: quantity out of range (0-255)");
}
inventorySet(&BACKPACK, (itemid_t)moduleBaseArgInt(0), (uint8_t)qty);
return jerry_undefined();
}
moduleBaseFunction(moduleBackpackAdd) {
moduleBaseRequireArgs(2);
moduleItemRequireId(0, "Backpack.add");
moduleBaseRequireNumber(1);
const int32_t qty = moduleBaseArgInt(1);
if(qty < 1 || qty > (int32_t)ITEM_STACK_QUANTITY_MAX) {
return moduleBaseThrow("Backpack.add: quantity out of range (1-255)");
}
inventoryAdd(&BACKPACK, (itemid_t)moduleBaseArgInt(0), (uint8_t)qty);
return jerry_undefined();
}
moduleBaseFunction(moduleBackpackRemove) {
moduleBaseRequireArgs(1);
moduleItemRequireId(0, "Backpack.remove");
inventoryRemove(&BACKPACK, (itemid_t)moduleBaseArgInt(0));
return jerry_undefined();
}
moduleBaseFunction(moduleBackpackSort) {
moduleBaseRequireArgs(1);
moduleBaseRequireNumber(0);
const inventorysort_t sortBy = (inventorysort_t)moduleBaseArgInt(0);
if((int32_t)sortBy < 0 || sortBy >= INVENTORY_SORT_COUNT) {
return moduleBaseThrow("Backpack.sort: invalid sort type");
}
const bool_t reverse = (argc > 1 && jerry_value_is_true(args[1]));
inventorySort(&BACKPACK, sortBy, reverse);
return jerry_undefined();
}
void moduleBackpackInit(void) {
scriptProtoInit(
&MODULE_BACKPACK_PROTO, "Backpack", sizeof(uint8_t), NULL
);
scriptProtoDefineStaticProp(
&MODULE_BACKPACK_PROTO, "isFull", moduleBackpackGetIsFull, NULL
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "getCount", moduleBackpackGetCount
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "has", moduleBackpackHas
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "isItemFull", moduleBackpackIsItemFull
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "set", moduleBackpackSet
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "add", moduleBackpackAdd
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "remove", moduleBackpackRemove
);
scriptProtoDefineStaticFunc(
&MODULE_BACKPACK_PROTO, "sort", moduleBackpackSort
);
moduleBaseSetInt(
"INVENTORY_SORT_BY_ID", (int32_t)INVENTORY_SORT_BY_ID
);
moduleBaseSetInt(
"INVENTORY_SORT_BY_TYPE", (int32_t)INVENTORY_SORT_BY_TYPE
);
}
void moduleBackpackDispose(void) {
scriptProtoDispose(&MODULE_BACKPACK_PROTO);
}
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
extern scriptproto_t MODULE_BACKPACK_PROTO;
/**
* Backpack.isFull — true when all storage slots are occupied.
*/
moduleBaseFunction(moduleBackpackGetIsFull);
/**
* Backpack.getCount(itemId) — quantity of itemId (0 if absent).
*
* @param args[0] Item ID constant (ITEM_ID_*).
*/
moduleBaseFunction(moduleBackpackGetCount);
/**
* Backpack.has(itemId) — true if itemId is present with quantity > 0.
*
* @param args[0] Item ID constant (ITEM_ID_*).
*/
moduleBaseFunction(moduleBackpackHas);
/**
* Backpack.isItemFull(itemId) — true if the stack is at max quantity.
*
* @param args[0] Item ID constant (ITEM_ID_*).
*/
moduleBaseFunction(moduleBackpackIsItemFull);
/**
* Backpack.set(itemId, quantity) — set quantity; removes when 0.
*
* @param args[0] Item ID constant (ITEM_ID_*).
* @param args[1] Quantity 0255.
*/
moduleBaseFunction(moduleBackpackSet);
/**
* Backpack.add(itemId, quantity) — add quantity units of itemId.
*
* @param args[0] Item ID constant (ITEM_ID_*).
* @param args[1] Quantity to add (1255).
*/
moduleBaseFunction(moduleBackpackAdd);
/**
* Backpack.remove(itemId) — removes itemId entirely from the backpack.
*
* @param args[0] Item ID constant (ITEM_ID_*).
*/
moduleBaseFunction(moduleBackpackRemove);
/**
* Backpack.sort(sortBy[, reverse]) — sort the backpack contents.
*
* @param args[0] Sort type (INVENTORY_SORT_BY_ID or
* INVENTORY_SORT_BY_TYPE).
* @param args[1] Optional boolean; true to reverse order.
*/
moduleBaseFunction(moduleBackpackSort);
/**
* Initializes the Backpack module, registers all Backpack methods, and
* sets INVENTORY_SORT_BY_ID / INVENTORY_SORT_BY_TYPE as globals.
*/
void moduleBackpackInit(void);
/**
* Disposes the Backpack module.
*/
void moduleBackpackDispose(void);
+47
View File
@@ -0,0 +1,47 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "moduleitem.h"
#include <string.h>
scriptproto_t MODULE_ITEM_PROTO;
moduleBaseFunction(moduleItemGetName) {
moduleBaseRequireArgs(1);
moduleItemRequireId(0, "Item.getName");
const itemid_t id = (itemid_t)moduleBaseArgInt(0);
return jerry_string_sz(ITEMS[id].name);
}
moduleBaseFunction(moduleItemGetType) {
moduleBaseRequireArgs(1);
moduleItemRequireId(0, "Item.getType");
const itemid_t id = (itemid_t)moduleBaseArgInt(0);
return jerry_number((double)ITEMS[id].type);
}
void moduleItemInit(void) {
scriptProtoInit(&MODULE_ITEM_PROTO, "Item", sizeof(uint8_t), NULL);
scriptProtoDefineStaticFunc(
&MODULE_ITEM_PROTO, "getName", moduleItemGetName
);
scriptProtoDefineStaticFunc(
&MODULE_ITEM_PROTO, "getType", moduleItemGetType
);
jerry_value_t result = jerry_eval(
(const jerry_char_t *)ITEM_SCRIPT,
strlen(ITEM_SCRIPT),
JERRY_PARSE_NO_OPTS
);
jerry_value_free(result);
}
void moduleItemDispose(void) {
scriptProtoDispose(&MODULE_ITEM_PROTO);
}
+55
View File
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
#include "item/item.h"
extern scriptproto_t MODULE_ITEM_PROTO;
/**
* Validates an itemid_t argument and returns a type error if invalid.
*
* @param i Argument index.
* @param ctx Context string for error messages.
*/
#define moduleItemRequireId(i, ctx) do { \
if(!jerry_value_is_number(args[(i)])) { \
return moduleBaseThrow(ctx ": itemId must be a number"); \
} \
const itemid_t _id = (itemid_t)moduleBaseArgInt(i); \
if(_id <= ITEM_ID_NULL || _id >= ITEM_ID_COUNT) { \
return moduleBaseThrow(ctx ": invalid item ID"); \
} \
} while(0)
/**
* Item.getName(itemId) — returns the item's string name.
*
* @param args[0] Item ID constant (ITEM_ID_*).
*/
moduleBaseFunction(moduleItemGetName);
/**
* Item.getType(itemId) — returns the item's type constant.
*
* @param args[0] Item ID constant (ITEM_ID_*).
*/
moduleBaseFunction(moduleItemGetType);
/**
* Initializes the Item module, registers Item.getName/getType, and
* evaluates ITEM_SCRIPT to populate ITEM_ID_* and ITEM_TYPE_* constants
* as globals in the script scope.
*/
void moduleItemInit(void);
/**
* Disposes the Item module.
*/
void moduleItemDispose(void);
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
modulelocale.c
)
@@ -0,0 +1,114 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "modulelocale.h"
#include "asset/loader/locale/assetlocaleloader.h"
#include <math.h>
#include <string.h>
#define MODULE_LOCALE_SUBSTITUTION_MAX 4
#define MODULE_LOCALE_BUFFER_SIZE 512
#define MODULE_LOCALE_ID_SIZE 256
scriptproto_t MODULE_LOCALE_PROTO;
moduleBaseFunction(moduleLocaleGetText) {
moduleBaseRequireArgs(1);
moduleBaseRequireString(0);
if(LOCALE.entry == NULL) {
return moduleBaseThrow("Locale.getText: no locale loaded");
}
char_t id[MODULE_LOCALE_ID_SIZE];
moduleBaseToString(args[0], id, sizeof(id));
// Second arg is optional plural count.
int32_t plural = 1;
jerry_length_t subStart = 1;
if(argc > 1 && jerry_value_is_number(args[1])) {
plural = moduleBaseArgInt(1);
subStart = 2;
}
// Collect up to MODULE_LOCALE_SUBSTITUTION_MAX substitution args.
assetlocalearg_t subArgs[MODULE_LOCALE_SUBSTITUTION_MAX];
char_t subStrings[MODULE_LOCALE_SUBSTITUTION_MAX][128];
size_t subCount = 0;
for(jerry_length_t i = subStart; i < argc; i++) {
if(subCount >= MODULE_LOCALE_SUBSTITUTION_MAX) break;
if(jerry_value_is_string(args[i])) {
moduleBaseToString(
args[i], subStrings[subCount], sizeof(subStrings[subCount])
);
subArgs[subCount].type = ASSET_LOCALE_ARG_STRING;
subArgs[subCount].stringValue = subStrings[subCount];
} else if(jerry_value_is_number(args[i])) {
double n = jerry_value_as_number(args[i]);
if(floor(n) == n) {
subArgs[subCount].type = ASSET_LOCALE_ARG_INT;
subArgs[subCount].intValue = (int32_t)n;
} else {
subArgs[subCount].type = ASSET_LOCALE_ARG_FLOAT;
subArgs[subCount].floatValue = (float_t)n;
}
} else {
continue;
}
subCount++;
}
char_t buf[MODULE_LOCALE_BUFFER_SIZE];
assetLocaleGetStringWithArgs(
&LOCALE.entry->data.locale,
id,
plural,
buf,
sizeof(buf),
subCount > 0 ? subArgs : NULL,
subCount
);
return jerry_string_sz(buf);
}
moduleBaseFunction(moduleLocaleSetLocale) {
moduleBaseRequireArgs(1);
moduleBaseRequireString(0);
char_t name[64];
moduleBaseToString(args[0], name, sizeof(name));
const localeinfo_t *locale = NULL;
if(strcmp(name, LOCALE_EN_US.name) == 0) locale = &LOCALE_EN_US;
if(locale == NULL) {
return moduleBaseThrow("Locale.setLocale: unknown locale name");
}
localeManagerSetLocale(locale);
return jerry_undefined();
}
void moduleLocaleInit(void) {
scriptProtoInit(
&MODULE_LOCALE_PROTO, "Locale", sizeof(uint8_t), NULL
);
scriptProtoDefineStaticFunc(
&MODULE_LOCALE_PROTO, "getText", moduleLocaleGetText
);
scriptProtoDefineStaticFunc(
&MODULE_LOCALE_PROTO, "setLocale", moduleLocaleSetLocale
);
}
void moduleLocaleDispose(void) {
scriptProtoDispose(&MODULE_LOCALE_PROTO);
}
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
#include "locale/localemanager.h"
extern scriptproto_t MODULE_LOCALE_PROTO;
/**
* Locale.getText(id[, pluralCount[, arg1, ...]]) — returns the
* translated string for the given message ID.
*
* @param args[0] Message ID string.
* @param args[1] Optional plural count (number). Defaults to 1.
* @param args[2..5] Optional substitution args (string or number).
*/
moduleBaseFunction(moduleLocaleGetText);
/**
* Locale.setLocale(name) — switches the active locale by name.
*
* @param args[0] Locale name string, e.g. "en-US".
*/
moduleBaseFunction(moduleLocaleSetLocale);
/**
* Initializes the Locale module and registers Locale.getText/setLocale.
*/
void moduleLocaleInit(void);
/**
* Disposes the Locale module.
*/
void moduleLocaleDispose(void);
+27
View File
@@ -6,6 +6,8 @@
*/
#include "modulelist.h"
#include "script/module/animation/moduleanimation.h"
#include "script/module/animation/moduleeasing.h"
#include "script/module/asset/moduleasset.h"
#include "script/module/console/moduleconsole.h"
#include "script/module/display/modulecolor.h"
@@ -16,13 +18,22 @@
#include "script/module/engine/moduletimeout.h"
#include "script/module/entity/moduleentity.h"
#include "script/module/input/moduleinput.h"
#include "script/module/item/moduleitem.h"
#include "script/module/item/modulebackpack.h"
#include "script/module/locale/modulelocale.h"
#include "script/module/save/modulesave.h"
#include "script/module/math/modulevec3.h"
#include "script/module/overworld/moduleoverworld.h"
#include "script/module/require/modulerequire.h"
#include "script/module/scene/modulescene.h"
#include "script/module/story/modulestory.h"
#include "script/module/system/modulesystem.h"
#include "script/module/ui/moduletextbox.h"
void moduleListInit(void) {
moduleAnimationInit();
moduleEasingInit();
moduleEventInit();
moduleTextureInit();
moduleColorInit();
@@ -35,9 +46,16 @@ void moduleListInit(void) {
moduleVec3Init();
moduleEntityInit();
moduleInputInit();
moduleItemInit();
moduleBackpackInit();
moduleLocaleInit();
moduleSaveInit();
moduleOverworldInit();
moduleRequireInit();
moduleSceneInit();
moduleStoryInit();
moduleSystemInit();
moduleTextboxInit();
}
void moduleListUpdate(void) {
@@ -46,9 +64,18 @@ void moduleListUpdate(void) {
}
void moduleListDispose(void) {
moduleTextboxDispose();
moduleSystemDispose();
moduleOverworldDispose();
moduleEasingDispose();
moduleAnimationDispose();
moduleStoryDispose();
moduleSceneDispose();
moduleRequireDispose();
moduleSaveDispose();
moduleLocaleDispose();
moduleBackpackDispose();
moduleItemDispose();
moduleInputDispose();
moduleEntityDispose();
moduleVec3Dispose();
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
moduleoverworld.c
)
@@ -0,0 +1,73 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "moduleoverworld.h"
#include "overworld/map.h"
scriptproto_t MODULE_OVERWORLD_PROTO;
moduleBaseFunction(moduleOverworldLoadMap) {
moduleBaseRequireArgs(1);
moduleBaseRequireString(0);
char_t handle[MAP_HANDLE_MAX];
moduleBaseToString(args[0], handle, (jerry_size_t)MAP_HANDLE_MAX);
errorret_t err = mapLoad(handle);
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleOverworldIsLoaded) {
return jerry_boolean(mapIsLoaded());
}
moduleBaseFunction(moduleOverworldSetPosition) {
moduleBaseRequireArgs(3);
moduleBaseRequireNumber(0);
moduleBaseRequireNumber(1);
moduleBaseRequireNumber(2);
tilepos_t pos;
pos.x = (tileunit_t)moduleBaseArgInt(0);
pos.y = (tileunit_t)moduleBaseArgInt(1);
pos.z = (tileunit_t)moduleBaseArgInt(2);
errorret_t err = mapPositionSet(pos);
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleOverworldUpdate) {
errorret_t err = mapUpdate();
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleOverworldJsDispose) {
mapDispose();
return jerry_undefined();
}
void moduleOverworldInit(void) {
scriptProtoInit(&MODULE_OVERWORLD_PROTO, "Overworld", 0, NULL);
scriptProtoDefineStaticFunc(
&MODULE_OVERWORLD_PROTO, "loadMap", moduleOverworldLoadMap
);
scriptProtoDefineStaticFunc(
&MODULE_OVERWORLD_PROTO, "isLoaded", moduleOverworldIsLoaded
);
scriptProtoDefineStaticFunc(
&MODULE_OVERWORLD_PROTO, "setPosition", moduleOverworldSetPosition
);
scriptProtoDefineStaticFunc(
&MODULE_OVERWORLD_PROTO, "update", moduleOverworldUpdate
);
scriptProtoDefineStaticFunc(
&MODULE_OVERWORLD_PROTO, "dispose", moduleOverworldJsDispose
);
}
void moduleOverworldDispose(void) {
scriptProtoDispose(&MODULE_OVERWORLD_PROTO);
}
@@ -0,0 +1,57 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
extern scriptproto_t MODULE_OVERWORLD_PROTO;
/**
* Overworld.loadMap(handle) — loads the map with the given handle string.
* Disposes any currently loaded map first.
*
* @param args[0] Map handle string (max 31 chars).
*/
moduleBaseFunction(moduleOverworldLoadMap);
/**
* Overworld.isLoaded() — returns true when a map is currently loaded.
*
* @return boolean
*/
moduleBaseFunction(moduleOverworldIsLoaded);
/**
* Overworld.setPosition(x, y, z) — slides the chunk window to the tile
* position (x, y, z).
*
* @param args[0] Tile X (integer).
* @param args[1] Tile Y (integer).
* @param args[2] Tile Z (integer).
*/
moduleBaseFunction(moduleOverworldSetPosition);
/**
* Overworld.update() — advances the map one tick.
*/
moduleBaseFunction(moduleOverworldUpdate);
/**
* Overworld.dispose() — unloads the current map.
*/
moduleBaseFunction(moduleOverworldJsDispose);
/**
* Initializes the Overworld module and registers the Overworld global.
*/
void moduleOverworldInit(void);
/**
* Disposes the Overworld module.
*/
void moduleOverworldDispose(void);
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
modulesave.c
)
+61
View File
@@ -0,0 +1,61 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "modulesave.h"
scriptproto_t MODULE_SAVE_PROTO;
moduleBaseFunction(moduleSaveExists) {
moduleBaseRequireArgs(1);
moduleSaveRequireSlot(0, "Save.exists");
return jerry_boolean(saveExists((uint8_t)moduleBaseArgInt(0)));
}
moduleBaseFunction(moduleSaveLoad) {
moduleBaseRequireArgs(1);
moduleSaveRequireSlot(0, "Save.load");
errorret_t err = saveLoad((uint8_t)moduleBaseArgInt(0));
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleSaveWrite) {
moduleBaseRequireArgs(1);
moduleSaveRequireSlot(0, "Save.write");
errorret_t err = saveWrite((uint8_t)moduleBaseArgInt(0));
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleSaveDelete) {
moduleBaseRequireArgs(1);
moduleSaveRequireSlot(0, "Save.delete");
errorret_t err = saveDelete((uint8_t)moduleBaseArgInt(0));
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
void moduleSaveInit(void) {
scriptProtoInit(&MODULE_SAVE_PROTO, "Save", sizeof(uint8_t), NULL);
scriptProtoDefineStaticFunc(
&MODULE_SAVE_PROTO, "exists", moduleSaveExists
);
scriptProtoDefineStaticFunc(
&MODULE_SAVE_PROTO, "load", moduleSaveLoad
);
scriptProtoDefineStaticFunc(
&MODULE_SAVE_PROTO, "write", moduleSaveWrite
);
scriptProtoDefineStaticFunc(
&MODULE_SAVE_PROTO, "delete", moduleSaveDelete
);
}
void moduleSaveDispose(void) {
scriptProtoDispose(&MODULE_SAVE_PROTO);
}
+67
View File
@@ -0,0 +1,67 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
#include "save/save.h"
extern scriptproto_t MODULE_SAVE_PROTO;
/**
* Validates a save-slot argument and returns a type error if invalid.
*
* @param i Argument index.
* @param ctx Context string for error messages.
*/
#define moduleSaveRequireSlot(i, ctx) do { \
if(!jerry_value_is_number(args[(i)])) { \
return moduleBaseThrow(ctx ": slot must be a number"); \
} \
const int32_t _s = moduleBaseArgInt(i); \
if(_s < 0 || _s >= (int32_t)SAVE_FILE_COUNT_MAX) { \
return moduleBaseThrow(ctx ": invalid save slot"); \
} \
} while(0)
/**
* Save.exists(slot) — true if a save file is present for the slot.
*
* @param args[0] Save slot index (0 to SAVE_FILE_COUNT_MAX - 1).
*/
moduleBaseFunction(moduleSaveExists);
/**
* Save.load(slot) — loads the save file for the given slot.
*
* @param args[0] Save slot index (0 to SAVE_FILE_COUNT_MAX - 1).
*/
moduleBaseFunction(moduleSaveLoad);
/**
* Save.write(slot) — writes the save file for the given slot.
*
* @param args[0] Save slot index (0 to SAVE_FILE_COUNT_MAX - 1).
*/
moduleBaseFunction(moduleSaveWrite);
/**
* Save.delete(slot) — deletes the save file for the given slot.
*
* @param args[0] Save slot index (0 to SAVE_FILE_COUNT_MAX - 1).
*/
moduleBaseFunction(moduleSaveDelete);
/**
* Initializes the Save module and registers Save.exists/load/write/delete.
*/
void moduleSaveInit(void);
/**
* Disposes the Save module.
*/
void moduleSaveDispose(void);
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
modulestory.c
)
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "modulestory.h"
#include <string.h>
scriptproto_t MODULE_STORY_PROTO;
moduleBaseFunction(moduleStoryGet) {
moduleBaseRequireArgs(1);
moduleStoryRequireFlag(0, "Story.get");
const storyflag_t flag = (storyflag_t)moduleBaseArgInt(0);
return jerry_number((double)storyFlagGet(flag));
}
moduleBaseFunction(moduleStorySet) {
moduleBaseRequireArgs(2);
moduleStoryRequireFlag(0, "Story.set");
moduleBaseRequireNumber(1);
const int32_t val = moduleBaseArgInt(1);
if(val < 0 || val > 255) {
return moduleBaseThrow("Story.set: value out of range (0-255)");
}
storyFlagSet(
(storyflag_t)moduleBaseArgInt(0),
(storyflagvalue_t)val
);
return jerry_undefined();
}
void moduleStoryInit(void) {
scriptProtoInit(&MODULE_STORY_PROTO, "Story", sizeof(uint8_t), NULL);
scriptProtoDefineStaticFunc(
&MODULE_STORY_PROTO, "get", moduleStoryGet
);
scriptProtoDefineStaticFunc(
&MODULE_STORY_PROTO, "set", moduleStorySet
);
jerry_value_t result = jerry_eval(
(const jerry_char_t *)STORY_FLAG_SCRIPT,
strlen(STORY_FLAG_SCRIPT),
JERRY_PARSE_NO_OPTS
);
jerry_value_free(result);
}
void moduleStoryDispose(void) {
scriptProtoDispose(&MODULE_STORY_PROTO);
}
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/module/modulebase.h"
#include "script/scriptproto.h"
#include "story/storyflag.h"
extern scriptproto_t MODULE_STORY_PROTO;
/**
* Validates a storyflag_t argument and returns a type error if invalid.
*
* @param i Argument index.
* @param ctx Context string for error messages.
*/
#define moduleStoryRequireFlag(i, ctx) do { \
if(!jerry_value_is_number(args[(i)])) { \
return moduleBaseThrow(ctx ": flagId must be a number"); \
} \
const storyflag_t _f = (storyflag_t)moduleBaseArgInt(i); \
if(_f <= STORY_FLAG_NULL || _f >= STORY_FLAG_COUNT) { \
return moduleBaseThrow(ctx ": invalid story flag ID"); \
} \
} while(0)
/**
* Story.get(flagId) — returns the current uint8 value of a story flag.
*
* @param args[0] Story flag constant (STORY_FLAG_*).
*/
moduleBaseFunction(moduleStoryGet);
/**
* Story.set(flagId, value) — sets a story flag to a uint8 value.
*
* @param args[0] Story flag constant (STORY_FLAG_*).
* @param args[1] Value 0255.
*/
moduleBaseFunction(moduleStorySet);
/**
* Initializes the Story module, registers Story.get/set, and evaluates
* STORY_FLAG_SCRIPT to inject STORY_FLAG_* constants as globals.
*/
void moduleStoryInit(void);
/**
* Disposes the Story module.
*/
void moduleStoryDispose(void);
+9
View File
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
moduletextbox.c
)
+110
View File
@@ -0,0 +1,110 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "moduletextbox.h"
#include "ui/uitextbox.h"
#include "input/inputaction.h"
scriptproto_t MODULE_TEXTBOX_PROTO;
moduleBaseFunction(moduleTextboxSetText) {
moduleBaseRequireArgs(1);
moduleBaseRequireString(0);
char_t buf[UI_TEXTBOX_TEXT_MAX];
moduleBaseToString(args[0], buf, sizeof(buf));
uiTextboxSetText(buf);
return jerry_undefined();
}
moduleBaseFunction(moduleTextboxNextPage) {
uiTextboxNextPage();
return jerry_undefined();
}
moduleBaseFunction(moduleTextboxUpdate) {
errorret_t err = uiTextboxUpdate();
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleTextboxDraw) {
errorret_t err = uiTextboxDraw();
if(errorIsNotOk(err)) return moduleBaseThrowError(err);
return jerry_undefined();
}
moduleBaseFunction(moduleTextboxSetAdvanceAction) {
moduleBaseRequireArgs(1);
moduleBaseRequireNumber(0);
const inputaction_t action = (inputaction_t)moduleBaseArgInt(0);
if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) {
return moduleBaseThrow(
"UITextbox.setAdvanceAction: invalid action"
);
}
UI_TEXTBOX.advanceAction = action;
return jerry_undefined();
}
moduleBaseFunction(moduleTextboxGetIsPageComplete) {
return jerry_boolean(uiTextboxPageIsComplete());
}
moduleBaseFunction(moduleTextboxGetHasNextPage) {
return jerry_boolean(uiTextboxHasNextPage());
}
moduleBaseFunction(moduleTextboxGetCurrentPage) {
return jerry_number((double)UI_TEXTBOX.currentPage);
}
moduleBaseFunction(moduleTextboxGetPageCount) {
return jerry_number((double)UI_TEXTBOX.pageCount);
}
void moduleTextboxInit(void) {
scriptProtoInit(
&MODULE_TEXTBOX_PROTO, "UITextbox", sizeof(uint8_t), NULL
);
scriptProtoDefineStaticFunc(
&MODULE_TEXTBOX_PROTO, "setText", moduleTextboxSetText
);
scriptProtoDefineStaticFunc(
&MODULE_TEXTBOX_PROTO, "nextPage", moduleTextboxNextPage
);
scriptProtoDefineStaticFunc(
&MODULE_TEXTBOX_PROTO, "update", moduleTextboxUpdate
);
scriptProtoDefineStaticFunc(
&MODULE_TEXTBOX_PROTO, "draw", moduleTextboxDraw
);
scriptProtoDefineStaticFunc(
&MODULE_TEXTBOX_PROTO, "setAdvanceAction",
moduleTextboxSetAdvanceAction
);
scriptProtoDefineStaticProp(
&MODULE_TEXTBOX_PROTO, "isPageComplete",
moduleTextboxGetIsPageComplete, NULL
);
scriptProtoDefineStaticProp(
&MODULE_TEXTBOX_PROTO, "hasNextPage",
moduleTextboxGetHasNextPage, NULL
);
scriptProtoDefineStaticProp(
&MODULE_TEXTBOX_PROTO, "currentPage",
moduleTextboxGetCurrentPage, NULL
);
scriptProtoDefineStaticProp(
&MODULE_TEXTBOX_PROTO, "pageCount",
moduleTextboxGetPageCount, NULL
);
}
void moduleTextboxDispose(void) {
scriptProtoDispose(&MODULE_TEXTBOX_PROTO);
}
+65
View File
@@ -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 "script/module/modulebase.h"
#include "script/scriptproto.h"
extern scriptproto_t MODULE_TEXTBOX_PROTO;
/**
* UITextbox.setText(text) — sets the textbox content and rebuilds layout.
*
* @param args[0] Null-terminated text string.
*/
moduleBaseFunction(moduleTextboxSetText);
/**
* UITextbox.nextPage() — advances to the next page; no-op on last page.
*/
moduleBaseFunction(moduleTextboxNextPage);
/**
* UITextbox.update() — advances the typewriter scroll by one tick.
*/
moduleBaseFunction(moduleTextboxUpdate);
/**
* UITextbox.draw() — draws the frame and visible text for this frame.
*/
moduleBaseFunction(moduleTextboxDraw);
/**
* UITextbox.setAdvanceAction(action) — sets the input action that
* advances the textbox when held.
*
* @param args[0] Input action constant (INPUT_ACTION_*).
*/
moduleBaseFunction(moduleTextboxSetAdvanceAction);
/** @return true when the typewriter has fully revealed the current page. */
moduleBaseFunction(moduleTextboxGetIsPageComplete);
/** @return true when at least one more page follows the current one. */
moduleBaseFunction(moduleTextboxGetHasNextPage);
/** @return Zero-based index of the current page. */
moduleBaseFunction(moduleTextboxGetCurrentPage);
/** @return Total number of pages for the current text. */
moduleBaseFunction(moduleTextboxGetPageCount);
/**
* Initializes the UITextbox module and registers all methods and
* properties on the UITextbox global.
*/
void moduleTextboxInit(void);
/**
* Disposes the UITextbox module.
*/
void moduleTextboxDispose(void);