Added nbt exporter for structure blocks

This commit is contained in:
Lucas Dower 2022-07-10 23:44:31 +01:00
parent a6e6f4ee38
commit 7c7b60e879
6 changed files with 121 additions and 3 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ ObjToSchematic-darwin-x64
!/res/atlases/vanilla.png
/res/palettes/empty.palette
/dist
/dev
/tools/blocks
/tools/models
notes.txt

View File

@ -21,4 +21,6 @@ export namespace AppConstants {
export const INDICES = 36;
export const OCCLUSION = ComponentSize.OCCLUSION * COMPONENT_PER_SIZE_OFFSET;
}
export const DATA_VERSION = 3105; // 1.19
}

View File

@ -4,8 +4,9 @@ import { Litematic } from './litematic_exporter';
import { ASSERT } from '../util';
import { ObjExporter } from './obj_exporter';
import { SchemExporter } from './schem_exporter';
import { NBTExporter } from './nbt_exporter';
export type TExporters = 'schematic' | 'litematic' | 'obj' | 'schem';
export type TExporters = 'schematic' | 'litematic' | 'obj' | 'schem' | 'nbt';
export class ExporterFactory {
public static GetExporter(voxeliser: TExporters): IExporter {
@ -18,6 +19,8 @@ export class ExporterFactory {
return new ObjExporter();
case 'schem':
return new SchemExporter();
case 'nbt':
return new NBTExporter();
default:
ASSERT(false);
}

View File

@ -0,0 +1,111 @@
import { NBT, TagType } from 'prismarine-nbt';
import { LOG } from '../util';
import { Vector3 } from '../vector';
import { BlockMesh } from '../block_mesh';
import { IExporter } from './base_exporter';
import { saveNBT } from '../util/nbt_util';
import { AppConstants } from '../constants';
import { StatusHandler } from '../status';
export class NBTExporter extends IExporter {
public override getFormatFilter() {
return {
name: this.getFormatName(),
extensions: ['nbt'],
};
}
public override getFormatName() {
return 'Structure Blocks';
}
public override getFileExtension(): string {
return 'nbt';
}
public override export(blockMesh: BlockMesh, filePath: string): boolean {
const bounds = blockMesh.getVoxelMesh().getBounds();
const sizeVector = bounds.getDimensions().add(1);
const isTooBig = sizeVector.x > 48 && sizeVector.y > 48 && sizeVector.z > 48;
if (isTooBig) {
StatusHandler.Get.add('warning', 'Structure blocks only support structures of size 48x48x48, blocks outside this range will be removed');
}
const blockNameToIndex = new Map<string, number>();
const palette: any = [];
for (const blockName of blockMesh.getBlockPalette()) {
palette.push({
Name: {
type: TagType.String,
value: 'minecraft:' + blockName, // TODO: Namespace blocks
},
});
blockNameToIndex.set(blockName, palette.length - 1);
}
const blocks: any = [];
for (const block of blockMesh.getBlocks()) {
const pos = block.voxel.position;
const blockIndex = blockNameToIndex.get(block.blockInfo.name);
if (blockIndex) {
if (pos.x > -24 && pos.x <= 24 && pos.y > -24 && pos.y <= 24 && pos.z > -24 && pos.z <= 24) {
blocks.push({
pos: {
type: TagType.List,
value: {
type: TagType.Int,
value: Vector3.sub(block.voxel.position, bounds.min).toArray(),
},
},
state: {
type: TagType.Int,
value: blockIndex,
},
});
}
}
}
const nbt: NBT = {
type: TagType.Compound,
name: 'SchematicBlocks',
value: {
DataVersion: {
type: TagType.Int,
value: AppConstants.DATA_VERSION,
},
size: {
type: TagType.List,
value: {
type: TagType.Int,
value: sizeVector.toArray(),
},
},
palette: {
type: TagType.List,
value: {
type: TagType.Compound,
value: palette,
},
},
blocks: {
type: TagType.List,
value: {
type: TagType.Compound,
value: blocks,
},
},
},
};
LOG(nbt);
saveNBT(nbt, filePath);
return false;
}
private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {
return vec.x + (vec.z * dimensions.x) + (vec.y * dimensions.x * dimensions.z);
}
}

View File

@ -4,6 +4,7 @@ import { Vector3 } from '../vector';
import { BlockMesh } from '../block_mesh';
import { IExporter } from './base_exporter';
import { saveNBT } from '../util/nbt_util';
import { AppConstants } from '../constants';
const varintarray = require('varint-array');
@ -24,7 +25,6 @@ export class SchemExporter extends IExporter {
}
private static SCHEMA_VERSION = 2;
private static DATA_VERSION = 3105; // 3105 => 1.19, TODO: Remove hardcoded value
public override export(blockMesh: BlockMesh, filePath: string): boolean {
const bounds = blockMesh.getVoxelMesh().getBounds();
@ -60,7 +60,7 @@ export class SchemExporter extends IExporter {
name: 'Schematic',
value: {
Version: { type: TagType.Int, value: SchemExporter.SCHEMA_VERSION },
DataVersion: { type: TagType.Int, value: SchemExporter.DATA_VERSION },
DataVersion: { type: TagType.Int, value: AppConstants.DATA_VERSION },
Width: { type: TagType.Short, value: sizeVector.x },
Height: { type: TagType.Short, value: sizeVector.y },
Length: { type: TagType.Short, value: sizeVector.z },

View File

@ -177,6 +177,7 @@ export class UI {
{ id: 'schematic', displayText: 'Schematic (.schematic)' },
{ id: 'obj', displayText: 'Wavefront OBJ (.obj)' },
{ id: 'schem', displayText: 'Sponge Schematic (.schem)' },
{ id: 'nbt', displayText: 'Structure blocks (.nbt)' },
]),
},
elementsOrder: ['export'],