use of org.spongepowered.api.world.schematic.Schematic in project SpongeCommon by SpongePowered.
the class SchematicTranslator method translate.
@Override
public Schematic translate(DataView view) throws InvalidDataException {
int version = view.getInt(DataQueries.Schematic.VERSION).get();
// TODO version conversions
if (version != VERSION) {
throw new InvalidDataException(String.format("Unknown schematic version %d (current version is %d)", version, VERSION));
}
DataView metadata = view.getView(DataQueries.Schematic.METADATA).orElse(null);
if (metadata != null) {
Optional<DataView> dot_data = metadata.getView(DataQuery.of("."));
if (dot_data.isPresent()) {
DataView data = dot_data.get();
for (DataQuery key : data.getKeys(false)) {
if (!metadata.contains(key)) {
metadata.set(key, data.get(key).get());
}
}
}
}
// TODO error handling for these optionals
int width = view.getShort(DataQueries.Schematic.WIDTH).get();
int height = view.getShort(DataQueries.Schematic.HEIGHT).get();
int length = view.getShort(DataQueries.Schematic.LENGTH).get();
if (width > MAX_SIZE || height > MAX_SIZE || length > MAX_SIZE) {
throw new InvalidDataException(String.format("Schematic is larger than maximum allowable size (found: (%d, %d, %d) max: (%d, %<d, %<d)", width, height, length, MAX_SIZE));
}
int[] offset = (int[]) view.get(DataQueries.Schematic.OFFSET).orElse(null);
if (offset == null) {
offset = new int[3];
}
if (offset.length != 3) {
throw new InvalidDataException("Schematic offset was not of length 3");
}
BlockPalette palette;
Optional<DataView> paletteData = view.getView(DataQueries.Schematic.PALETTE);
int palette_max = view.getInt(DataQueries.Schematic.PALETTE_MAX).orElse(0xFFFF);
if (paletteData.isPresent()) {
// If we had a default palette_max we don't want to allocate all
// that space for nothing so we use a sensible default instead
palette = new BimapPalette(palette_max != 0xFFFF ? palette_max : 64);
DataView paletteMap = paletteData.get();
Set<DataQuery> paletteKeys = paletteMap.getKeys(false);
for (DataQuery key : paletteKeys) {
BlockState state = Sponge.getRegistry().getType(BlockState.class, key.getParts().get(0)).get();
((BimapPalette) palette).assign(state, paletteMap.getInt(key).get());
}
} else {
palette = GlobalPalette.instance;
}
MutableBlockVolume buffer = new ArrayMutableBlockBuffer(palette, new Vector3i(-offset[0], -offset[1], -offset[2]), new Vector3i(width, height, length));
byte[] blockdata = (byte[]) view.get(DataQueries.Schematic.BLOCK_DATA).get();
int index = 0;
int i = 0;
int value = 0;
int varint_length = 0;
while (i < blockdata.length) {
value = 0;
varint_length = 0;
while (true) {
value |= (blockdata[i] & 127) << (varint_length++ * 7);
if (varint_length > 5) {
throw new RuntimeException("VarInt too big (probably corrupted data)");
}
if ((blockdata[i] & 128) != 128) {
i++;
break;
}
i++;
}
// index = (y * length + z) * width + x
int y = index / (width * length);
int z = (index % (width * length)) / width;
int x = (index % (width * length)) % width;
BlockState state = palette.get(value).get();
buffer.setBlock(x - offset[0], y - offset[1], z - offset[2], state);
index++;
}
Map<Vector3i, TileEntityArchetype> tiles = Maps.newHashMap();
List<DataView> tiledata = view.getViewList(DataQueries.Schematic.TILEENTITY_DATA).orElse(null);
if (tiledata != null) {
for (DataView tile : tiledata) {
int[] pos = (int[]) tile.get(DataQueries.Schematic.TILEENTITY_POS).get();
if (offset.length != 3) {
throw new InvalidDataException("Schematic tileentity pos was not of length 3");
}
TileEntityType type = TileEntityTypeRegistryModule.getInstance().getForClass(TileEntity.REGISTRY.getObject(new ResourceLocation(tile.getString(DataQuery.of("id")).get())));
TileEntityArchetype archetype = new SpongeTileEntityArchetypeBuilder().state(buffer.getBlock(pos[0] - offset[0], pos[1] - offset[1], pos[2] - offset[2])).tileData(tile).tile(type).build();
tiles.put(new Vector3i(pos[0] - offset[0], pos[1] - offset[1], pos[2] - offset[2]), archetype);
}
}
Schematic schematic = new SpongeSchematic(buffer, tiles, metadata);
return schematic;
}
use of org.spongepowered.api.world.schematic.Schematic in project SpongeCommon by SpongePowered.
the class CopyPasta method onGamePreInitialization.
@Listener
public void onGamePreInitialization(GamePreInitializationEvent event) {
this.schematicsDir = new File(this.config, "schematics");
this.schematicsDir.mkdirs();
this.logger.info("Saving schematics to " + this.schematicsDir.getAbsolutePath());
Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Copies a region of the world to your clipboard")).permission(PLUGIN_ID + ".command.copy").executor((src, args) -> {
if (!(src instanceof Player)) {
src.sendMessage(Text.of(TextColors.RED, "Player only."));
return CommandResult.success();
}
Player player = (Player) src;
PlayerData data = get(player);
if (data.getPos1() == null || data.getPos2() == null) {
player.sendMessage(Text.of(TextColors.RED, "You must set both positions before copying"));
return CommandResult.success();
}
Vector3i min = data.getPos1().min(data.getPos2());
Vector3i max = data.getPos1().max(data.getPos2());
ArchetypeVolume volume = player.getWorld().createArchetypeVolume(min, max, player.getLocation().getPosition().toInt());
data.setClipboard(volume);
player.sendMessage(Text.of(TextColors.GREEN, "Saved to clipboard."));
return CommandResult.success();
}).build(), "copy");
Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Pastes your clipboard at your current position")).permission(PLUGIN_ID + ".command.paste").executor((src, args) -> {
if (!(src instanceof Player)) {
src.sendMessage(Text.of(TextColors.RED, "Player only."));
return CommandResult.success();
}
Player player = (Player) src;
PlayerData data = get(player);
ArchetypeVolume volume = data.getClipboard();
if (volume == null) {
player.sendMessage(Text.of(TextColors.RED, "You must copy something before pasting"));
return CommandResult.success();
}
Sponge.getCauseStackManager().pushCause(this);
volume.apply(player.getLocation(), BlockChangeFlags.ALL);
Sponge.getCauseStackManager().popCause();
player.sendMessage(Text.of(TextColors.GREEN, "Pasted clipboard into world."));
return CommandResult.success();
}).build(), "paste");
Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Saves your clipboard to disk")).permission(PLUGIN_ID + ".command.save").arguments(seq(string(Text.of("format")), string(Text.of("name")))).executor((src, args) -> {
if (!(src instanceof Player)) {
src.sendMessage(Text.of(TextColors.RED, "Player only."));
return CommandResult.success();
}
String format = args.getOne("format").get().toString();
String name = args.getOne("name").get().toString();
Player player = (Player) src;
PlayerData data = get(player);
ArchetypeVolume volume = data.getClipboard();
if (volume == null) {
player.sendMessage(Text.of(TextColors.RED, "You must copy something before saving"));
return CommandResult.success();
}
if (!"legacy".equalsIgnoreCase(format) && !"sponge".equalsIgnoreCase(format)) {
player.sendMessage(Text.of(TextColors.RED, "Unsupported schematic format, supported formats are [legacy, sponge]"));
return CommandResult.success();
}
Schematic schematic = Schematic.builder().volume(data.getClipboard()).metaValue(Schematic.METADATA_AUTHOR, player.getName()).metaValue(Schematic.METADATA_NAME, name).paletteType(BlockPaletteTypes.LOCAL).build();
DataContainer schematicData = null;
if ("legacy".equalsIgnoreCase(format)) {
schematicData = DataTranslators.LEGACY_SCHEMATIC.translate(schematic);
} else if ("sponge".equalsIgnoreCase(format)) {
schematicData = DataTranslators.SCHEMATIC.translate(schematic);
}
File outputFile = new File(this.schematicsDir, name + ".schematic");
try {
DataFormats.NBT.writeTo(new GZIPOutputStream(new FileOutputStream(outputFile)), schematicData);
player.sendMessage(Text.of(TextColors.GREEN, "Saved schematic to " + outputFile.getAbsolutePath()));
} catch (Exception e) {
e.printStackTrace();
player.sendMessage(Text.of(TextColors.DARK_RED, "Error saving schematic: " + e.getMessage()));
return CommandResult.success();
}
return CommandResult.success();
}).build(), "save");
Sponge.getCommandManager().register(this, CommandSpec.builder().description(Text.of("Loads a schematic from disk to your clipboard")).permission(PLUGIN_ID + ".command.load").arguments(seq(string(Text.of("format")), string(Text.of("name")))).executor((src, args) -> {
if (!(src instanceof Player)) {
src.sendMessage(Text.of(TextColors.RED, "Player only."));
return CommandResult.success();
}
String format = args.getOne("format").get().toString();
String name = args.getOne("name").get().toString();
Player player = (Player) src;
PlayerData data = get(player);
if (!"legacy".equalsIgnoreCase(format) && !"sponge".equalsIgnoreCase(format)) {
player.sendMessage(Text.of(TextColors.RED, "Unsupported schematic format, supported formats are [legacy, sponge]"));
return CommandResult.success();
}
File inputFile = new File(this.schematicsDir, name + ".schematic");
if (!inputFile.exists()) {
player.sendMessage(Text.of(TextColors.RED, "Schematic at " + inputFile.getAbsolutePath() + " not found."));
return CommandResult.success();
}
DataContainer schematicData = null;
try {
schematicData = DataFormats.NBT.readFrom(new GZIPInputStream(new FileInputStream(inputFile)));
} catch (Exception e) {
e.printStackTrace();
player.sendMessage(Text.of(TextColors.DARK_RED, "Error loading schematic: " + e.getMessage()));
return CommandResult.success();
}
Schematic schematic = null;
if ("legacy".equalsIgnoreCase(format)) {
schematic = DataTranslators.LEGACY_SCHEMATIC.translate(schematicData);
} else if ("sponge".equalsIgnoreCase(format)) {
schematic = DataTranslators.SCHEMATIC.translate(schematicData);
}
player.sendMessage(Text.of(TextColors.GREEN, "Loaded schematic from " + inputFile.getAbsolutePath()));
data.setClipboard(schematic);
return CommandResult.success();
}).build(), "load");
}
Aggregations