diff --git a/meson.build b/meson.build index 157ba06b..eb69348a 100644 --- a/meson.build +++ b/meson.build @@ -96,13 +96,6 @@ endif if host_machine.system() == 'windows' deps += cc.find_library('d3d11') deps += cc.find_library('ws2_32', required:true) - # For Windows, you may need to install OpenBLAS or Intel MKL - # and adjust these library names accordingly -# deps += cc.find_library('openblas', required:false) -# if not cc.find_library('openblas', required:false).found() -# deps += cc.find_library('blas', required:false) -# deps += cc.find_library('lapacke', required:false) -# endif deps += cc.find_library('dbghelp') deps += cc.find_library('winmm') deps += cc.find_library('setupapi') @@ -177,15 +170,6 @@ endif deps += dependency('threads') -# Try to find system-installed chipmunk first -chipmunk_dep = dependency('chipmunk', static: true, required: false) -if not chipmunk_dep.found() - message('⚙ System chipmunk not found, building subproject...') - deps += dependency('chipmunk', static:true) -else - deps += chipmunk_dep -endif - # Try to find system-installed curl first curl_dep = dependency('libcurl', static: true, required: false) if not curl_dep.found() @@ -339,14 +323,10 @@ endforeach if host_machine.system() == 'windows' exe_ext = '.exe' + link += '-Wl,--export-all-symbols' else exe_ext = '' -endif - -strip_enabled = ['release', 'minsize'].contains(get_option('buildtype')) - -if strip_enabled - add_project_link_arguments('-s', language: ['c', 'cpp']) + link += '-Wl,-export_dynamic' endif cell_bin = executable('cell_bin', sources, @@ -361,10 +341,18 @@ cell_dep = declare_dependency( link_with: cell_bin ) +cell_so = both_libraries( + 'cell', + sources, + include_directories: includers, + dependencies: deps, + install : true, +) + # Create core.zip from scripts folder qop_target = custom_target('core.qop', output: 'core.qop', - command: ['sh', '-c', ' mkdir -p .cell && cell qopconv -d ' + meson.project_source_root() / 'scripts . core.qop'], + command: ['sh', '-c', ' qopconv -d ' + meson.project_source_root() / 'scripts . core.qop'], build_by_default: true, build_always_stale: true ) @@ -388,12 +376,8 @@ install_headers('source/cell.h', 'source/jsffi.h') install_headers('source/blob.h') install_headers('source/quickjs.h') install_headers('source/qjs_macros.h') -install_headers('source/qjs_blob.h') install_headers('source/qjs_common.h') install_headers('source/qjs_actor.h') -install_headers('source/qjs_fd.h') -install_headers('source/qjs_os.h') -install_headers('source/qjs_time.h') install_headers('source/HandmadeMath.h') install_headers('source/render.h') diff --git a/scripts/engine.cm b/scripts/engine.cm index 6621d72e..2bcfd27c 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -4,6 +4,24 @@ cell.DOC = Symbol() var ACTORDATA = cell.hidden.actorsym var SYSYM = '__SYSTEM__' +// Get hidden modules from cell.hidden before stripping it +var hidden = cell.hidden + +var use_dyn = hidden.use_dyn +var dylib_ext = hidden.dylib_ext +var load_internal = hidden.load_internal + +function use_embed(name) { + return load_internal(name) +} + +var actor_mod = use_embed('actor') +var wota = use_embed('wota') +var nota = use_embed('nota') +var enet = use_embed('enet') +var fd = use_embed('fd') +var console_mod = use_embed('console') + var ENETSERVICE = 0.1 var REPLYTIMEOUT = 60 // seconds before replies are ignored @@ -38,8 +56,6 @@ function console_rec(line, file, msg) { // time: [${time.text("mb d yyyy h:nn:ss")}] } -var console_mod = cell.hidden.console - globalThis.log = {} log.console = function(msg) { @@ -62,16 +78,7 @@ log.system = function(msg) { log.console(msg) } -// Get hidden modules from cell.hidden before stripping it -var hidden = cell.hidden -var actor_mod = hidden.actor -var wota = hidden.wota -var use_embed = hidden.use_embed -var use_dyn = hidden.use_dyn -var enet = hidden.enet -var nota = hidden.nota -var fd = use_embed('fd') log.console(fd.getcwd()) log.console(cell.args.program) @@ -110,13 +117,6 @@ function mkdir_p(dir) { } } -// Wota decode timing tracking -var wota_decode_times = [] -var last_wota_flush = 0 - -// Strip hidden from cell so nothing else can access it -// But first, list files in the core QOP package - var qop = use_embed('qop') var core_qop = qop.open(hidden.core_qop_blob) var utf8 = use_embed('utf8') @@ -194,11 +194,16 @@ function resolve_path(requested, pkg_context, ext) { function check(path, pkg, isCore) { if (isCore) { try { - core_qop.read(path) - return { path: path, package_name: null, isCore: true } + var blob = core_qop.read(path) + if (blob) { + // log.console("check: found in core: " + path) + return { path: path, package_name: null, isCore: true } + } + return null } catch (e) { return null } } if (is_file(path)) { + // log.console("check: found file: " + path) return { path: path, package_name: pkg, isCore: false } } return null @@ -299,6 +304,26 @@ globalThis.use = function use(file, ...args) { // Check embedded modules first (these are always available) var embed_mod = use_embed(requested) + if (!embed_mod) embed_mod = load_internal(requested) + + // Check for dynamic library + var dyn_mod = null + var dyn_path = resolve_path(requested, current_package, dylib_ext) + if (dyn_path) { + try { + if (!dyn_path.isCore) { + dyn_mod = use_dyn(dyn_path.path) + log.console("use: loaded dynamic library " + dyn_path.path) + } + } catch (e) { + log.console(`use: failed to load dynamic library ${dyn_path.path}: ${e}`) + } + } + + // If we have a dynamic module, use it as the embedded module (context) + if (dyn_mod) { + embed_mod = dyn_mod + } // Resolve the module path with package awareness var resolved = resolve_path(requested, current_package, MOD_EXT) @@ -306,7 +331,7 @@ globalThis.use = function use(file, ...args) { // Generate cache key based on resolution var cache_key = resolved ? (resolved.isCore ? 'core:' + resolved.path : resolved.path) - : requested + : (dyn_path ? dyn_path.path : requested) if (use_cache[cache_key]) return use_cache[cache_key] @@ -315,7 +340,7 @@ globalThis.use = function use(file, ...args) { if (!resolved && !embed_mod) throw new Error(`Module ${file} could not be found (package context: ${current_package || 'none'})`) - // If only embedded module exists, return it + // If only embedded/dynamic module exists, return it if (!resolved && embed_mod) { use_cache[cache_key] = embed_mod return embed_mod diff --git a/source/cell.c b/source/cell.c index 2a71ad4a..6eb70472 100644 --- a/source/cell.c +++ b/source/cell.c @@ -61,9 +61,6 @@ #define QOP_IMPLEMENTATION #include "qop.h" -#define JS_BLOB_IMPLEMENTATION -#include "qjs_blob.h" - #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) @@ -179,7 +176,6 @@ void actor_free(cell_rt *actor) } hmfree(actor->timers); - arrfree(actor->module_registry); /* Free all letters in the queue */ for (int i = 0; i < arrlen(actor->letters); i++) { diff --git a/source/cell.h b/source/cell.h index 017b0426..49998e0e 100644 --- a/source/cell.h +++ b/source/cell.h @@ -4,12 +4,19 @@ #include #include "quickjs.h" #include "qjs_macros.h" -#include "qjs_blob.h" #include "blob.h" #ifdef __cplusplus extern "C" { #endif +JSValue js_blob_use(JSContext *js); +// makes a new stone blob from data, copying the data over +JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes); + +// returns undefined if the blob is not stone +void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); + +int js_is_blob(JSContext *js, JSValue v); #ifdef HAVE_MIMALLOC typedef struct mi_heap_s mi_heap_t; @@ -39,8 +46,6 @@ typedef struct letter { #define ACTOR_RECLAIMING 4 // Actor running GC #define ACTOR_SLOW 5 // Actor going slowly; deprioritize -typedef JSValue (*MODULEFN)(JSContext *js); - extern int tracy_profiling_enabled; typedef struct tagMTRand { @@ -48,11 +53,6 @@ typedef struct tagMTRand { int32_t index; } MTRand; -typedef struct { - const char *name; - MODULEFN fn; -} ModuleEntry; - typedef struct cell_rt { JSContext *context; #ifdef HAVE_MIMALLOC @@ -64,8 +64,6 @@ mi_heap_t *heap; void *init_wota; - ModuleEntry *module_registry; - /* Protects JSContext usage */ SDL_Mutex *mutex; /* for everything else */ SDL_Mutex *msg_mutex; /* For message queue and timers queue */ diff --git a/source/cell_qoi.c b/source/cell_qoi.c index 43f018f5..e879746d 100644 --- a/source/cell_qoi.c +++ b/source/cell_qoi.c @@ -1,6 +1,6 @@ -#include "cell_qoi.h" +#define QOI_IMPLEMENTATION #include "qoi.h" -#include "qjs_blob.h" +#include "cell.h" #include "qjs_sdl.h" #include #include diff --git a/source/cell_qoi.h b/source/cell_qoi.h deleted file mode 100644 index 5b699e4b..00000000 --- a/source/cell_qoi.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CELL_QOI_H -#define CELL_QOI_H - -#include - -JSValue js_qoi_use(JSContext *js); - -#endif // CELL_QOI_H \ No newline at end of file diff --git a/source/config.c b/source/config.c index 65051114..286ff702 100644 --- a/source/config.c +++ b/source/config.c @@ -39,12 +39,3 @@ #define CGLTF_IMPLEMENTATION #include "cgltf.h" - -#define PAR_SHAPES_IMPLEMENTATION -#include "par/par_shapes.h" - -#define PAR_STREAMLINES_IMPLEMENTATION -#include "par/par_streamlines.h" - -#define QOI_IMPLEMENTATION -#include "qoi.h" diff --git a/source/jsffi.c b/source/jsffi.c index bb241838..2e98d574 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -1,8 +1,6 @@ #include "jsffi.h" #include "font.h" #include "datastream.h" -#include "qjs_sdl.h" -#include "qjs_sdl_input.h" #include "transform.h" #include "stb_ds.h" #include "stb_image.h" @@ -17,41 +15,17 @@ #include #include "render.h" #include "HandmadeMath.h" -#include "par/par_streamlines.h" -#include "par/par_shapes.h" #include #include "cute_aseprite.h" #include "cell.h" -#include "qjs_blob.h" -#include "qjs_dmon.h" -#include "qjs_enet.h" -#include "qjs_nota.h" #include "qjs_wota.h" -#include "qjs_soloud.h" -#include "qjs_sdl.h" -#include "qjs_sdl_video.h" -#include "qjs_math.h" -#include "qjs_geometry.h" -#include "qjs_transform.h" -#include "qjs_sprite.h" -#include "qjs_sdl_gpu.h" -#include "qjs_os.h" -#include "qjs_actor.h" -#include "qjs_spline.h" -#include "qjs_js.h" -#include "qjs_debug.h" -#include "qjs_sdl_surface.h" -#include "qjs_sdl.h" -#include "qjs_kim.h" -#include "qjs_utf8.h" -#include "qjs_fit.h" -#include "qjs_text.h" -#include "qjs_staef.h" -#include "qjs_wildstar.h" -#include "qjs_fd.h" -#include "qjs_qop.h" +#if defined(_WIN32) +#include +#else +#include +#endif // External transform function declarations extern JSClassID js_transform_id; @@ -749,7 +723,7 @@ JSC_CCALL(os_make_gif, void *pixels = stbi_load_gif_from_memory(raw, rawlen, &delays, &width, &height, &frames, &n, 4); if (!pixels) { - return JS_ThrowReferenceError(js, "Failed to decode GIF: %s", stbi_failure_reason()); + return JS_ThrowReferenceError(js, "1decode GIF: %s", stbi_failure_reason()); } // Always return an array of surfaces, even for single frame @@ -1026,40 +1000,105 @@ static const JSCFunctionListEntry js_video_funcs[] = { MIST_FUNC_DEF(os, make_video, 1), }; -JSC_SCALL(os_use_embed, - cell_rt *rt = JS_GetContextOpaque(js); - ModuleEntry *module_registry = rt->module_registry; - for (int i = 0; i < arrlen(module_registry); i++) { - if (strcmp(str,module_registry[i].name) == 0) { - ret = module_registry[i].fn(js); - break; - } - } -) +static void *get_main_module_handle() { +#if defined(_WIN32) + return GetModuleHandle(NULL); +#else + return dlopen(NULL, RTLD_LAZY); +#endif +} -JSC_SCALL(os_use_dyn, - SDL_SharedObject *ptr = SDL_LoadObject(str); - if (!ptr) - return JS_ThrowReferenceError(js, "Shared library %s could not be loaded", SDL_GetError()); +static void *get_symbol(void *handle, const char *name) { +#if defined(_WIN32) + return (void*)GetProcAddress((HMODULE)handle, name); +#else + return dlsym(handle, name); +#endif +} + +JSC_CCALL(os_use_dyn, + const char *path = JS_ToCString(js, argv[0]); + if (!path) return JS_ThrowTypeError(js, "path must be a string"); - JSValue (*js_use)(JSContext*); - js_use = (JSValue (*)(JSContext*))SDL_LoadFunction(ptr, "use"); + // 1. Load the library +#if defined(_WIN32) + HMODULE handle = LoadLibraryA(path); +#else + void *handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); +#endif - if (!js_use) - ret = JS_ThrowReferenceError(js, "Shared library %s has no use function", str); - else - ret = js_use(js); + if (!handle) { + JS_FreeCString(js, path); +#if defined(_WIN32) + return JS_ThrowReferenceError(js, "Could not load library"); +#else + return JS_ThrowReferenceError(js, "Could not load library: %s", dlerror()); +#endif + } - SDL_UnloadObject(ptr); + // 2. Construct symbol name: js__use + // Extract basename from path + const char *base = strrchr(path, '/'); +#if defined(_WIN32) + const char *base2 = strrchr(path, '\\'); + if (base2 > base) base = base2; +#endif + + if (base) base++; // Skip the slash + else base = path; // No slash, use whole path + + char name_buf[256]; + const char *dot = strrchr(base, '.'); + size_t len = dot ? (size_t)(dot - base) : strlen(base); + if (len > 100) len = 100; // Safety cap + + char clean_base[128]; + memcpy(clean_base, base, len); + clean_base[len] = '\0'; + + snprintf(name_buf, sizeof(name_buf), "js_%s_use", clean_base); + + // 3. Get the symbol + typedef JSValue (*init_fn)(JSContext*); + init_fn fn = (init_fn)get_symbol(handle, name_buf); + + JS_FreeCString(js, path); + + if (!fn) { + // Try without stripping extension? No, standard is usually without. + // Maybe try "js_main_use"? No. + // Let's stick to the plan. +#if defined(_WIN32) + FreeLibrary(handle); +#else + dlclose(handle); +#endif + return JS_ThrowReferenceError(js, "Could not find entry point %s in library", name_buf); + } + + // 4. Call the function + return fn(js); ) -#define JSSTATIC(NAME, PARENT) \ -js_##NAME = JS_NewObject(js); \ -JS_SetPropertyFunctionList(js, js_##NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs)); \ -JS_SetPrototype(js, js_##NAME, PARENT); \ -JSValue js_miniz_use(JSContext *js); -JSValue js_num_use(JSContext *js); +JSC_SCALL(os_load_internal, + void *handle = get_main_module_handle(); + if (!handle) { + return JS_ThrowReferenceError(js, "Could not get main module handle"); + } + + char func_name[256]; + snprintf(func_name, sizeof(func_name), "js_%s_use", str); + + JSValue (*js_use)(JSContext*) = get_symbol(handle, func_name); + + if (!js_use) { + // Try without "js_" prefix or other variations if needed, but standard is js__use + return JS_NULL; + } + + ret = js_use(js); +) JSValue js_graphics_use(JSContext *js) { JSValue mod = JS_NewObject(js); @@ -1090,83 +1129,18 @@ JSC_CCALL(os_value_id, return argv[0]; ) -#include "qjs_crypto.h" -#include "qjs_time.h" -#include "qjs_http.h" -#include "qjs_wota.h" -#include "qjs_socket.h" -#include "qjs_nota.h" -#include "qjs_layout.h" -#include "qjs_sdl_gpu.h" -#include "cell_qoi.h" - -JSValue js_imgui_use(JSContext *js); -#define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use} - void ffi_load(JSContext *js) { cell_rt *rt = JS_GetContextOpaque(js); - - JS_FreeValue(js, js_blob_use(js)); // juice blob - + JS_FreeValue(js, js_blob_use(js)); + uint64_t rr; + // randombytes is defined in qjs_crypto.c which is linked, but header was removed. + // We declare it here to avoid implicit declaration error. + extern int randombytes(void *buf, size_t n); randombytes(&rr,4); m_seedRand(&rt->mrand, rr); - - // cell modules - arrput(rt->module_registry, MISTLINE(time)); - arrput(rt->module_registry, ((ModuleEntry){"math", js_math_use})); - arrput(rt->module_registry, MISTLINE(blob)); - - // extra - arrput(rt->module_registry, MISTLINE(wildstar)); - arrput(rt->module_registry, ((ModuleEntry){"fd", js_fd_use})); - arrput(rt->module_registry, ((ModuleEntry){"qop", js_qop_use})); - arrput(rt->module_registry, ((ModuleEntry){"os", js_os_use})); - arrput(rt->module_registry, MISTLINE(http)); - arrput(rt->module_registry, MISTLINE(crypto)); - arrput(rt->module_registry, MISTLINE(miniz)); -// arrput(rt->module_registry, MISTLINE(num)); - arrput(rt->module_registry, MISTLINE(kim)); - arrput(rt->module_registry, MISTLINE(utf8)); - arrput(rt->module_registry, MISTLINE(fit)); - arrput(rt->module_registry, MISTLINE(text)); - arrput(rt->module_registry, MISTLINE(staef)); - arrput(rt->module_registry, MISTLINE(wota)); - arrput(rt->module_registry, MISTLINE(nota)); - arrput(rt->module_registry, MISTLINE(sdl_gpu)); - arrput(rt->module_registry, MISTLINE(qoi)); - - // power user - arrput(rt->module_registry, MISTLINE(js)); - arrput(rt->module_registry, MISTLINE(debug)); - -#ifndef __EMSCRIPTEN__ - arrput(rt->module_registry, MISTLINE(dmon)); -#endif - arrput(rt->module_registry, MISTLINE(util)); - - // prosperon - arrput(rt->module_registry, ((ModuleEntry){"sdl_audio", js_sdl_audio_use})); - arrput(rt->module_registry, ((ModuleEntry){"sdl_video", js_sdl_video_use})); - arrput(rt->module_registry, ((ModuleEntry){"input", js_input_use})); - arrput(rt->module_registry, ((ModuleEntry){"surface", js_sdl_surface_use})); - arrput(rt->module_registry, MISTLINE(spline)); - arrput(rt->module_registry, ((ModuleEntry){"geometry", js_geometry_use})); - arrput(rt->module_registry, MISTLINE(graphics)); - arrput(rt->module_registry, MISTLINE(video)); - arrput(rt->module_registry, MISTLINE(soloud)); - arrput(rt->module_registry, MISTLINE(layout)); - -// arrput(rt->module_registry, MISTLINE(imgui)); - arrput(rt->module_registry, ((ModuleEntry){"camera", js_camera_use})); - - arrput(rt->module_registry, MISTLINE(sprite)); - arrput(rt->module_registry, MISTLINE(transform)); - - arrput(rt->module_registry, MISTLINE(imgui)); - JSValue globalThis = JS_GetGlobalObject(js); JSValue prosp = JS_NewObject(js); @@ -1185,25 +1159,22 @@ void ffi_load(JSContext *js) JS_FreeValue(js,number_proto); JSValue hidden_fn = JS_NewObject(js); - // add engine.js-only functions to hidden_fn. It should grab them and then remove so nothing else can use them. - - // Add modules that should only be accessible to engine.js - JS_SetPropertyStr(js, hidden_fn, "actor", js_actor_use(js)); - JS_SetPropertyStr(js, hidden_fn, "wota", js_wota_use(js)); - JS_SetPropertyStr(js, hidden_fn, "console", js_console_use(js)); - JS_SetPropertyStr(js, hidden_fn, "nota", js_nota_use(js)); - -#ifndef __EMSCRIPTEN__ - JS_SetPropertyStr(js, hidden_fn, "enet", js_enet_use(js)); -#endif // Add functions that should only be accessible to engine.js - JS_SetPropertyStr(js, hidden_fn, "use_dyn", JS_NewCFunction(js, js_os_use_dyn, "use_dyn", 1)); - JS_SetPropertyStr(js, hidden_fn, "use_embed", JS_NewCFunction(js, js_os_use_embed, "use_embed", 1)); + JS_SetPropertyStr(js, hidden_fn, "load_internal", JS_NewCFunction(js, js_os_load_internal, "load_internal", 1)); JS_SetPropertyStr(js, hidden_fn, "rand", JS_NewCFunction(js, js_os_rand, "rand", 0)); JS_SetPropertyStr(js, hidden_fn, "randi", JS_NewCFunction(js, js_os_randi, "randi", 0)); JS_SetPropertyStr(js, hidden_fn, "srand", JS_NewCFunction(js, js_os_srand, "srand", 1)); + JS_SetPropertyStr(js, hidden_fn, "use_dyn", JS_NewCFunction(js, js_os_use_dyn, "use_dyn", 1)); +#if defined(_WIN32) + JS_SetPropertyStr(js, hidden_fn, "dylib_ext", JS_NewString(js, ".dll")); +#elif defined(__APPLE__) + JS_SetPropertyStr(js, hidden_fn, "dylib_ext", JS_NewString(js, ".dylib")); +#else + JS_SetPropertyStr(js, hidden_fn, "dylib_ext", JS_NewString(js, ".so")); +#endif + const char actorsym_script[] = "var sym = Symbol(`actordata`); sym;"; JSValue actorsym = JS_Eval(js, actorsym_script, sizeof(actorsym_script)-1, "internal", 0); diff --git a/source/qjs_blob.c b/source/qjs_blob.c index 70c6e824..b3edddb5 100644 --- a/source/qjs_blob.c +++ b/source/qjs_blob.c @@ -1,6 +1,6 @@ #define BLOB_IMPLEMENTATION #include "blob.h" -#include "qjs_blob.h" +#include "cell.h" // Get countof from macros if not defined #ifndef countof diff --git a/source/qjs_blob.h b/source/qjs_blob.h deleted file mode 100644 index e791fdcb..00000000 --- a/source/qjs_blob.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef QJS_BLOB_H -#define QJS_BLOB_H - -#include "cell.h" -#include "blob.h" - -#ifdef __cplusplus -extern "C" { -#endif - -JSValue js_blob_use(JSContext *ctx); - -// makes a new stone blob from data, copying the data over -JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes); - -// returns undefined if the blob is not stone -void *js_get_blob_data(JSContext *js, size_t *size, JSValue v); - -int js_is_blob(JSContext *js, JSValue v); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/qjs_crypto.c b/source/qjs_crypto.c index 07176ccc..09d78834 100644 --- a/source/qjs_crypto.c +++ b/source/qjs_crypto.c @@ -1,10 +1,9 @@ -#include "qjs_crypto.h" +#include "cell.h" #include #include #include #include "monocypher.h" -#include "qjs_blob.h" #include #include diff --git a/source/qjs_crypto.h b/source/qjs_crypto.h deleted file mode 100644 index b33f238d..00000000 --- a/source/qjs_crypto.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef QJS_CRYPTO_H -#define QJS_CRYPTO_H - -#include "cell.h" - -JSValue js_crypto_use(JSContext *ctx); -int randombytes(void *buf, size_t n); - -#endif diff --git a/source/qjs_debug.c b/source/qjs_debug.c index fa5d6f4d..9f959ba0 100644 --- a/source/qjs_debug.c +++ b/source/qjs_debug.c @@ -1,4 +1,3 @@ -#include "qjs_debug.h" #include "qjs_macros.h" #include "jsffi.h" diff --git a/source/qjs_debug.h b/source/qjs_debug.h deleted file mode 100644 index ffa7e391..00000000 --- a/source/qjs_debug.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_DEBUG_H -#define QJS_DEBUG_H - -#include "cell.h" - -JSValue js_debug_use(JSContext *ctx); - -#endif \ No newline at end of file diff --git a/source/qjs_dmon.c b/source/qjs_dmon.c index c46dc822..3cbd18e1 100644 --- a/source/qjs_dmon.c +++ b/source/qjs_dmon.c @@ -1,5 +1,4 @@ -#include "qjs_dmon.h" - +#include "cell.h" #define DMON_IMPL #include "dmon.h" diff --git a/source/qjs_dmon.h b/source/qjs_dmon.h deleted file mode 100644 index bd8e20fc..00000000 --- a/source/qjs_dmon.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_DMON_H -#define QJS_DMON_H - -#include "cell.h" - -JSValue js_dmon_use(JSContext *js); - -#endif diff --git a/source/qjs_enet.c b/source/qjs_enet.c index 4751415b..50c4bb24 100644 --- a/source/qjs_enet.c +++ b/source/qjs_enet.c @@ -1,5 +1,4 @@ -#include "qjs_enet.h" -#include "qjs_blob.h" +#include "cell.h" #include #include #include diff --git a/source/qjs_enet.h b/source/qjs_enet.h deleted file mode 100644 index 3d5de1d6..00000000 --- a/source/qjs_enet.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_ENET_H -#define QJS_ENET_H - -#include "cell.h" - -JSValue js_enet_use(JSContext*); - -#endif diff --git a/source/qjs_fd.c b/source/qjs_fd.c index e90cce9a..66a0bb95 100644 --- a/source/qjs_fd.c +++ b/source/qjs_fd.c @@ -1,5 +1,5 @@ #include "qjs_fd.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include diff --git a/source/qjs_fd.h b/source/qjs_fd.h deleted file mode 100644 index ce2e2087..00000000 --- a/source/qjs_fd.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_FD_H -#define QJS_FD_H - -#include "cell.h" - -JSValue js_fd_use(JSContext *js); - -#endif // QJS_FD_H \ No newline at end of file diff --git a/source/qjs_fit.c b/source/qjs_fit.c index f921327e..b144ab45 100644 --- a/source/qjs_fit.c +++ b/source/qjs_fit.c @@ -1,4 +1,3 @@ -#include "qjs_fit.h" #include "jsffi.h" #include #include diff --git a/source/qjs_fit.h b/source/qjs_fit.h deleted file mode 100644 index 89eaa238..00000000 --- a/source/qjs_fit.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_FIT_H -#define QJS_FIT_H - -#include - -JSValue js_fit_use(JSContext *js); - -#endif \ No newline at end of file diff --git a/source/qjs_geometry.c b/source/qjs_geometry.c index 3f7d47ac..cfc6c6a7 100644 --- a/source/qjs_geometry.c +++ b/source/qjs_geometry.c @@ -1,5 +1,4 @@ -#include "qjs_geometry.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include "qjs_common.h" diff --git a/source/qjs_geometry.h b/source/qjs_geometry.h deleted file mode 100644 index 38cbaa3c..00000000 --- a/source/qjs_geometry.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_GEOMETRY_H -#define QJS_GEOMETRY_H - -#include "cell.h" - -JSValue js_geometry_use(JSContext *ctx); - -#endif /* QJS_GEOMETRY_H */ diff --git a/source/qjs_http.c b/source/qjs_http.c index 6d5d890b..a09a7ca7 100644 --- a/source/qjs_http.c +++ b/source/qjs_http.c @@ -1,4 +1,4 @@ -#include "qjs_blob.h" +#include "cell.h" #define PAR_EASYCURL_IMPLEMENTATION #include "thirdparty/par/par_easycurl.h" #include diff --git a/source/qjs_http.h b/source/qjs_http.h deleted file mode 100644 index bf58a862..00000000 --- a/source/qjs_http.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_HTTP_H -#define QJS_HTTP_H - -#include "cell.h" - -JSValue js_http_use(JSContext*); - -#endif diff --git a/source/qjs_imgui.cpp b/source/qjs_imgui.cpp index 96f05b2c..04fed96f 100644 --- a/source/qjs_imgui.cpp +++ b/source/qjs_imgui.cpp @@ -23,7 +23,6 @@ //#include "imgui_impl_sdlrenderer3.h" #include "imgui_impl_sdlgpu3.h" -#include "qjs_renderer.h" #include "qjs_macros.h" diff --git a/source/qjs_js.c b/source/qjs_js.c index b395e9bf..8f4c530c 100644 --- a/source/qjs_js.c +++ b/source/qjs_js.c @@ -1,5 +1,5 @@ -#include "qjs_js.h" #include "jsffi.h" +#include "cell.h" JSC_CCALL(os_gc, JS_RunGC(JS_GetRuntime(js)) ) JSC_CCALL(os_mem_limit, JS_SetMemoryLimit(JS_GetRuntime(js), js2number(js,argv[0]))) @@ -51,8 +51,6 @@ JSC_CCALL(js_eval_compile, ret = JS_EvalFunction(js, argv[0]); ) -#include "qjs_blob.h" - JSC_CCALL(js_compile_blob, JSRuntime *rt = JS_GetRuntime(js); // JS_SetStripInfo(rt, JS_STRIP_SOURCE); diff --git a/source/qjs_js.h b/source/qjs_js.h deleted file mode 100644 index 53dae658..00000000 --- a/source/qjs_js.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_JS_H -#define QJS_JS_H - -#include "cell.h" - -JSValue js_js_use(JSContext *ctx); - -#endif \ No newline at end of file diff --git a/source/qjs_kim.c b/source/qjs_kim.c index 4084baf3..7280a5d8 100644 --- a/source/qjs_kim.c +++ b/source/qjs_kim.c @@ -1,5 +1,4 @@ -#include "qjs_kim.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include #include diff --git a/source/qjs_kim.h b/source/qjs_kim.h deleted file mode 100644 index 580a4c00..00000000 --- a/source/qjs_kim.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_KIM_H -#define QJS_KIM_H - -#include "cell.h" - -JSValue js_kim_use(JSContext*); - -#endif \ No newline at end of file diff --git a/source/qjs_layout.h b/source/qjs_layout.h deleted file mode 100644 index 5f2d7ad2..00000000 --- a/source/qjs_layout.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_LAYOUT_H -#define QJS_LAYOUT_H - -#include "cell.h" - -JSValue js_layout_use(JSContext *js); - -#endif diff --git a/source/qjs_math.c b/source/qjs_math.c index 76e07d67..64b5504b 100644 --- a/source/qjs_math.c +++ b/source/qjs_math.c @@ -1,4 +1,3 @@ -#include "qjs_math.h" #include "jsffi.h" #include "qjs_macros.h" diff --git a/source/qjs_math.h b/source/qjs_math.h deleted file mode 100644 index f12740f1..00000000 --- a/source/qjs_math.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_MATH_H -#define QJS_MATH_H - -#include "cell.h" - -JSValue js_math_use(JSContext *ctx); - -#endif /* QJS_MATH_H */ diff --git a/source/qjs_miniz.c b/source/qjs_miniz.c index 96526bb5..e57e4556 100644 --- a/source/qjs_miniz.c +++ b/source/qjs_miniz.c @@ -1,6 +1,6 @@ #include "quickjs.h" #include "miniz.h" -#include "qjs_blob.h" +#include "cell.h" static JSClassID js_reader_class_id; static JSClassID js_writer_class_id; diff --git a/source/qjs_nota.c b/source/qjs_nota.c index a3218cca..5252f50e 100755 --- a/source/qjs_nota.c +++ b/source/qjs_nota.c @@ -1,5 +1,5 @@ #include "qjs_nota.h" -#include "qjs_blob.h" +#include "cell.h" #define NOTA_IMPLEMENTATION #include "nota.h" diff --git a/source/qjs_os.c b/source/qjs_os.c index b2061b22..ef258155 100644 --- a/source/qjs_os.c +++ b/source/qjs_os.c @@ -1,10 +1,7 @@ -#include "qjs_os.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include "qjs_common.h" #include "qjs_wota.h" -#include "qjs_transform.h" -#include "transform.h" #include #include diff --git a/source/qjs_os.h b/source/qjs_os.h deleted file mode 100644 index f5afbbd0..00000000 --- a/source/qjs_os.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_OS_H -#define QJS_OS_H - -#include "cell.h" - -JSValue js_os_use(JSContext *ctx); - -#endif /* QJS_OS_H */ diff --git a/source/qjs_qop.c b/source/qjs_qop.c index c22352a0..daff457e 100644 --- a/source/qjs_qop.c +++ b/source/qjs_qop.c @@ -1,6 +1,5 @@ -#include "qjs_qop.h" #include "qop.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" static JSClassID js_qop_archive_class_id; diff --git a/source/qjs_qop.h b/source/qjs_qop.h deleted file mode 100644 index a2c0a0f7..00000000 --- a/source/qjs_qop.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_QOP_H -#define QJS_QOP_H - -#include "cell.h" - -JSValue js_qop_use(JSContext *js); - -#endif // QJS_QOP_H \ No newline at end of file diff --git a/source/qjs_renderer.c b/source/qjs_renderer.c index 20b58c88..ac873758 100644 --- a/source/qjs_renderer.c +++ b/source/qjs_renderer.c @@ -1,4 +1,3 @@ -#include "qjs_renderer.h" #include diff --git a/source/qjs_renderer.h b/source/qjs_renderer.h deleted file mode 100644 index b785aa56..00000000 --- a/source/qjs_renderer.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_RENDERER_H -#define QJS_RENDERER_H - -#include "cell.h" - -JSValue js_renderer_use(JSContext *ctx); - -#endif /* QJS_RENDERER_H */ diff --git a/source/qjs_sdl.c b/source/qjs_sdl.c index c33d7850..68542017 100644 --- a/source/qjs_sdl.c +++ b/source/qjs_sdl.c @@ -2,7 +2,6 @@ #include "jsffi.h" #include "qjs_macros.h" #include "cell.h" -#include "qjs_blob.h" #include "stb_ds.h" #include "qjs_actor.h" #include "qjs_sdl_surface.h" diff --git a/source/qjs_sdl_gpu.c b/source/qjs_sdl_gpu.c index 325933f8..cb148f30 100644 --- a/source/qjs_sdl_gpu.c +++ b/source/qjs_sdl_gpu.c @@ -2,7 +2,6 @@ #include "jsffi.h" #include "qjs_macros.h" #include "qjs_sdl_surface.h" -#include "qjs_blob.h" #include "quickjs.h" #include diff --git a/source/qjs_sdl_input.c b/source/qjs_sdl_input.c index 353f5201..d7854dd6 100644 --- a/source/qjs_sdl_input.c +++ b/source/qjs_sdl_input.c @@ -2,7 +2,6 @@ #include "jsffi.h" #include "qjs_macros.h" #include "cell.h" -#include "qjs_blob.h" #include "stb_ds.h" #include "qjs_actor.h" #include "qjs_wota.h" diff --git a/source/qjs_sdl_surface.c b/source/qjs_sdl_surface.c index ea962e50..a4c59d10 100644 --- a/source/qjs_sdl_surface.c +++ b/source/qjs_sdl_surface.c @@ -1,5 +1,5 @@ #include "qjs_sdl_surface.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include #include diff --git a/source/qjs_sdl_video.c b/source/qjs_sdl_video.c index 4013cf4b..c9410611 100644 --- a/source/qjs_sdl_video.c +++ b/source/qjs_sdl_video.c @@ -1,5 +1,4 @@ -#include "qjs_sdl_video.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include "qjs_sdl_surface.h" #include "qjs_actor.h" diff --git a/source/qjs_sdl_video.h b/source/qjs_sdl_video.h deleted file mode 100644 index e158e34c..00000000 --- a/source/qjs_sdl_video.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_SDL_VIDEO_H -#define QJS_SDL_VIDEO_H - -#include "cell.h" - -JSValue js_sdl_video_use(JSContext *ctx); - -#endif /* QJS_SDL_VIDEO_H */ diff --git a/source/qjs_socket.c b/source/qjs_socket.c index b5a57f9f..b859922b 100644 --- a/source/qjs_socket.c +++ b/source/qjs_socket.c @@ -1,6 +1,5 @@ -#include "quickjs.h" +#include "cell.h" #include "jsffi.h" -#include "qjs_blob.h" #ifdef _WIN32 #include diff --git a/source/qjs_socket.h b/source/qjs_socket.h deleted file mode 100644 index d2ee0a48..00000000 --- a/source/qjs_socket.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_SOCKET_H -#define QJS_SOCKET_H - -#include "quickjs.h" - -JSValue js_socket_use(JSContext *js); - -#endif // QJS_SOCKET_H \ No newline at end of file diff --git a/source/qjs_soloud.c b/source/qjs_soloud.c index 1533b2ea..311f7f85 100644 --- a/source/qjs_soloud.c +++ b/source/qjs_soloud.c @@ -1,5 +1,4 @@ -#include "qjs_soloud.h" -#include "qjs_blob.h" +#include "cell.h" #define STB_HEXWAVE_IMPLEMENTATION #include "soloud_c.h" diff --git a/source/qjs_soloud.h b/source/qjs_soloud.h deleted file mode 100644 index 810f3543..00000000 --- a/source/qjs_soloud.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_SOLOUD_H -#define QJS_SOLOUD_H - -#include "cell.h" - -JSValue js_soloud_use(JSContext*); - -#endif diff --git a/source/qjs_spline.c b/source/qjs_spline.c index b8d568b8..c01adc6a 100644 --- a/source/qjs_spline.c +++ b/source/qjs_spline.c @@ -1,4 +1,3 @@ -#include "qjs_spline.h" #include "qjs_macros.h" #include "jsffi.h" #include "spline.h" diff --git a/source/qjs_spline.h b/source/qjs_spline.h deleted file mode 100644 index 24462145..00000000 --- a/source/qjs_spline.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_SPLINE_H -#define QJS_SPLINE_H - -#include "cell.h" - -JSValue js_spline_use(JSContext *ctx); - -#endif \ No newline at end of file diff --git a/source/qjs_staef.c b/source/qjs_staef.c index a635dfe0..61e74917 100644 --- a/source/qjs_staef.c +++ b/source/qjs_staef.c @@ -1,4 +1,3 @@ -#include "qjs_staef.h" #include "font.h" #include "qjs_macros.h" #include "HandmadeMath.h" diff --git a/source/qjs_staef.h b/source/qjs_staef.h deleted file mode 100644 index 93547aea..00000000 --- a/source/qjs_staef.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_STAEF_H -#define QJS_STAEF_H - -#include "quickjs.h" - -JSValue js_staef_use(JSContext *js); - -#endif // QJS_STAEF_H diff --git a/source/qjs_text.c b/source/qjs_text.c index 93395295..33040cc2 100644 --- a/source/qjs_text.c +++ b/source/qjs_text.c @@ -1,5 +1,4 @@ -#include "qjs_text.h" -#include "qjs_blob.h" +#include "cell.h" #include "blob.h" #include #include diff --git a/source/qjs_text.h b/source/qjs_text.h deleted file mode 100644 index ee59e7e0..00000000 --- a/source/qjs_text.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_TEXT_H -#define QJS_TEXT_H - -#include - -JSValue js_text_use(JSContext *js); - -#endif diff --git a/source/qjs_time.h b/source/qjs_time.h deleted file mode 100644 index cec48d77..00000000 --- a/source/qjs_time.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_TIME_H -#define QJS_TIME_H - -#include "cell.h" - -JSValue js_time_use(JSContext *ctx); - -#endif /* QJS_TIME_H */ diff --git a/source/qjs_transform.c b/source/qjs_transform.c index a44ca013..2953d42b 100644 --- a/source/qjs_transform.c +++ b/source/qjs_transform.c @@ -1,4 +1,3 @@ -#include "qjs_transform.h" #include "jsffi.h" #include "qjs_macros.h" #include "stb_ds.h" diff --git a/source/qjs_transform.h b/source/qjs_transform.h deleted file mode 100644 index e2c7dba1..00000000 --- a/source/qjs_transform.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef QJS_TRANSFORM_H -#define QJS_TRANSFORM_H - -#include "cell.h" - -extern JSClassID js_transform_id; - -JSValue js_transform_use(JSContext *ctx); - -#endif /* QJS_TRANSFORM_H */ diff --git a/source/qjs_utf8.c b/source/qjs_utf8.c index f7fa00de..4ee0860c 100644 --- a/source/qjs_utf8.c +++ b/source/qjs_utf8.c @@ -1,5 +1,4 @@ -#include "qjs_utf8.h" -#include "qjs_blob.h" +#include "cell.h" #include "jsffi.h" #include #include diff --git a/source/qjs_utf8.h b/source/qjs_utf8.h deleted file mode 100644 index ae1327c9..00000000 --- a/source/qjs_utf8.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_UTF8_H -#define QJS_UTF8_H - -#include "cell.h" - -JSValue js_utf8_use(JSContext*); - -#endif \ No newline at end of file diff --git a/source/qjs_wildstar.c b/source/qjs_wildstar.c index 7a6420a2..803ad4a9 100644 --- a/source/qjs_wildstar.c +++ b/source/qjs_wildstar.c @@ -1,4 +1,3 @@ -#include "qjs_wildstar.h" #include "wildmatch.h" #include "jsffi.h" #include "qjs_macros.h" diff --git a/source/qjs_wildstar.h b/source/qjs_wildstar.h deleted file mode 100644 index 5949d058..00000000 --- a/source/qjs_wildstar.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_WILDSTAR_H -#define QJS_WILDSTAR_H - -#include "quickjs.h" - -JSValue js_wildstar_use(JSContext *js); - -#endif diff --git a/source/qjs_wota.c b/source/qjs_wota.c index bb479c56..1383f5d1 100644 --- a/source/qjs_wota.c +++ b/source/qjs_wota.c @@ -1,5 +1,5 @@ #include "qjs_wota.h" -#include "qjs_blob.h" +#include "cell.h" #include "wota.h" #include diff --git a/subprojects/chipmunk.wrap b/subprojects/chipmunk.wrap deleted file mode 100644 index 322137be..00000000 --- a/subprojects/chipmunk.wrap +++ /dev/null @@ -1,13 +0,0 @@ -[wrap-file] -directory = Chipmunk2D-Chipmunk-7.0.3 -source_url = https://github.com/slembcke/Chipmunk2D/archive/Chipmunk-7.0.3.tar.gz -source_filename = Chipmunk2D-Chipmunk-7.0.3.tar.gz -source_hash = 1e6f093812d6130e45bdf4cb80280cb3c93d1e1833d8cf989d554d7963b7899a -patch_filename = chipmunk_7.0.3-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/chipmunk_7.0.3-1/get_patch -patch_hash = 90e5e1be7712812cd303974910c37e7c4f2d2c8060312521b3a7995daa54f66a -wrapdb_version = 7.0.3-1 - -[provide] -chipmunk = chipmunk_dep - diff --git a/subprojects/qrencode.wrap b/subprojects/qrencode.wrap deleted file mode 100644 index c9f29bc3..00000000 --- a/subprojects/qrencode.wrap +++ /dev/null @@ -1,13 +0,0 @@ -[wrap-file] -directory = qrencode-4.1.1 -source_url = https://fukuchi.org/works/qrencode/qrencode-4.1.1.tar.gz -source_filename = qrencode-4.1.1.tar.gz -source_hash = da448ed4f52aba6bcb0cd48cac0dd51b8692bccc4cd127431402fca6f8171e8e -patch_filename = qrencode_4.1.1-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/qrencode_4.1.1-1/get_patch -patch_hash = be4f3944de65cc526e0714e7c162bd44d637650ab3876adfcf2347c638f277a9 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/qrencode_4.1.1-1/qrencode-4.1.1.tar.gz -wrapdb_version = 4.1.1-1 - -[provide] -dependency_names = libqrencode diff --git a/tests/steam.ce b/tests/steam.ce deleted file mode 100644 index b5deb3da..00000000 --- a/tests/steam.ce +++ /dev/null @@ -1,115 +0,0 @@ -var steam = use('steam') - -// Test Steam functionality -if (steam && steam.user) { - var isLoggedOn = steam.user.logged_on() - log.console("Steam user logged on:", isLoggedOn) - if (isLoggedOn) { - var userName = steam.friends.name() - var steamId = steam.user.steam_id() - var appId = steam.app.id() - log.console("Steam user name: '" + userName + "'") - log.console("Steam user ID: '" + steamId.toString() + "'") - log.console("Steam app ID: " + appId.toString()) - - // Request user stats for achievements - steam.stats.request() - - // Display online friends - log.console("\n=== ONLINE FRIENDS ===") - var friendCount = steam.friends.count(1) // EFriendFlagImmediate = 1 - if (friendCount > 0) { - for (var i = 0; i < friendCount; i++) { - var friend = steam.friends.get_friend(i, 1) - if (friend) { - var friendName = steam.friends.get_friend_persona_name(friend) - var friendState = steam.friends.get_friend_persona_state(friend) - // Only show online friends (state > 0) - if (friendState > 0) { - var stateNames = ["Offline", "Online", "Busy", "Away", "Snooze", "Looking to Trade", "Looking to Play"] - var stateName = stateNames[friendState] || "Unknown" - log.console(" " + friendName + " - " + stateName) - - // Check if friend is playing a game - var gameInfo = steam.friends.get_friend_game_played(friend) - if (gameInfo && gameInfo.game_id) { - var gameName = steam.friends.get_friend_rich_presence(friend, "steam_display") - if (gameName) { - log.console(" Playing: " + gameName) - } else { - log.console(" Playing game ID: " + gameInfo.game_id) - } - } - } - } - } - } else { - log.console(" No friends found or friends list not loaded yet") - } - - // Display achievement information - log.console("\n=== ACHIEVEMENTS ===") - var achievementCount = steam.achievement.count() - if (achievementCount > 0) { - log.console("Total achievements: " + achievementCount) - - for (var i = 0; i < achievementCount; i++) { - var achName = steam.achievement.name(i) - if (achName) { - var achieved = steam.achievement.get(achName) - var displayName = steam.achievement.get_display_attribute(achName, "name") - var description = steam.achievement.get_display_attribute(achName, "desc") - - if (achieved) { - var unlockInfo = steam.achievement.get_and_unlock_time(achName) - if (unlockInfo) { - var unlockDate = new Date(unlockInfo.unlock_time * 1000) - log.console(" ✓ " + (displayName || achName) + " - Unlocked " + unlockDate.toLocaleDateString()) - } else { - log.console(" ✓ " + (displayName || achName) + " - Unlocked") - } - } else { - // Check for progress on this achievement - var progressInt = steam.achievement.get_progress_limits_int(achName) - var progressFloat = steam.achievement.get_progress_limits_float(achName) - - var progressText = "" - if (progressInt && progressInt.max_progress > 0) { - progressText = " (Progress: " + progressInt.min_progress + "/" + progressInt.max_progress + ")" - } else if (progressFloat && progressFloat.max_progress > 0) { - progressText = " (Progress: " + progressFloat.min_progress.toFixed(1) + "/" + progressFloat.max_progress.toFixed(1) + ")" - } - - log.console(" ✗ " + (displayName || achName) + progressText) - if (description) { - log.console(" " + description) - } - } - } - } - - // Show global achievement stats if available - steam.stats.request_global_achievement_percentages() - - // Get most achieved achievement info - var mostAchieved = steam.achievement.get_most_achieved_info() - if (mostAchieved) { - log.console("\nMost achieved: " + mostAchieved.name + " (" + mostAchieved.percent.toFixed(1) + "% of players)") - } - } else { - log.console("No achievements found for this game") - } - - // Display user phone/security status - log.console("\n=== ACCOUNT SECURITY ===") - log.console("Phone verified: " + steam.user.is_phone_verified()) - log.console("Two-factor enabled: " + steam.user.is_two_factor_enabled()) - log.console("Behind NAT: " + steam.user.is_behind_nat()) - - // Display user level and badge info if available - var userLevel = steam.user.level() - if (userLevel > 0) { - log.console("Steam level: " + userLevel) - } - } -} \ No newline at end of file