Read project data and export JSON
Choose the right data format: a project to merge, scene geometry, or JSON for a Minecraft integration.
A plugin can add the contents of a saved project, read scene geometry, or prepare JSON for a Minecraft integration. Choose the format based on what you need to do with the result. These three representations are not interchangeable.
Download the complete project-data.js example. After installation, a button with a JSON icon appears in the toolbar. It opens a window with three actions. While one action is running, the other buttons and fields are disabled. Test importing on a copy of your project.
Three different tasks
| Task | Method | Result |
|---|---|---|
| Add objects from another project and continue editing | mergeContent(content, decode) |
Objects are added to the current scene |
| Pass visible geometry to your own analyzer or exporter | getMeshes() |
Temporary THREE.Mesh objects containing a geometry snapshot |
| Obtain data for creating a model and playing animations in Minecraft | await exportToJSON(fullProject, version) |
A game export object, or false if the export cannot proceed |
editorAPI has no general-purpose getProject() method that returns all editable
state. To merge content, use a project file or its original JSON string. Serializing
a mesh snapshot or a game export does not create a BDEngine project file.
Merging projects, reading meshes, and exporting use editorAPI. The internal
window.editor is used to check the current project before importing and to read the
selected Minecraft version index. There is currently no public getter for the selected
version. Check these dependencies on internal interfaces after editor updates.
Add the contents of a project
Pass a .bdengine or .bdstudio file as an ArrayBuffer with decode: true.
Reading a file is asynchronous: capture the original project before arrayBuffer()
and check that it has not changed before starting the import:
async function mergeProjectFile(file) { // Internal editor fields: check these after editor updates. const editor = window.editor; const api = window.editorAPI; if (!editor?.objects || !editor.history) { throw new Error('The project is not ready yet.'); }
const root = editor.objects; const history = editor.history; const historyGeneration = history._generation; const loadGeneration = editor._projectLoadGeneration; const content = await file.arrayBuffer();
if ( window.editor !== editor || editor.objects !== root || editor.history !== history || history._generation !== historyGeneration || editor._projectLoadGeneration !== loadGeneration ) { throw new Error('The project changed while the file was being read. Try importing again.'); }
await api.mergeContent(content, true);}Here, file is the user-selected File from an input[type=file] element. The check
detects replacement of the editor, project root, or history, as well as the start of
a new project load. If the original project has changed, the example does not call
mergeContent: repeat the action in the intended project. Once merging has started,
the editor performs its own checks that the project is still current.
Closing the window does not cancel an operation in progress. In the complete
example, task state is shared across window openings and retained when the script
is manually run again. If you reopen the window while a file is being read or imported,
its controls remain disabled until the operation finishes. Running the script again
does not start a second import in parallel; the result appears in the current window.
The editor detects supported project containers and their resources. Do not unpack
a modern project file as an arbitrary ZIP or discard its embedded resources.
For a project JSON string that has already been decoded, use decode: false:
await window.editorAPI.mergeContent(projectJsonText, false);This must be a string in the project format, not an object produced by JSON.parse.
Server API JSON is not suitable: its structure and purpose are different.
The method adds content to the current scene. The current implementation has
restrictions on imported structure blocks, which the editor reports in its interface.
Handled errors are also shown there. The editorAPI.mergeContent() wrapper does not
return the internal method’s boolean result, so undefined after await indicates
neither success nor failure. Check the scene and notifications.
Accepted inputs are detailed in the mergeContent reference.
Get temporary geometry
getMeshes() returns a snapshot of visible meshes. Mesh manager instances are expanded
into individual Mesh objects; bounding boxes, light gizmos, and meshes inside lights
are excluded. This is not the editor’s object tree: the number of meshes does not
necessarily match the number of entries in the object list.
const meshes = window.editorAPI.getMeshes();try { console.log('Meshes in the snapshot:', meshes.length); // Read meshes here. Do not add them back to the project to duplicate it.} finally { for (const mesh of meshes) { mesh.removeFromParent(); mesh.geometry.dispose(); const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material]; materials.forEach(material => material.dispose()); }}In the current implementation, geometries and materials are cloned for the snapshot.
Material textures may still be shared with the editor: do not call dispose() on
map, alphaMap, or other snapshot textures. The code above releases only the
geometries and materials created for the snapshot after use.
The world transform has already been copied into mesh.matrix, and matrixAutoUpdate
is disabled. Do not treat these meshes’ position, rotation, and scale values as
the project’s original editable transforms. Request a new snapshot after the scene
changes. See the getMeshes contract.
Get export JSON
Specify the export mode and the target Minecraft version index:
// Reading an internal editor setting: check this after editor updates.const version = window.editor.settingsEditor.exportMine.commandVersion;const data = await window.editorAPI.exportToJSON(false, version);if (data === false) { console.log('No export was produced. Check the editor notification.');} else { console.log(data.version, data.type);}fullProject: truerequests an export through Animator and switches the editor to that mode if needed.falsedoes not switch an already open Animator back to model editing. The result therefore also depends on the current mode: in Animator, evenfalsecan producetype: "full". For a model export, switch to model editing first. This does not guarantee support for every feature of a regular datapack.versionis a numeric index in the editor’s version list, not a string such as"1.21.4"or a JSON schema version. If omitted, the API selects the latest supported index, even if the user previously chose a different version.- The method changes the type and selected version in the export window, updates it, and displays it to the user. It is not a background getter without side effects.
- Use
await, check forfalse, and handle exceptions. For example, unfinished HeadPaint textures block the export.
The complete example reads the selected index on each button click, saves the returned
object to bde-export.json, and does not send it to a server. It does not publish
the export or create a temporary ID.
In the returned object, fields such as version, type, passengers, datapack,
and meta are at the root when present in that export. There is no content wrapper,
and strings retain the [BDESERVERTAG] marker. Do not add the HTTP wrapper or treat
this data as an editable project.
Signature: exportToJSON. Result format: JSON structure and differences between sources.
Verify with a test scene
- Save your original work. Create a separate project with one block display.
- Open the example window and count the meshes. Clicking again should not add objects to the scene; the counter reports temporary geometry.
- Choose a small saved project to merge. Check the added objects and notifications, then undo the import using the editor’s history.
- Switch projects while the file is being read. The import should stop with a message; objects from the file must not be added to the new project.
- Close and reopen the example window during an operation. Its buttons and fields should remain disabled until the operation finishes. Also check this when manually running the script again: the new window receives the result and enables its controls when the operation is complete.
- Switch to model editing and choose the required Minecraft version in the export
window. Download the example’s JSON with
fullProjectunchecked and checkversionandtype. - In a separate scene, add an animation and repeat with the checkbox selected. Check fields against the scene’s contents rather than expecting every optional field to be present.
Real structure blocks, separate group origins, and other regular datapack features do not become available simply because a plugin calls the API. Before implementing a consumer, read the game JSON export limitations.
The example’s contracts were checked against publicFunctions.js, editor.js,
utils.js, RenderRT.js, RenderRTCore.js, command.js, and Export.js.
This checks the implementation; running an arbitrary exported project in Minecraft
requires separate testing of your integration.