
💃 Getting Started ​
This workspace-private package stores .voxelmap.json worlds and the .blockset.json blocksets they link. Add "@jolly-pixel/asset.voxel-map": "workspace:*" to another workspace's dependencies.
👀 Usage example ​
Register the kinds ​
import {
blocksetAssetKind,
voxelMapAssetKind
} from "@jolly-pixel/asset.voxel-map";
import { createAssetBackend } from "@jolly-pixel/asset-server";
import { FilesystemAssetSource } from "@jolly-pixel/asset-source";
import * as EventStore from "@jolly-pixel/event-store";
using eventStore = await EventStore.persistence.sqlite(
"./assets/.jollypixel/events.db"
);
await createAssetBackend({
source: new FilesystemAssetSource("./assets"),
eventStore,
handlers: [blocksetAssetKind(), voxelMapAssetKind()]
});A blockset owns its pixels and their normal map settings, tile size, block definitions and material groups. A world links blocksets by asset reference and stores only its layers; every linked blockset is a catalog dependency of the world. The default chunkSize is 16. A map saved with another chunk size still loads, and is saved back with the handler's. The map handler waits 5 seconds after edits before writing a snapshot, with a 60-second maximum delay while edits continue. Pass snapshot to change this policy on either kind. blocksetAssetKind({ tileSize, defaultSize }) sets what a blockset created without content holds: 32-pixel tiles on an 8 by 8 tile grid by default. A map created without content comes with a blockset of the same name beside it, created without content and linked as its default blockset. A deleted blockset keeps its pixel and tile sizes and loses its pixels, normal map settings, blocks and material groups.
Connect a world and its blocksets ​
Construct the sync clients before joining the rooms. document is a VoxelDocument; draw it with a VoxelView when the editor also needs rendering.
import { assetRoomName } from "@jolly-pixel/asset";
import { Client } from "@jolly-pixel/network/client";
import { VoxelDocument } from "@jolly-pixel/voxel.renderer";
import {
SyncedBlockset,
BLOCKSET_KIND,
VoxelSyncClient,
type VoxelMapRoom
} from "@jolly-pixel/asset.voxel-map/client";
const client = new Client();
const document = new VoxelDocument();
const room: VoxelMapRoom = client.room(assetRoomName("voxelmap", assetId));
const sync = new VoxelSyncClient({ room, document });
room.join();
const blockset = new SyncedBlockset(
client.room(assetRoomName(BLOCKSET_KIND, blocksetAssetId))
);
blockset.ready.then(() => {
// blockset.pixels is a PixelDocument, blockset.blockset a BlocksetDocument
});
// On teardown: sync.destroy(); blockset.dispose(); room.leave(); client.destroy();The first snapshot loads each document. Local world commands go to the map room; local pixel edits and block, material group and tile size commands go to the blockset room. Accepted remote commands are applied with a remote origin. sync.replaceWorld(document.save()) sends a full replacement and produces a new snapshot.
📚 API ​
@jolly-pixel/asset.voxel-mapexportsvoxelMapAssetKind,VoxelMapState,blocksetAssetKind,BlocksetState,blocksetAsset, theVOXEL_MAP_ASSETandBLOCKSET_ASSETdescriptors,ASSET_KINDS(the kind package, taking{ blockset?, voxelmap? }options), and the kind and event constants of both kinds for server registration and persistence.createBlocksetFile({ tileSize?, size?, pixels?, blocks?, materialGroups? })builds aBlocksetFile;blocksetFileFromPng(png, { tileSize?, blockLimit? })wraps an image with one cube block per tile, up toblockLimit(32).encodeBlocksetFile,decodeBlocksetFileandparseBlocksetFileare its codec; a malformed file throwsInvalidAssetFileErrorfrom@jolly-pixel/asset-server. The decoders are only exported from the package root.createVoxelMapFile({ chunkSize, blocksets?, layer? })builds aVoxelWorldJSONmap linking the given blocksets, each in the first free slot, with onelayer("Ground");encodeVoxelWorldfrom@jolly-pixel/voxel.rendererturns it into content. Loading a map checks it againstvoxelWorldSchema, blockset links included, before the renderer parses it; a malformed map throwsInvalidAssetFileError.@jolly-pixel/asset.voxel-map/clientexportsVoxelSyncClient,SyncedVoxelMap, the map's undo history (VoxelEdits,voxelHistoryRegistration),voxelMapDocumentKind,BlocksetSyncClient,SyncedBlockset,blocksetDocumentKind,blocksetRoom,createBlocksetAsset, the blockset file builders and encoder, wire types, andblocksetAsset. It also exports the block projection:blockShapeUv,uvGeometryForSlot,BlockProjectionandBlocksetIslands, which builds a blockset's normal map islands from its blocks.@jolly-pixel/asset.voxel-map/serverexportsVoxelCommandArbiter,BlocksetCommandArbiter, and the protocol and snapshot schemas of both rooms.
The package root imports server dependencies. Browser code should use the client entry point. See the network API for command and lifecycle details and architecture for state ownership and conflict keys. The world and blockset file formats and voxel commands are documented by voxel.renderer.
✨ Contributors guide ​
Read the contributing guide before submitting a change. Run pnpm --filter @jolly-pixel/asset.voxel-map test and pnpm run lint from the monorepo root.
📃 License ​
MIT