PlacementWorld.cpp includes Poco JSON via JsonDocument.h, but the
building module did not declare THIRDPARTY poco, so those TUs compiled
without POCO_NO_AUTOMATIC_LIBS. MSVC then recorded a link of
PocoFoundationd.lib (the DLL debug name) instead of PocoFoundationmdd.lib.
Declare poco on building and apply the no-auto-link flags to every
native module, the host binary, and unit_test so a future JsonDocument
include cannot regress the Windows link.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
A scene link keeps an external object in step with the node it hangs off. The
kinds were a closed enum with a switch in TransformSystem, so scene had to
include graphics, physics and audio to do the casts, and no other module could
ever attach to the tree without editing SceneHost.h -- particles, voxel,
spritestack, avatar and weather all had to stay outside it.
Kinds are registered now (scene/SceneLink.h). The module owning the target type
supplies pushWorld / pullWorld / alive, keeps the casts on its own side where
the type is complete, and scene never learns what a Renderable3D is. Dispatch is
a function-pointer table rather than virtual calls, since link sync runs for
every dirty node every frame.
The six typed helpers (linkRenderable2D and friends) stay as conveniences and
now resolve their kind by name, so they return false rather than crash when the
module that registers it was trimmed out. The script API already named kinds
with strings, which is exactly the registry key, so it is unchanged.
Direction is now the right way round: graphics, physics and audio depend on
scene rather than scene on them, and scene drops from L5 to L1. What remains is
scene -> graphics from pickScreenAt / collectFrustumIdsAt, which take a Camera3D
and read its projection; that is recorded in the back-edge whitelist as the next
thing to move.
Each provider lives in a SceneLinks.cpp, sharing the basename so the three come
out of the build together when scene is disabled.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
load.nut constructed about thirty modules by name, so any build that trimmed
one crashed at bind time. That is the only reason the browser runtime needed a
second root script, load_web.nut, listing the WASM-surviving subset by hand:
two files to keep in step with the link list, and no way to express any other
subset.
The boot script now walks eve.moduleList, generated at configure time from the
same manifest that produces the link list, and guards optional modules with
has_module(). The two frame drivers share one eve_frame(): desktop runs the
while loop at the bottom of load.nut, the browser leaves it to
emscripten_set_main_loop through the new eve.hostDrivesFrames flag rather than
a separate script. load_web.nut is gone.
EVENGINE_WEBGPU_TRIM is gone as well. What was a special case is now the "web"
profile, and the two remaining uses that really meant "is this Emscripten" say
so directly. Third-party groups the WASM aggregate does not build resolve to
nothing there, matching the list it linked before.
graphics now treats font as an optional dependency rather than a hard one:
graphics/Font.cpp is its only user and was already excluded on WASM. Turning
font off excludes that file everywhere, so the rule no longer depends on the
platform.
Verified: full-profile link line still identical to before the manifest work;
web profile resolves to exactly the module set the old REMOVE_ITEM list left;
a 3d-profile binary boots and runs the basic example, reporting avatar and
dialogue absent and the rest present; example smoke suite unchanged at 19/9.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
Which modules a build contains was spread over four places that had to be kept
in step by hand: the create_module() calls, the EVELIBS list, the per-platform
ThirdParty lists, and load.nut. Nothing tied them together, so the only trimming
that ever worked was the one hard-coded axis (Emscripten), and dropping a module
never dropped its libraries -- ThirdParty was a flat list unrelated to the
module set.
cmake/module_manifest.cmake now declares each module once with its dependencies,
third-party groups, script binding and profiles, and everything else is derived:
-DEVENGINE_PROFILE=minimal|2d|3d|full|web presets (default full)
-DEVENGINE_MODULE_<NAME>=ON|OFF per-module override, either casing
Dependencies close automatically, so enabling particles pulls in gpgpu,
animation and ik. Disabling something another enabled module needs is a
configure error naming both sides rather than a link failure. OPTIONAL_DEPS
covers 'integrate when present': each enabled module defines EVENGINE_HAS_<NAME>,
which is how scene picks up audio.
cmake/thirdparty_libs.cmake maps logical groups to per-platform link names and
emits them in EVE_TP_ORDER, since GNU ld needs dependents before providers.
The full profile is unchanged by construction: the generated link line is
identical to the previous one, same libraries in the same order and the same
object files. Trimmed builds work -- the 3d profile links and produces a 198 MB
debug binary against 233 MB for full, and -DEVENGINE_MODULE_DATABASE=OFF drops
PocoData and SQLite from the link.
DevTools becomes a declared module rather than a platform #ifdef, so it can be
switched off on desktop too. Its manifest DEPS record that McpServer and
SceneInspect still include scene / physics / procgen / particles / audio / ui
directly, so the resolver tells you to disable devtools before trimming those.
Step S5 of docs/dev/模块编排与裁剪架构.md. Boot scripts still name modules
directly, so a trimmed build links but needs S6 before it runs.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
HotReload knew what lived at every watched path: it included graphics to
refresh textures, particles to reload emitter configs and map to reload tile
layers. That made the engine's lowest-level module depend on three of its
highest, and it was the only reason filesystem sat in a dependency cycle.
Each module now registers an eve::caps::IAssetReloader for the assets it owns
and HotReload only routes paths. Behaviour is unchanged: automatic dispatch
still matches by extension, an explicit bind() still targets one kind and
ignores the extension, and the texture reloader runs at kTexture priority so
the GPU upload happens before emitters and tile layers re-bind to it.
The reloadable set now follows the linked module set, so a build without
particles simply has no particle reloader rather than a dangling reference.
Reload kinds also become extensible: a module or plugin can add one without
touching filesystem.
Back-edge whitelist 14 -> 11; the dependency graph is now acyclic apart from
the event pump.
(map.render.tilesContributeDepthY fails when run after the hotreload cases both
before and after this change -- pre-existing test-order state, not from here.)
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
Introduces eve::cap in common/Capability.h: a name-keyed registry where the
consumer owns the interface, the provider registers an implementation, and
neither includes the other. It generalises what common/RenderTrace.h already
does for the render tracer, and supports both a single provider (provide/query)
and many ordered ones (addListener/forEach), keyed by string so a provider
compiled into a plugin lands in the same slot as the host.
Two upward dependencies go away:
system -> graphics IGpuInfo. The Vulkan physical-device fields move into
graphics/vulkan/GpuInfoProvider.cpp, with a WebGPU
counterpart, so System.cpp loses both the graphics
include and its EVENGINE_WEBGPU branches.
thread -> event IMainThreadPost. postMain and submitPost now enqueue
through the capability. The interface makes explicit
what was previously only a comment in submitPost: the
submitting thread calls prepare() so the worker never
reaches the module registry.
Both now report an error when no provider is linked, rather than lazily
creating a module the build may not contain.
Step S3 of docs/dev/模块编排与裁剪架构.md; back-edge whitelist 16 -> 14.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
rpg, inventory and building each carried a byte-identical JsonHelpers.h (only
the namespace differed), card and voxel inlined a fourth and fifth copy, and
i18n hand-rolled a sixth parser because it needs to build without Poco.
Replace all of them with eve::json in common/Json.h. The backend is i18n's
recursive-descent parser, promoted and extended to track integral literals so
getInt() stays exact; picking that over Poco keeps EVCommon dependency-free and
drops Poco from six gameplay modules outright (15 modules -> 9, 136 include
sites -> 108), which is what lets those modules be trimmed independently later.
Accessors keep the lenient, never-throwing behaviour the per-module helpers
had: a missing key, wrong type or bad index yields the fallback. Two places
that relied on Poco throwing to reject incomplete input (housegen instance and
room records) now check required fields explicitly.
test/json.cpp covers the parser directly -- scalars, lenient conversion,
integer exactness and range, nesting, escapes, surrogate pairs, malformed
input and empty containers.
This is step S2 of docs/dev/模块编排与裁剪架构.md.
Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
Add a development-server based remote hot reload so script/resource changes
made on the host are synced and reloaded live on devices whose game bundle is
read-only (iOS app bundle, Android APK).
- Implement the previously stubbed `eve dev` command as a small HTTP file
server (GET /manifest, /raw/<path>, /ping) serving a game directory.
- Extend HotReload with a background remote-sync client: poll the server
manifest, compare mtime/size, download changed files into a writable overlay
directory mounted at "/" via the new Filesystem::mountRealDirectory, and
queue changed virtual paths for the script layer to dofile/reload.
- Wire it into load.nut: config.devServer/devSyncMs, shared handle_change(),
poll_remote_reload(), and a `eve run --dev-server <url>` CLI override.
- Add iOS/Android hot-reload dir helpers and cleartext-HTTP platform config
(iOS ATS + NSLocalNetworkUsageDescription, Android usesCleartextTraffic).
- Add test/remotesync.cpp covering overlay shadowing, end-to-end sync, and
unreachable-recovery; update docs.
Adds 'eve mcp': a desktop-only headless MCP host (stdio by default, --port for TCP, --root for the project). It runs the full runtime, attaches DevTools (eve_eval / eve_run_script / snapshot), and starts the new EditorHost module that renders JSON-defined editor Views (ImGui) bound two-way to Squirrel ViewModel tables (MVVM), persists editors under editors/, and exposes the eve_host_* tool family (apply/state/set_value/events/capture/script/shutdown...). The stdio transport uses a background stdin reader and keeps stdout JSON-RPC-only; script print() is routed to stderr.
Tests: stdio handshake + tools/list round trip, host editor binding (VM<->View sync, set_value -> VM write + onChange events, save/reload persistence). Docs updated (AI与MCP支持.md, 命令行设计.md, tools/eve-mcp README) with the editor JSON protocol and Codex stdio setup.
Add an i18n module (eve.I18n) for game localization:
- Load per-language JSON locale tables from VFS or raw JSON.
- Dot-path key lookup with {name} placeholder substitution.
- CLDR-style plural rules (en/fr/ru/pl/cs/zh and more).
- Fall back to default language, then to the raw key.
- Optional file auto-reload via update(dt).
Self-contained JSON parser (no Poco) so it builds on WASM too.
Includes C++ + Squirrel script tests, user/module docs, an
examples/i18n demo, and i18n integration in the dialogue example.
EVHouseGen is only created when NOT EVENGINE_WEBGPU_TRIM, but it stayed in
the unconditional EVELIBS list, so the WASM link failed with
'wasm-ld: unable to find library -lEVHouseGen'. Remove it alongside the
other trimmed modules.
The devtools module (DebugAdapter/Snapshot/SceneInspect/RenderVision/
McpServer) depends on Poco JSON+Net, which is trimmed from the WASM build.
EVDevTools was already excluded from EVELIBS on Emscripten, but
create_module() still compiled its Poco-heavy sources, failing with
'Poco/JSON/Array.h: No such file'. Guard the module build with the same
platform condition as the EVELIBS exclusion.
Add the scene_director Squirrel kit (src/scripts/scene_director.nut) with
spawn/move/scale/rotate/remove/material/lighting/camera/cameras/info/modify/
reset, embedded into the engine and exposed to host games as
eve.sceneDirectorScript. New MCP tools (eve_scene_director_install/status,
eve_scene_reset, eve_scene_modify, eve_scene_info, eve_camera_generate) are
thin dispatchers over the kit, so agents can place props, set lighting,
frame cameras, inspect truth and reset the stage through MCP alone.
The kit's cross-references are written explicitly as scene_director.<field>
to avoid Squirrel table-closure his resolution, and cameras() uses a
fixed 6-way compass table (no math-lib dependency) so it works both in the
engine and in plain ssq test VMs.
- Fixed the JSON schema for the 'capture_render_frame' tool by adding a missing closing brace.
- Ensured proper structure for the input schema to maintain consistency and prevent potential parsing errors.
The deps restructure added box3d to the iOS/Apple, Emscripten, and Linux
link lists but missed Android, so libmain.so failed to link with
undefined b3* symbols from EVPhysics. Add box3d to the Android list.
Adds a vision-model bridge (devtools/RenderVision) that captures the
current frame (Graphics readback -> PNG data URL) and sends it with
engine render parameters to an OpenAI-compatible vision model over
plain HTTP, returning prose that describes the frame and explains the
render-parameter <-> visual-result correspondence for other LLM agents.
- New MCP tools:
- eve_render_describe (fresh/reason; cached otherwise)
- eve_render_vision_config (set/read config, key masked)
- Breakpoint hit and runtime-error pause auto-flag a pending dump that
McpServer::poll performs on the main (render) thread.
- Config via env (EVE_VISION_BASE_URL/API_KEY/MODEL/PATH/TIMEOUT_MS)
or the config tool.
- No TLS/OpenSSL is linked, so the endpoint must be plain HTTP (works
with local Ollama/vLLM/LM Studio).
- Compiles cleanly on MSVC (C++20); tests extended for new tools.
Move the user-maintained VKBuilder from the third-party aggregate into external/ (git submodule), and relocate the third-party DungeonTemplateLibrary and Box3D from external/ into the third-party aggregate (previously pushed to EVEngine/third-party). Update .gitmodules, include paths, DTL/box3d build wiring, and docs.
Integrate the latest main (weather system, outline shader, camera controller,
model converter, hidpi-ui). Resolve additive conflicts in shared registration
files so both the day/night and weather modules are registered:
- src/modules/CMakeLists.txt, src/engine/CMakeLists.txt, test/CMakeLists.txt
- src/scripts/load.nut, docs/usr/MODULES.md
ImageData::getConstant is declared but never defined, causing LNK2019 /
undefined-reference link failures on all CI platforms. Use the
medialoader::FormatHandler::ENCODED_PNG constant directly for the
eve_screenshot PNG encode.