save_level
Writes the editor's current level (.umap) to disk, refusing during Play-in-Editor and for read-only files; use it to persist level edits.
Instructions
Write the editor's current level (.umap) to disk; it REFUSES while PIE is running (the engine guard rejects the write anyway) and derives success from the file being on disk afterwards, never from the save call's own bool. WARNING: it also REFUSES when the target .umap is READ-ONLY on disk, which in an LFS repo means a lockable path you have not git lfs locked: that write cannot succeed, and answering over HEAD's still-untouched bytes would report success:true having written nothing. The refusal names the file and the fix (git lfs lock <file>) -- take the lock, do not retry. WARNING: on a file that ALREADY existed, file_exists_on_disk alone still cannot tell "I wrote it" from "it was already there": the field that proves the write is file_mtime_changed. It is deliberately NOT gating success, because a save with nothing dirty to write also leaves the mtime alone and that is not a failure. WARNING: with filename this is a SaveAs that DUPLICATES: the editor stays on the old map, the new one becomes a resident world (which then makes load_level refuse), and a SECOND save to the same filename opens a modal that freezes the editor -- treat filename as one-shot per name per session.
Returns: { success: bool, error?: string, data?: { saved_filename?: string, saved_package?: string, saved_disk_path?: string, level_name?: string, file_exists_on_disk: bool, file_size_bytes: int, file_existed_before: bool, file_mtime_changed: bool (the write itself -- see the read-only note above), save_call_returned: bool, rescued_with_save_packages: bool, pie_was_stopped: bool, orphan_world_risk?: bool, requested?: { filename?: string, save_as?: bool } } }
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | Optional. This command is REFUSED while a Play-in-Editor session is running: it either compiles a Blueprint (the reinstancer can retain a world, and CheckForWorldGCLeaks is Fatal -- it KILLS the editor) or writes to disk (Editor.AllowSavingAssetsDuringPIE=0 makes the engine refuse the write, so it would report success without writing a byte). Stop PIE and retry instead; force=true runs it anyway, at your own risk. | |
| save_as | No | Accepted for wire compatibility and IGNORED: the branch is chosen by whether `filename` was given. It comes back inside `requested` to mark it as your input, not a measurement. | |
| filename | No | Optional. A /Game asset path (e.g. /Game/Maps/Foo) or a disk .umap path; both accepted and resolved. Omit it to save the level in place -- that is the branch that just works. Passing one is a SaveAs: duplicate + resident world + the one-shot rule above. |