Blocks are now exported to schematic

This commit is contained in:
Lucas Dower 2022-02-28 19:47:44 +00:00
parent 99aa9bcd71
commit 3e1538aa97
5 changed files with 1429 additions and 26 deletions

1402
resources/block_ids.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -169,14 +169,6 @@ export class AppContext {
const exportFormat = UI.Get.layout.export.elements.export.getCachedValue() as string;
const exporter = (exportFormat === 'schematic') ? new Schematic() : new Litematic();
if (exportFormat === 'schematic') {
this._warnings.push(`
The .schematic format does not support newer Minecraft blocks.
For now, all blocks are exported as Stone blocks until a block palette
is available that only uses supported blocks.
`);
}
const filePath = remote.dialog.showSaveDialogSync({
title: 'Save structure',
buttonLabel: 'Save',

View File

@ -26,14 +26,6 @@ export interface BlockInfo {
faces: FaceInfo
}
// https://minecraft.fandom.com/wiki/Java_Edition_data_values/Pre-flattening/Block_IDs
/* eslint-disable */
export enum Block {
Stone = 1.0,
Dirt = 3.0,
Cobblestone = 4.0
}
interface BlockPalette {
blocks: string[];
}

View File

@ -1,9 +1,11 @@
import * as zlib from 'zlib';
import * as fs from 'fs';
import path from 'path';
import { NBT, TagType, writeUncompressed } from 'prismarine-nbt';
import { Vector3 } from './vector';
import { Block } from './block_atlas';
import { BlockMesh } from './block_mesh';
import { LOG } from './util';
import { AppContext } from './app_context';
export abstract class Exporter {
protected _sizeVector!: Vector3;
@ -42,13 +44,32 @@ export class Schematic extends Exporter {
const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
const blocksData = Array<number>(bufferSize);
const metaData = Array<number>(bufferSize);
const bounds = blockMesh.getVoxelMesh().getBounds();
const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = JSON.parse(fs.readFileSync(path.join(__dirname, '../resources/block_ids.json'), 'utf8'));
const blocks = blockMesh.getBlocks();
const unsupportedBlocks = new Set<string>();
let numBlocksUnsupported = 0;
for (const block of blocks) {
const indexVector = Vector3.sub(block.voxel.position, bounds.min);
const index = this._getBufferIndex(indexVector, this._sizeVector);
blocksData[index] = Block.Stone;
if (block.blockInfo.name in schematicBlocks) {
const schematicBlock = schematicBlocks[block.blockInfo.name];
blocksData[index] = new Int8Array([schematicBlock.id])[0];
metaData[index] = new Int8Array([schematicBlock.meta])[0];
} else {
blocksData[index] = 1; // Default to a Stone block
metaData[index] = 0;
unsupportedBlocks.add(block.blockInfo.name);
++numBlocksUnsupported;
}
}
if (unsupportedBlocks.size > 0) {
AppContext.Get.addWarning(`${numBlocksUnsupported} blocks (${unsupportedBlocks.size} unique) are not supported by the .schematic format, Stone block are used in their place. Try using the schematic-friendly palette, or export using .litematica`);
LOG('Unsupported blocks', unsupportedBlocks);
}
const nbt: NBT = {
@ -60,7 +81,7 @@ export class Schematic extends Exporter {
Length: { type: TagType.Short, value: this._sizeVector.z },
Materials: { type: TagType.String, value: 'Alpha' },
Blocks: { type: TagType.ByteArray, value: blocksData },
Data: { type: TagType.ByteArray, value: new Array<number>(bufferSize).fill(0) },
Data: { type: TagType.ByteArray, value: metaData },
Entities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
TileEntities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
},
@ -136,8 +157,8 @@ export class Litematic extends Exporter {
const blockStates = new Array<long>();
for (let i = blockEncoding.length; i > 0; i -= 64) {
let right = parseInt(blockEncoding.substring(i-32, i), 2);
let left = parseInt(blockEncoding.substring(i-64, i-32), 2);
let right = parseInt(blockEncoding.substring(i - 32, i), 2);
let left = parseInt(blockEncoding.substring(i - 64, i - 32), 2);
// TODO: Cleanup, UINT32 -> INT32
if (right > 2147483647) {

View File

@ -5,10 +5,6 @@ import path from 'path';
import prompt from 'prompt';
void async function main() {
test();
}();
async function test() {
log(LogStyle.Info, 'Creating a new palette...');
const paletteBlocksDir = path.join(__dirname, './new-palette-blocks.txt');
@ -48,4 +44,4 @@ async function test() {
fs.writeFileSync(path.join(__dirname, `../resources/palettes/${promptUser.paletteName}.palette`), JSON.stringify(paletteJSON, null, 4));
log(LogStyle.Success, `Successfully created ${promptUser.paletteName}.palette in /resources/palettes/`);
}
}();