use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.
the class MCEditSchematicReader method read.
@Override
public Clipboard read() throws IOException {
// Schematic tag
NamedTag rootTag = inputStream.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
throw new IOException("Tag 'Schematic' does not exist or is not first");
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
if (!schematic.containsKey("Blocks")) {
throw new IOException("Schematic file is missing a 'Blocks' tag");
}
// Check type of Schematic
String materials = requireTag(schematic, "Materials", StringTag.class).getValue();
if (!materials.equals("Alpha")) {
throw new IOException("Schematic file is not an Alpha schematic");
}
// ====================================================================
// Metadata
// ====================================================================
BlockVector3 origin;
Region region;
// Get information
short width = requireTag(schematic, "Width", ShortTag.class).getValue();
short height = requireTag(schematic, "Height", ShortTag.class).getValue();
short length = requireTag(schematic, "Length", ShortTag.class).getValue();
try {
int originX = requireTag(schematic, "WEOriginX", IntTag.class).getValue();
int originY = requireTag(schematic, "WEOriginY", IntTag.class).getValue();
int originZ = requireTag(schematic, "WEOriginZ", IntTag.class).getValue();
BlockVector3 min = BlockVector3.at(originX, originY, originZ);
int offsetX = requireTag(schematic, "WEOffsetX", IntTag.class).getValue();
int offsetY = requireTag(schematic, "WEOffsetY", IntTag.class).getValue();
int offsetZ = requireTag(schematic, "WEOffsetZ", IntTag.class).getValue();
BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
origin = min.subtract(offset);
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
} catch (IOException ignored) {
origin = BlockVector3.ZERO;
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
}
// ====================================================================
// Blocks
// ====================================================================
// Get blocks
byte[] blockId = requireTag(schematic, "Blocks", ByteArrayTag.class).getValue();
byte[] blockData = requireTag(schematic, "Data", ByteArrayTag.class).getValue();
byte[] addId = new byte[0];
// Have to later combine IDs
short[] blocks = new short[blockId.length];
// the highest 4 bits are stored in a separate byte array.
if (schematic.containsKey("AddBlocks")) {
addId = requireTag(schematic, "AddBlocks", ByteArrayTag.class).getValue();
}
// Combine the AddBlocks data with the first 8-bit block ID
for (int index = 0; index < blockId.length; index++) {
if ((index >> 1) >= addId.length) {
// No corresponding AddBlocks index
blocks[index] = (short) (blockId[index] & 0xFF);
} else {
if ((index & 1) == 0) {
blocks[index] = (short) (((addId[index >> 1] & 0x0F) << 8) + (blockId[index] & 0xFF));
} else {
blocks[index] = (short) (((addId[index >> 1] & 0xF0) << 4) + (blockId[index] & 0xFF));
}
}
}
// Need to pull out tile entities
final ListTag tileEntityTag = getTag(schematic, "TileEntities", ListTag.class);
List<Tag> tileEntities = tileEntityTag == null ? new ArrayList<>() : tileEntityTag.getValue();
BlockMap<BaseBlock> tileEntityBlocks = BlockMap.createForBaseBlock();
for (Tag tag : tileEntities) {
if (!(tag instanceof CompoundTag)) {
continue;
}
CompoundTag t = (CompoundTag) tag;
Map<String, Tag> values = new HashMap<>(t.getValue());
String id = t.getString("id");
values.put("id", new StringTag(convertBlockEntityId(id)));
int x = t.getInt("x");
int y = t.getInt("y");
int z = t.getInt("z");
int index = y * width * length + z * width + x;
// position in schematics?
if (index >= blocks.length) {
LOGGER.warn("Skipping corrupt tile entity at position {} {} {} in schematic.", x, y, z);
continue;
}
BlockState block = getBlockState(blocks[index], blockData[index]);
BlockState newBlock = block;
if (newBlock != null) {
for (NBTCompatibilityHandler handler : COMPATIBILITY_HANDLERS) {
if (handler.isAffectedBlock(newBlock)) {
newBlock = handler.updateNBT(block, values).toImmutableState();
if (newBlock == null || values.isEmpty()) {
break;
}
}
}
}
if (values.isEmpty()) {
t = null;
} else {
t = new CompoundTag(values);
}
if (fixer != null && t != null) {
// FAWE start - BinaryTag
t = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp(DataFixer.FixTypes.BLOCK_ENTITY, t.asBinaryTag(), -1));
// FAWE end
}
BlockVector3 vec = BlockVector3.at(x, y, z);
// Insert into the map if we have changed the block or have a tag
BlockState blockToInsert = newBlock != null ? newBlock : (t != null ? block : null);
if (blockToInsert != null) {
BaseBlock baseBlock = t != null ? blockToInsert.toBaseBlock(new CompoundTag(t.getValue())) : blockToInsert.toBaseBlock();
tileEntityBlocks.put(vec, baseBlock);
}
}
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
clipboard.setOrigin(origin);
Set<Integer> unknownBlocks = new HashSet<>();
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
for (int z = 0; z < length; ++z) {
int index = y * width * length + z * width + x;
BlockVector3 pt = BlockVector3.at(x, y, z);
BaseBlock state = Optional.ofNullable(tileEntityBlocks.get(pt)).orElseGet(() -> {
BlockState blockState = getBlockState(blocks[index], blockData[index]);
return blockState == null ? null : blockState.toBaseBlock();
});
try {
if (state != null) {
clipboard.setBlock(region.getMinimumPoint().add(pt), state);
} else {
short block = blocks[index];
byte data = blockData[index];
int combined = block << 8 | data;
if (unknownBlocks.add(combined)) {
LOGGER.warn("Unknown block when loading schematic: {} {}. This is most likely a" + "bad schematic.", block, data);
}
}
} catch (WorldEditException ignored) {
// BlockArrayClipboard won't throw this
}
}
}
}
// ====================================================================
// Entities
// ====================================================================
ListTag entityList = getTag(schematic, "Entities", ListTag.class);
if (entityList != null) {
List<Tag> entityTags = entityList.getValue();
for (Tag tag : entityTags) {
if (tag instanceof CompoundTag) {
CompoundTag compound = (CompoundTag) tag;
if (fixer != null) {
// FAWE start - BinaryTag
compound = (CompoundTag) AdventureNBTConverter.fromAdventure(fixer.fixUp(DataFixer.FixTypes.ENTITY, compound.asBinaryTag(), -1));
// FAWE end
}
String id = convertEntityId(compound.getString("id"));
Location location = NBTConversions.toLocation(clipboard, compound.getListTag("Pos"), compound.getListTag("Rotation"));
if (!id.isEmpty()) {
EntityType entityType = EntityTypes.get(id.toLowerCase(Locale.ROOT));
if (entityType != null) {
for (EntityNBTCompatibilityHandler compatibilityHandler : ENTITY_COMPATIBILITY_HANDLERS) {
if (compatibilityHandler.isAffectedEntity(entityType, compound)) {
compound = compatibilityHandler.updateNBT(entityType, compound);
}
}
BaseEntity state = new BaseEntity(entityType, compound);
clipboard.createEntity(location, state);
} else {
LOGGER.warn("Unknown entity when pasting schematic: " + id.toLowerCase(Locale.ROOT));
}
}
}
}
}
return clipboard;
}
use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.
the class SpongeSchematicWriter method write2.
/**
* Writes a version 2 schematic file.
*
* @param clipboard The clipboard
* @return The schematic map
*/
private Map<String, Tag> write2(Clipboard clipboard) {
Region region = clipboard.getRegion();
BlockVector3 origin = clipboard.getOrigin();
BlockVector3 min = region.getMinimumPoint();
BlockVector3 offset = min.subtract(origin);
int width = region.getWidth();
int height = region.getHeight();
int length = region.getLength();
if (width > MAX_SIZE) {
throw new IllegalArgumentException("Width of region too large for a .schematic");
}
if (height > MAX_SIZE) {
throw new IllegalArgumentException("Height of region too large for a .schematic");
}
if (length > MAX_SIZE) {
throw new IllegalArgumentException("Length of region too large for a .schematic");
}
Map<String, Tag> schematic = new HashMap<>();
schematic.put("Version", new IntTag(CURRENT_VERSION));
schematic.put("DataVersion", new IntTag(WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataVersion()));
Map<String, Tag> metadata = new HashMap<>();
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
metadata.put("FAWEVersion", new IntTag(Fawe.instance().getVersion().build));
schematic.put("Metadata", new CompoundTag(metadata));
schematic.put("Width", new ShortTag((short) width));
schematic.put("Height", new ShortTag((short) height));
schematic.put("Length", new ShortTag((short) length));
// The Sponge format Offset refers to the 'min' points location in the world. That's our 'Origin'
schematic.put("Offset", new IntArrayTag(new int[] { min.getBlockX(), min.getBlockY(), min.getBlockZ() }));
int paletteMax = 0;
Map<String, Integer> palette = new HashMap<>();
List<CompoundTag> tileEntities = new ArrayList<>();
ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * height * length);
for (int y = 0; y < height; y++) {
int y0 = min.getBlockY() + y;
for (int z = 0; z < length; z++) {
int z0 = min.getBlockZ() + z;
for (int x = 0; x < width; x++) {
int x0 = min.getBlockX() + x;
BlockVector3 point = BlockVector3.at(x0, y0, z0);
BaseBlock block = clipboard.getFullBlock(point);
if (block.getNbtData() != null) {
Map<String, Tag> values = new HashMap<>(block.getNbtData().getValue());
// Remove 'id' if it exists. We want 'Id'
values.remove("id");
// Positions are kept in NBT, we don't want that.
values.remove("x");
values.remove("y");
values.remove("z");
values.put("Id", new StringTag(block.getNbtId()));
values.put("Pos", new IntArrayTag(new int[] { x, y, z }));
tileEntities.add(new CompoundTag(values));
}
String blockKey = block.toImmutableState().getAsString();
int blockId;
if (palette.containsKey(blockKey)) {
blockId = palette.get(blockKey);
} else {
blockId = paletteMax;
palette.put(blockKey, blockId);
paletteMax++;
}
while ((blockId & -128) != 0) {
buffer.write(blockId & 127 | 128);
blockId >>>= 7;
}
buffer.write(blockId);
}
}
}
schematic.put("PaletteMax", new IntTag(paletteMax));
Map<String, Tag> paletteTag = new HashMap<>();
palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value)));
schematic.put("Palette", new CompoundTag(paletteTag));
schematic.put("BlockData", new ByteArrayTag(buffer.toByteArray()));
schematic.put("BlockEntities", new ListTag(CompoundTag.class, tileEntities));
// version 2 stuff
if (clipboard.hasBiomes()) {
writeBiomes(clipboard, schematic);
}
if (!clipboard.getEntities().isEmpty()) {
writeEntities(clipboard, schematic);
}
return schematic;
}
use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.
the class ExtentBlockCopy method apply.
@Override
public boolean apply(BlockVector3 position) throws WorldEditException {
BaseBlock block = source.getFullBlock(position);
BlockVector3 orig = position.subtract(from);
BlockVector3 transformed = transform.apply(orig.toVector3()).toBlockPoint();
// Apply transformations to NBT data if necessary
block = transformNbtData(block);
return destination.setBlock(transformed.add(to), block);
}
use of com.sk89q.worldedit.world.block.BaseBlock in project FastAsyncWorldEdit by IntellectualSites.
the class MultiStageReorder method setBlock.
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
if (!enabled) {
return setDelegateBlock(location, block);
}
BlockState existing = getExtent().getBlock(location);
PlacementPriority priority = getPlacementPriority(block);
PlacementPriority srcPriority = getPlacementPriority(existing);
if (srcPriority != PlacementPriority.FIRST) {
BaseBlock replacement = (block.getBlockType().getMaterial().isAir() ? block : BlockTypes.AIR.getDefaultState()).toBaseBlock();
switch(srcPriority) {
case FINAL:
stages.get(PlacementPriority.CLEAR_FINAL).put(location, replacement);
break;
case LATE:
stages.get(PlacementPriority.CLEAR_LATE).put(location, replacement);
break;
case LAST:
stages.get(PlacementPriority.CLEAR_LAST).put(location, replacement);
break;
default:
break;
}
if (block.getBlockType().getMaterial().isAir()) {
return !existing.equalsFuzzy(block);
}
}
stages.get(priority).put(location, block.toBaseBlock());
return !existing.equalsFuzzy(block);
}
use of com.sk89q.worldedit.world.block.BaseBlock in project WorldGuard by EngineHub.
the class SpongeUtil method clearSpongeWater.
/**
* Remove water around a sponge.
*
* @param world The world the sponge is in
* @param ox The x coordinate of the 'sponge' block
* @param oy The y coordinate of the 'sponge' block
* @param oz The z coordinate of the 'sponge' block
*/
public static void clearSpongeWater(World world, int ox, int oy, int oz) {
WorldConfiguration wcfg = WorldGuard.getInstance().getPlatform().getGlobalStateManager().get(world);
for (int cx = -wcfg.spongeRadius; cx <= wcfg.spongeRadius; cx++) {
for (int cy = -wcfg.spongeRadius; cy <= wcfg.spongeRadius; cy++) {
for (int cz = -wcfg.spongeRadius; cz <= wcfg.spongeRadius; cz++) {
BlockVector3 vector = BlockVector3.at(ox + cx, oy + cy, oz + cz);
BaseBlock block = world.getFullBlock(vector);
BlockType blockType = block.getBlockType();
if (isReplacable(blockType)) {
try {
world.setBlock(vector, BlockTypes.AIR.getDefaultState());
} catch (WorldEditException e) {
e.printStackTrace();
}
} else {
@SuppressWarnings("unchecked") Property<Object> waterloggedProp = waterloggable.computeIfAbsent(blockType, (bt -> (Property<Object>) bt.getPropertyMap().get("waterlogged")));
if (waterloggedProp != null) {
try {
world.setBlock(vector, block.with(waterloggedProp, false));
} catch (WorldEditException e) {
e.printStackTrace();
}
}
}
}
}
}
}
Aggregations