feat(npc, nav): 17.5 - a person walks by the world's way where it has one (NpcWorld.way: the next corner toward the target, asked every half second, on reaching it or for a new target; the errand begins only at the target itself; the step round and the give-up stay the fallback), way_test round a wall; and ludic.nav reads a mesh file into the shim's own memory and frees it once parsed, so loading a map leaves nothing in Ludic's never-freed heap

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-27 21:57:34 +03:00
parent 4add35b4ca
commit ee0768bf3e
12 changed files with 184 additions and 39 deletions

View file

@ -47,8 +47,8 @@ export function nav_polygons(nav_st: NavState, kind: int) -> int {
return nvc_polys(h)
}
# a kind's mesh written to a file, and read back. Reading holds the file's bytes for good (a slice
# is never given back), so a mesh is loaded once per map, never per frame
# a kind's mesh written to a file, and read back - through the asset pack when it is in one - into the
# shim's own memory, which it frees once the tiles are made, so a map swap leaves nothing behind
export function nav_save_file(nav_st: NavState, kind: int, path: string) -> bool {
let h = nv_mesh(nav_st, kind)
if h == null { return false }
@ -59,8 +59,14 @@ export function nav_save_file(nav_st: NavState, kind: int, path: string) -> bool
return Fs.write_bytes(path, buf, n)
}
export function nav_load_file(nav_st: mut NavState, kind: int, path: string) -> bool {
if not Fs.exists(path) { return false }
let buf = Fs.read_bytes(path)
if buf == null or len(buf) == 0 { return false }
return nv_set(nav_st, kind, nvc_load(buf, len(buf)))
let f = file_open(path, "rb")
if f == null { return false }
file_seek(f, 0, 2)
let n = file_tell(f)
file_seek(f, 0, 0)
let buf = nvc_stage(n)
var got = 0
if buf != null { got = file_read(f, buf, n) }
file_close(f)
return nv_set(nav_st, kind, nvc_load_staged(buf, got))
}

Binary file not shown.

View file

@ -13,3 +13,5 @@ extern function nvc_path(h: pointer, f: int, sx: float, sy: float, sz: float, ex
extern function nvc_partial(h: pointer) -> int = "nav_partial"
extern function nvc_raycast(h: pointer, f: int, sx: float, sy: float, sz: float, ex: float, ez: float) -> int = "nav_raycast"
extern function nvc_random_near(h: pointer, f: int, x: float, y: float, z: float, r: float, seed: int, out: pointer) -> int = "nav_random_near"
extern function nvc_stage(size: int) -> pointer = "nav_stage"
extern function nvc_load_staged(buf: pointer, size: int) -> pointer = "nav_load_staged"

View file

@ -7,6 +7,7 @@
#include <DetourNavMeshQuery.h>
#include <DetourCommon.h>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>

View file

@ -100,3 +100,12 @@ NAV_SHIM void *nav_load(const unsigned char *buf, int size) {
}
return nav_open(mesh);
}
// a file read straight into the shim's own memory rather than a Ludic slice (which is never given
// back): nav_stage hands out the room, nav_load_staged parses it and frees it, whatever the outcome
NAV_SHIM unsigned char *nav_stage(int size) { return size > 0 ? static_cast<unsigned char *>(malloc(size)) : nullptr; }
NAV_SHIM void *nav_load_staged(unsigned char *buf, int size) {
void *h = buf ? nav_load(buf, size) : nullptr;
free(buf);
return h;
}