VOXELFORMAT: allow to load minecraft schematic files

master
Martin Gerhardy 2022-03-27 22:01:29 +02:00
parent 70b5d3bd93
commit 77df9b968b
9 changed files with 517 additions and 320 deletions

View File

@ -11,6 +11,7 @@
| Goxel | gox | X | X | X | | X | |
| MagicaVoxel | vox | X | X | X | X | X | ttps://github.com/ephtracy/voxel-model |
| Minecraft Region | mcr | X | | X | X | X | https://minecraft.gamepedia.com/Region_file_format |
| Minecraft Schematics | schematic | X | | X | X | X | https://minecraft.fandom.com/wiki/Schematic_file_format |
| Nick's Voxel Model | nvm | X | | X | | X | |
| Qubicle Exchange | qef | X | X | X | | | https://getqubicle.com/qubicle/documentation/docs/file/qef/ |
| Qubicle Binary Tree | qbt | X | X | X | | X | https://getqubicle.com/qubicle/documentation/docs/file/qbt/ |

View File

@ -5,6 +5,7 @@ set(SRCS
external/tiny_gltf.h
external/json.hpp
private/MinecraftPaletteMap.h private/MinecraftPaletteMap.cpp
private/NamedBinaryTag.h private/NamedBinaryTag.cpp
private/PaletteLookup.h
@ -36,6 +37,7 @@ set(SRCS
SceneGraphNode.h SceneGraphNode.cpp
SceneGraphUtil.h SceneGraphUtil.cpp
SproxelFormat.h SproxelFormat.cpp
SchematicFormat.h SchematicFormat.cpp
STLFormat.h STLFormat.cpp
VolumeCache.h VolumeCache.cpp
VoxFormat.h VoxFormat.cpp
@ -63,6 +65,7 @@ set(TEST_SRCS
tests/QBCLFormatTest.cpp
tests/QEFFormatTest.cpp
tests/SceneGraphTest.cpp
tests/SchematicFormatTest.cpp
tests/SproxelFormatTest.cpp
tests/STLFormatTest.cpp
tests/VoxFormatTest.cpp

View File

@ -13,6 +13,7 @@
#include "io/MemoryReadStream.h"
#include "io/ZipReadStream.h"
#include "private/NamedBinaryTag.h"
#include "private/MinecraftPaletteMap.h"
#include "voxel/MaterialColor.h"
#include "voxel/RawVolumeWrapper.h"
#include "voxelutil/VolumeCropper.h"
@ -384,324 +385,6 @@ voxel::RawVolume *MCRFormat::parseLevelCompound(int dataVersion, const priv::Nam
return finalize(volumes, xPos, zPos);
}
using PaletteMap = core::StringMap<int>;
// this list was found in enkiMI by Doug Binks and extended
static const PaletteMap &getPaletteMap() {
static const PaletteMap mcPalette{{"air", 0},
{"stone", 1},
{"andesite", 1},
{"seagrass", 2},
{"grass", 2},
{"grass_block", 2},
{"dirt", 3},
{"cobblestone", 4},
{"oak_planks", 5},
{"oak_sapling", 6},
{"bedrock", 7},
{"flowing_water", 8},
{"water", 9},
{"flowing_lava", 10},
{"lava", 11},
{"sand", 12},
{"gravel", 13},
{"gold_ore", 14},
{"iron_ore", 15},
{"coal_ore", 16},
{"oak_log", 17},
{"acacia_leaves", 18},
{"spruce_leaves", 18},
{"oak_leaves", 18},
{"jungle_leaves", 18},
{"birch_leaves", 18},
{"sponge", 19},
{"glass", 20},
{"lapis_ore", 21},
{"lapis_block", 22},
{"dispenser", 23},
{"sandstone", 24},
{"note_block", 25},
{"red_bed", 26},
{"powered_rail", 27},
{"detector_rail", 28},
{"sticky_piston", 29},
{"cobweb", 30},
{"tall_grass", 31},
{"tall_seagrass", 31},
{"dead_bush", 32},
{"piston", 33},
{"piston_head", 34},
{"white_concrete", 35},
{"dandelion", 37},
{"poppy", 38},
{"brown_mushroom", 39},
{"red_mushroom", 40},
{"gold_block", 41},
{"iron_block", 42},
{"smooth_stone_slab", 43},
{"stone_slab", 44},
{"brick_wall", 45},
{"bricks", 45},
{"tnt", 46},
{"bookshelf", 47},
{"mossy_cobblestone", 48},
{"obsidian", 49},
{"torch", 50},
{"fire", 51},
{"spawner", 52},
{"oak_stairs", 53},
{"chest", 54},
{"redstone_wire", 55},
{"diamond_ore", 56},
{"diamond_block", 57},
{"crafting_table", 58},
{"wheat", 59},
{"farmland", 60},
{"furnace", 61},
{"campfire", 62},
{"oak_sign", 63},
{"oak_door", 64},
{"ladder", 65},
{"rail", 66},
{"stone_stairs", 67},
{"oak_wall_sign", 68},
{"lever", 69},
{"stone_pressure_plate", 70},
{"iron_door", 71},
{"oak_pressure_plate", 72},
{"redstone_ore", 73},
{"red_concrete", 74},
{"redstone_wall_torch", 75},
{"redstone_torch", 76},
{"stone_button", 77},
{"snow_block", 78},
{"ice", 79},
{"snow", 80},
{"cactus", 81},
{"clay", 82},
{"bamboo", 83},
{"jukebox", 84},
{"oak_fence", 85},
{"pumpkin", 86},
{"netherrack", 87},
{"soul_sand", 88},
{"glowstone", 89},
{"portal", 90},
{"carved_pumpkin", 91},
{"cake", 92},
{"repeater", 93},
{"skeleton_skull", 94},
{"white_stained_glass", 95},
{"oak_trapdoor", 96},
{"turtle_egg", 97},
{"stone_bricks", 98},
{"brown_mushroom_block", 99},
{"red_mushroom_block", 100},
{"iron_bars", 101},
{"light_blue_stained_glass_pane", 102},
{"melon", 103},
{"pumpkin_stem", 104},
{"melon_stem", 105},
{"vine", 106},
{"oak_fence_gate", 107},
{"brick_stairs", 108},
{"stone_brick_stairs", 109},
{"mycelium", 110},
{"light_gray_concrete", 111},
{"nether_brick", 112},
{"nether_brick_fence", 113},
{"nether_brick_stairs", 114},
{"nether_wart", 115},
{"enchanting_table", 116},
{"brewing_stand", 117},
{"cauldron", 118},
{"end_portal", 119},
{"end_portal_frame", 120},
{"end_stone", 121},
{"dragon_egg", 122},
{"redstone_lamp", 123},
{"shroomlight", 124},
{"oak_wood", 125},
{"oak_slab", 126},
{"cocoa", 127},
{"sandstone_stairs", 128},
{"emerald_ore", 129},
{"ender_chest", 130},
{"tripwire_hook", 131},
{"tripwire", 132},
{"emerald_block", 133},
{"spruce_stairs", 134},
{"birch_stairs", 135},
{"jungle_stairs", 136},
{"command_block", 137},
{"beacon", 138},
{"cobblestone_wall", 139},
{"flower_pot", 140},
{"carrots", 141},
{"potatoes", 142},
{"oak_button", 143},
{"skeleton_wall_skull", 144},
{"anvil", 145},
{"trapped_chest", 146},
{"light_weighted_pressure_plate", 147},
{"heavy_weighted_pressure_plate", 148},
{"comparator", 149},
{"chain", 150},
{"daylight_detector", 151},
{"redstone_block", 152},
{"nether_quartz_ore", 153},
{"hopper", 154},
{"quartz_block", 155},
{"quartz_stairs", 156},
{"activator_rail", 157},
{"dropper", 158},
{"pink_stained_glass", 159},
{"white_stained_glass_pane", 160},
{"dead_brain_coral", 161},
{"acacia_planks", 162},
{"acacia_stairs", 163},
{"dark_oak_stairs", 164},
{"slime_block", 165},
{"barrier", 166},
{"iron_trapdoor", 167},
{"prismarine", 168},
{"sea_lantern", 169},
{"hay_block", 170},
{"white_carpet", 171},
{"coarse_dirt", 172},
{"coal_block", 173},
{"packed_ice", 174},
{"orange_concrete", 175},
{"white_banner", 176},
{"white_wall_banner", 177},
{"white_concrete_powder", 178},
{"red_sandstone", 179},
{"red_sandstone_stairs", 180},
{"red_sandstone_wall", 181},
{"red_sandstone_slab", 182},
{"spruce_fence_gate", 183},
{"birch_fence_gate", 184},
{"jungle_fence_gate", 185},
{"dark_oak_fence_gate", 186},
{"acacia_fence_gate", 187},
{"spruce_fence", 188},
{"birch_fence", 189},
{"jungle_fence", 190},
{"dark_oak_fence", 191},
{"acacia_fence", 192},
{"spruce_door", 193},
{"birch_door", 194},
{"jungle_door", 195},
{"acacia_door", 196},
{"dark_oak_door", 197},
{"end_rod", 198},
{"chorus_plant", 199},
{"chorus_flower", 200},
{"purpur_block", 201},
{"purpur_pillar", 202},
{"purpur_stairs", 203},
{"purple_stained_glass", 204},
{"purpur_slab", 205},
{"end_stone_bricks", 206},
{"beetroots", 207},
{"grass_path", 208},
{"end_gateway", 209},
{"repeating_command_block", 210},
{"chain_command_block", 211},
{"frosted_ice", 212},
{"magma_block", 213},
{"nether_wart_block", 214},
{"red_nether_bricks", 215},
{"bone_block", 216},
{"structure_void", 217},
{"observer", 218},
{"white_shulker_box", 219},
{"orange_shulker_box", 220},
{"magenta_shulker_box", 221},
{"light_blue_shulker_box", 222},
{"yellow_shulker_box", 223},
{"lime_shulker_box", 224},
{"pink_shulker_box", 225},
{"gray_shulker_box", 226},
{"light_gray_shulker_box", 227},
{"cyan_shulker_box", 228},
{"purple_shulker_box", 229},
{"blue_shulker_box", 230},
{"brown_shulker_box", 231},
{"green_shulker_box", 232},
{"red_shulker_box", 233},
{"black_shulker_box", 234},
{"white_glazed_terracotta", 235},
{"orange_glazed_terracotta", 236},
{"magenta_glazed_terracotta", 237},
{"light_blue_glazed_terracotta", 238},
{"yellow_glazed_terracotta", 239},
{"lime_glazed_terracotta", 240},
{"pink_glazed_terracotta", 241},
{"gray_glazed_terracotta", 242},
{"light_gray_glazed_terracotta", 243},
{"cyan_glazed_terracotta", 244},
{"purple_glazed_terracotta", 245},
{"blue_glazed_terracotta", 246},
{"brown_glazed_terracotta", 247},
{"green_glazed_terracotta", 248},
{"red_glazed_terracotta", 249},
{"black_glazed_terracotta", 250},
{"gray_concrete", 251},
{"gray_concrete_powder", 252},
{"deepslate_redstone_ore", 1}, // TODO
{"deepslate_iron_ore", 1}, // TODO
{"kelp", 1}, // TODO
{"deepslate", 1}, // TODO
{"moss_carpet", 1}, // TODO
{"granite", 1}, // TODO
{"diorite", 1}, // TODO
{"glow_lichen", 1}, // TODO
{"copper_ore", 1}, // TODO
{"tuff", 1}, // TODO
{"deepslate_gold_ore", 1}, // TODO
{"flowering_azalea", 1}, // TODO
{"azalea", 1}, // TODO
{"cave_vines", 1}, // TODO
{"cave_vines_plant", 1}, // TODO
{"big_dripleaf", 1}, // TODO
{"big_dripleaf_stem", 1}, // TODO
{"spore_blossom", 1}, // TODO
{"deepslate_diamond_ore", 1}, // TODO
{"budding_amethyst", 1}, // TODO
{"smooth_basalt", 1}, // TODO
{"birch_log", 1}, // TODO
{"cave_air", 1}, // TODO
{"kelp_plant", 1}, // TODO
{"deepslate_lapis_ore", 1}, // TODO
{"deepslate_copper_ore", 1}, // TODO
{"moss_block", 1}, // TODO
{"small_amethyst_bud", 1}, // TODO
{"calcite", 1}, // TODO
{"amethyst_block", 1}, // TODO
{"medium_amethyst_bud", 1}, // TODO
{"large_amethyst_bud", 1}, // TODO
{"amethyst_cluster", 1}, // TODO
{"mossy_stone_bricks", 1}, // TODO
{"cracked_stone_bricks", 1}, // TODO
{"small_dripleaf", 1}, // TODO
{"deepslate_coal_ore", 1}, // TODO
{"fern", 1}, // TODO
{"raw_copper_block", 1}, // TODO
{"raw_iron_block", 1}, // TODO
{"jungle_log", 1}, // TODO
{"wall_torch", 1}, // TODO
{"raw_iron_block", 1}, // TODO
{"polished_granite", 1}, // TODO
{"cut_sandstone", 1}, // TODO
{"oxeye_daisy", 1}, // TODO
{"sugar_cane", 1}, // TODO
{"azure_bluet", 1}, // TODO
{"cornflower", 1}, // TODO
{"structure_block", 255}};
return mcPalette;
}
bool MCRFormat::parsePaletteList(int dataVersion, const priv::NamedBinaryTag &palette, MinecraftSectionPalette &sectionPal) {
// prior to 1.16 (2556) the palette entries used multiple 64bit fields
// TODO const bool paletteMultiBits = dataVersion < 2556;
@ -736,7 +419,7 @@ bool MCRFormat::parsePaletteList(int dataVersion, const priv::NamedBinaryTag &pa
continue;
}
// skip minecraft:
const core::String key = value->substr(10);
const core::String key = value->contains("minecraft:") ? value->substr(10) : *value;
auto iter = map.find(key);
if (iter == map.end()) {
Log::debug("Could not find a color mapping for '%s'", key.c_str());
@ -752,4 +435,4 @@ bool MCRFormat::parsePaletteList(int dataVersion, const priv::NamedBinaryTag &pa
#undef wrap
} // namespace voxel
} // namespace voxelformat

View File

@ -0,0 +1,115 @@
/**
* @file
*/
#include "SchematicFormat.h"
#include "core/Color.h"
#include "core/Common.h"
#include "core/Log.h"
#include "core/StringUtil.h"
#include "core/collection/DynamicArray.h"
#include "core/collection/StringMap.h"
#include "io/File.h"
#include "io/MemoryReadStream.h"
#include "io/ZipReadStream.h"
#include "private/MinecraftPaletteMap.h"
#include "private/NamedBinaryTag.h"
#include "voxel/MaterialColor.h"
#include "voxel/Palette.h"
#include "voxel/RawVolume.h"
#include "voxel/RawVolumeWrapper.h"
#include "voxel/Region.h"
#include "voxel/Voxel.h"
#include "voxelutil/VolumeCropper.h"
#include "voxelutil/VolumeMerger.h"
#include <glm/common.hpp>
namespace voxelformat {
bool SchematicFormat::loadGroups(const core::String &filename, io::SeekableReadStream &stream, SceneGraph &sceneGraph) {
_palette.minecraft();
const voxel::Palette &palette = voxel::getPalette();
for (size_t i = 0; i < _palette.size(); ++i) {
_paletteMapping[i] = palette.getClosestMatch(core::Color::fromRGBA(_palette.colors[i]));
}
io::ZipReadStream zipStream(stream);
priv::NamedBinaryTagContext ctx;
ctx.stream = &zipStream;
const priv::NamedBinaryTag &schematic = priv::NamedBinaryTag::parse(ctx);
if (!schematic.valid()) {
Log::error("Could not find 'Schematic' tag");
return false;
}
const int16_t width = schematic.get("Width").int16();
const int16_t height = schematic.get("Height").int16();
const int16_t depth = schematic.get("Length").int16();
voxel::RawVolume *volume = new voxel::RawVolume(voxel::Region(0, 0, 0, width, height, depth));
const priv::NamedBinaryTag &blocks = schematic.get("Blocks");
if (!blocks.valid()) {
Log::error("Could not find 'Blocks' tag");
return false;
}
// const int8_t itemStackVersion = schematic.get("itemStackVersion").int8(); // MCEdit2
core::Buffer<int> pal;
pal.resize(voxel::PaletteMaxColors);
int paletteEntry = 0;
const priv::NamedBinaryTag &blockIds = schematic.get("BlockIDs"); // MCEdit2
if (blockIds.valid()) {
const int blockCnt = (int)blockIds.compound()->size();
const PaletteMap &map = getPaletteMap();
for (int i = 0; i < blockCnt; ++i) {
const priv::NamedBinaryTag &nbt = blockIds.get(core::String::format("%i", i));
const core::String *value = nbt.string();
if (value == nullptr) {
continue;
}
// skip minecraft:
const core::String key = value->contains("minecraft:") ? value->substr(10) : *value;
auto iter = map.find(key);
if (iter == map.end()) {
Log::debug("Could not find a color mapping for '%s'", key.c_str());
pal[paletteEntry] = -1;
} else {
pal[paletteEntry] = iter->value;
}
++paletteEntry;
}
}
// const priv::NamedBinaryTag &materials = schematic.get("Materials");
// Classic, Pocket, Alpha
// const priv::NamedBinaryTag &schematicaMapping = schematic.get("SchematicaMapping");
// const priv::NamedBinaryTag &data = schematic.get("Data");
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
for (int z = 0; z < depth; ++z) {
const int idx = (y * depth + z) * width + x;
const uint8_t palIdx = (*blocks.byteArray())[idx];
if (palIdx != 0u) {
if (paletteEntry == 0) {
volume->setVoxel(x, y, z, voxel::createVoxel(voxel::VoxelType::Generic, palIdx));
} else {
volume->setVoxel(x, y, z, voxel::createVoxel(voxel::VoxelType::Generic, pal[palIdx]));
}
}
}
}
}
const int32_t x = schematic.get("x").int32();
const int32_t y = schematic.get("y").int32();
const int32_t z = schematic.get("z").int32();
volume->translate(glm::ivec3(x, y, z));
SceneGraphNode node(SceneGraphNodeType::Model);
node.setVolume(volume, true);
sceneGraph.emplace(core::move(node));
return true;
}
} // namespace voxelformat

View File

@ -0,0 +1,31 @@
/**
* @file
*/
#pragma once
#include "Format.h"
namespace io {
class ZipReadStream;
}
namespace voxelformat {
namespace priv {
class NamedBinaryTag;
}
/**
* @note https://minecraft.fandom.com/wiki/Schematic_file_format
*/
class SchematicFormat : public Format {
public:
bool loadGroups(const core::String &filename, io::SeekableReadStream& stream, SceneGraph& sceneGraph) override;
bool saveGroups(const SceneGraph& sceneGraph, const core::String &filename, io::SeekableWriteStream& stream) override {
return false;
}
};
}

View File

@ -39,6 +39,7 @@
#include "voxelformat/OBJFormat.h"
#include "voxelformat/VoxOldFormat.h"
#include "voxelformat/GLTFFormat.h"
#include "voxelformat/SchematicFormat.h"
namespace voxelformat {
@ -65,6 +66,7 @@ const io::FormatDescription SUPPORTED_VOXEL_FORMATS_LOAD[] = {
{"Goxel", "gox", [] (uint32_t magic) {return magic == FourCC('G','O','X',' ');}, VOX_FORMAT_FLAG_SCREENSHOT_EMBEDDED},
{"CubeWorld", "cub", nullptr, VOX_FORMAT_FLAG_PALETTE_EMBEDDED},
{"Minecraft region", "mca", nullptr, VOX_FORMAT_FLAG_PALETTE_EMBEDDED},
{"Minecraft schematic", "schematic", nullptr, VOX_FORMAT_FLAG_PALETTE_EMBEDDED},
{"Sproxel csv", "csv", nullptr, 0u},
{"Wavefront Object", "obj", nullptr, 0u},
{"Standard Triangle Language", "stl", nullptr, 0u},
@ -191,6 +193,8 @@ static core::SharedPtr<Format> getFormat(const io::FormatDescription *desc, uint
format = core::make_shared<PLYFormat>();
} else if (ext == "fbx") {
format = core::make_shared<FBXFormat>();
} else if (ext == "schematic") {
format = core::make_shared<SchematicFormat>();
} else if (ext == "gltf" || ext == "glb") {
format = core::make_shared<GLTFFormat>();
}

View File

@ -0,0 +1,325 @@
/**
* @file
*/
#include "MinecraftPaletteMap.h"
namespace voxelformat {
const PaletteMap &getPaletteMap() {
// https://github.com/mcedit/mcedit2/tree/master/src/mceditlib/blocktypes
static const PaletteMap mcPalette{{"air", 0},
{"stone", 1},
{"andesite", 1},
{"seagrass", 2},
{"grass", 2},
{"grass_block", 2},
{"dirt", 3},
{"cobblestone", 4},
{"oak_planks", 5},
{"oak_sapling", 6},
{"bedrock", 7},
{"flowing_water", 8},
{"water", 9},
{"flowing_lava", 10},
{"lava", 11},
{"sand", 12},
{"gravel", 13},
{"gold_ore", 14},
{"iron_ore", 15},
{"coal_ore", 16},
{"oak_log", 17},
{"acacia_leaves", 18},
{"spruce_leaves", 18},
{"oak_leaves", 18},
{"jungle_leaves", 18},
{"birch_leaves", 18},
{"sponge", 19},
{"glass", 20},
{"lapis_ore", 21},
{"lapis_block", 22},
{"dispenser", 23},
{"sandstone", 24},
{"note_block", 25},
{"red_bed", 26},
{"powered_rail", 27},
{"detector_rail", 28},
{"sticky_piston", 29},
{"cobweb", 30},
{"tall_grass", 31},
{"tall_seagrass", 31},
{"dead_bush", 32},
{"piston", 33},
{"piston_head", 34},
{"white_concrete", 35},
{"dandelion", 37},
{"poppy", 38},
{"brown_mushroom", 39},
{"red_mushroom", 40},
{"gold_block", 41},
{"iron_block", 42},
{"smooth_stone_slab", 43},
{"stone_slab", 44},
{"brick_wall", 45},
{"bricks", 45},
{"tnt", 46},
{"bookshelf", 47},
{"mossy_cobblestone", 48},
{"obsidian", 49},
{"torch", 50},
{"fire", 51},
{"spawner", 52},
{"oak_stairs", 53},
{"chest", 54},
{"redstone_wire", 55},
{"diamond_ore", 56},
{"diamond_block", 57},
{"crafting_table", 58},
{"wheat", 59},
{"farmland", 60},
{"furnace", 61},
{"campfire", 62},
{"oak_sign", 63},
{"oak_door", 64},
{"ladder", 65},
{"rail", 66},
{"stone_stairs", 67},
{"oak_wall_sign", 68},
{"lever", 69},
{"stone_pressure_plate", 70},
{"iron_door", 71},
{"oak_pressure_plate", 72},
{"redstone_ore", 73},
{"red_concrete", 74},
{"redstone_wall_torch", 75},
{"redstone_torch", 76},
{"stone_button", 77},
{"snow_block", 78},
{"ice", 79},
{"snow", 80},
{"cactus", 81},
{"clay", 82},
{"bamboo", 83},
{"jukebox", 84},
{"oak_fence", 85},
{"pumpkin", 86},
{"netherrack", 87},
{"soul_sand", 88},
{"glowstone", 89},
{"portal", 90},
{"carved_pumpkin", 91},
{"cake", 92},
{"repeater", 93},
{"skeleton_skull", 94},
{"white_stained_glass", 95},
{"oak_trapdoor", 96},
{"turtle_egg", 97},
{"stone_bricks", 98},
{"brown_mushroom_block", 99},
{"red_mushroom_block", 100},
{"iron_bars", 101},
{"light_blue_stained_glass_pane", 102},
{"melon", 103},
{"pumpkin_stem", 104},
{"melon_stem", 105},
{"vine", 106},
{"oak_fence_gate", 107},
{"brick_stairs", 108},
{"stone_brick_stairs", 109},
{"mycelium", 110},
{"light_gray_concrete", 111},
{"nether_brick", 112},
{"nether_brick_fence", 113},
{"nether_brick_stairs", 114},
{"nether_wart", 115},
{"enchanting_table", 116},
{"brewing_stand", 117},
{"cauldron", 118},
{"end_portal", 119},
{"end_portal_frame", 120},
{"end_stone", 121},
{"dragon_egg", 122},
{"redstone_lamp", 123},
{"shroomlight", 124},
{"oak_wood", 125},
{"oak_slab", 126},
{"cocoa", 127},
{"sandstone_stairs", 128},
{"emerald_ore", 129},
{"ender_chest", 130},
{"tripwire_hook", 131},
{"tripwire", 132},
{"emerald_block", 133},
{"spruce_stairs", 134},
{"birch_stairs", 135},
{"jungle_stairs", 136},
{"command_block", 137},
{"beacon", 138},
{"cobblestone_wall", 139},
{"flower_pot", 140},
{"carrots", 141},
{"potatoes", 142},
{"oak_button", 143},
{"skeleton_wall_skull", 144},
{"anvil", 145},
{"trapped_chest", 146},
{"light_weighted_pressure_plate", 147},
{"heavy_weighted_pressure_plate", 148},
{"comparator", 149},
{"chain", 150},
{"daylight_detector", 151},
{"redstone_block", 152},
{"nether_quartz_ore", 153},
{"hopper", 154},
{"quartz_block", 155},
{"quartz_stairs", 156},
{"activator_rail", 157},
{"dropper", 158},
{"pink_stained_glass", 159},
{"white_stained_glass_pane", 160},
{"dead_brain_coral", 161},
{"acacia_planks", 162},
{"acacia_stairs", 163},
{"dark_oak_stairs", 164},
{"slime_block", 165},
{"barrier", 166},
{"iron_trapdoor", 167},
{"prismarine", 168},
{"sea_lantern", 169},
{"hay_block", 170},
{"white_carpet", 171},
{"coarse_dirt", 172},
{"coal_block", 173},
{"packed_ice", 174},
{"orange_concrete", 175},
{"white_banner", 176},
{"white_wall_banner", 177},
{"white_concrete_powder", 178},
{"red_sandstone", 179},
{"red_sandstone_stairs", 180},
{"red_sandstone_wall", 181},
{"red_sandstone_slab", 182},
{"spruce_fence_gate", 183},
{"birch_fence_gate", 184},
{"jungle_fence_gate", 185},
{"dark_oak_fence_gate", 186},
{"acacia_fence_gate", 187},
{"spruce_fence", 188},
{"birch_fence", 189},
{"jungle_fence", 190},
{"dark_oak_fence", 191},
{"acacia_fence", 192},
{"spruce_door", 193},
{"birch_door", 194},
{"jungle_door", 195},
{"acacia_door", 196},
{"dark_oak_door", 197},
{"end_rod", 198},
{"chorus_plant", 199},
{"chorus_flower", 200},
{"purpur_block", 201},
{"purpur_pillar", 202},
{"purpur_stairs", 203},
{"purple_stained_glass", 204},
{"purpur_slab", 205},
{"end_stone_bricks", 206},
{"beetroots", 207},
{"grass_path", 208},
{"end_gateway", 209},
{"repeating_command_block", 210},
{"chain_command_block", 211},
{"frosted_ice", 212},
{"magma_block", 213},
{"nether_wart_block", 214},
{"red_nether_bricks", 215},
{"bone_block", 216},
{"structure_void", 217},
{"observer", 218},
{"white_shulker_box", 219},
{"orange_shulker_box", 220},
{"magenta_shulker_box", 221},
{"light_blue_shulker_box", 222},
{"yellow_shulker_box", 223},
{"lime_shulker_box", 224},
{"pink_shulker_box", 225},
{"gray_shulker_box", 226},
{"light_gray_shulker_box", 227},
{"cyan_shulker_box", 228},
{"purple_shulker_box", 229},
{"blue_shulker_box", 230},
{"brown_shulker_box", 231},
{"green_shulker_box", 232},
{"red_shulker_box", 233},
{"black_shulker_box", 234},
{"white_glazed_terracotta", 235},
{"orange_glazed_terracotta", 236},
{"magenta_glazed_terracotta", 237},
{"light_blue_glazed_terracotta", 238},
{"yellow_glazed_terracotta", 239},
{"lime_glazed_terracotta", 240},
{"pink_glazed_terracotta", 241},
{"gray_glazed_terracotta", 242},
{"light_gray_glazed_terracotta", 243},
{"cyan_glazed_terracotta", 244},
{"purple_glazed_terracotta", 245},
{"blue_glazed_terracotta", 246},
{"brown_glazed_terracotta", 247},
{"green_glazed_terracotta", 248},
{"red_glazed_terracotta", 249},
{"black_glazed_terracotta", 250},
{"gray_concrete", 251},
{"gray_concrete_powder", 252},
{"deepslate_redstone_ore", 1}, // TODO
{"deepslate_iron_ore", 1}, // TODO
{"kelp", 1}, // TODO
{"deepslate", 1}, // TODO
{"moss_carpet", 1}, // TODO
{"granite", 1}, // TODO
{"diorite", 1}, // TODO
{"glow_lichen", 1}, // TODO
{"copper_ore", 1}, // TODO
{"tuff", 1}, // TODO
{"deepslate_gold_ore", 1}, // TODO
{"flowering_azalea", 1}, // TODO
{"azalea", 1}, // TODO
{"cave_vines", 1}, // TODO
{"cave_vines_plant", 1}, // TODO
{"big_dripleaf", 1}, // TODO
{"big_dripleaf_stem", 1}, // TODO
{"spore_blossom", 1}, // TODO
{"deepslate_diamond_ore", 1}, // TODO
{"budding_amethyst", 1}, // TODO
{"smooth_basalt", 1}, // TODO
{"birch_log", 1}, // TODO
{"cave_air", 1}, // TODO
{"kelp_plant", 1}, // TODO
{"deepslate_lapis_ore", 1}, // TODO
{"deepslate_copper_ore", 1}, // TODO
{"moss_block", 1}, // TODO
{"small_amethyst_bud", 1}, // TODO
{"calcite", 1}, // TODO
{"amethyst_block", 1}, // TODO
{"medium_amethyst_bud", 1}, // TODO
{"large_amethyst_bud", 1}, // TODO
{"amethyst_cluster", 1}, // TODO
{"mossy_stone_bricks", 1}, // TODO
{"cracked_stone_bricks", 1}, // TODO
{"small_dripleaf", 1}, // TODO
{"deepslate_coal_ore", 1}, // TODO
{"fern", 1}, // TODO
{"raw_copper_block", 1}, // TODO
{"raw_iron_block", 1}, // TODO
{"jungle_log", 1}, // TODO
{"wall_torch", 1}, // TODO
{"raw_iron_block", 1}, // TODO
{"polished_granite", 1}, // TODO
{"cut_sandstone", 1}, // TODO
{"oxeye_daisy", 1}, // TODO
{"sugar_cane", 1}, // TODO
{"azure_bluet", 1}, // TODO
{"cornflower", 1}, // TODO
{"structure_block", 255}};
return mcPalette;
}
} // namespace voxelformat

View File

@ -0,0 +1,14 @@
/**
* @file
*/
#include "core/collection/StringMap.h"
namespace voxelformat {
using PaletteMap = core::StringMap<int>;
// this list was found in enkiMI by Doug Binks and extended
const PaletteMap &getPaletteMap();
} // namespace voxelformat

View File

@ -0,0 +1,21 @@
/**
* @file
*/
#include "voxelformat/SchematicFormat.h"
#include "AbstractVoxFormatTest.h"
#include "io/FileStream.h"
#include "voxelformat/VolumeFormat.h"
namespace voxelformat {
class SchematicFormatTest : public AbstractVoxFormatTest {};
TEST_F(SchematicFormatTest, testLoad) {
SchematicFormat f;
// https://www.planetminecraft.com/project/viking-island-4911284/
std::unique_ptr<voxel::RawVolume> volume(load("viking_island.schematic", f));
ASSERT_NE(nullptr, volume) << "Could not load schematic file";
}
} // namespace voxelformat