Search in sources :

Example 6 with Point3i

use of javax.vecmath.Point3i in project WorldPainter by Captain-Chaos.

the class WPObjectExporter method renderObject.

/**
 * Export an object to the world, optionally taking into account the blocks
 * that are already there.
 *
 * @param world The Minecraft world to which to export the object.
 * @param dimension The dimension corresponding to the exported world, used
 *     to determine the terrain height.
 * @param object The object to export.
 * @param x The X coordinate at which to export the object.
 * @param y The Y coordinate at which to export the object.
 * @param z The Z coordinate at which to export the object.
 * @param obliterate When <code>true</code>, all blocks of the object are
 *     placed regardless of what is already there. When <code>false</code>,
 *     rules are followed and some or all blocks may not be placed,
 *     depending on what is already there.
 */
public static void renderObject(MinecraftWorld world, Dimension dimension, WPObject object, int x, int y, int z, boolean obliterate) {
    final Point3i dim = object.getDimensions();
    final Point3i offset = object.getOffset();
    final int undergroundMode = object.getAttribute(ATTRIBUTE_UNDERGROUND_MODE);
    final int leafDecayMode = object.getAttribute(ATTRIBUTE_LEAF_DECAY_MODE);
    final boolean bottomless = dimension.isBottomless();
    final int[] replaceBlockIds = object.getAttribute(ATTRIBUTE_REPLACE_WITH_AIR);
    final boolean replaceBlocks = replaceBlockIds != null;
    final boolean extendFoundation = object.getAttribute(ATTRIBUTE_EXTEND_FOUNDATION);
    if ((z + offset.z + dim.z - 1) >= world.getMaxHeight()) {
        // Object doesn't fit in the world vertically
        return;
    }
    // System.out.println("Object dimensions: " + dim + ", origin: " + orig);
    for (int dx = 0; dx < dim.x; dx++) {
        for (int dy = 0; dy < dim.y; dy++) {
            final int worldX = x + dx + offset.x;
            final int worldY = y + dy + offset.y;
            final int terrainHeight = dimension.getIntHeightAt(worldX, worldY);
            for (int dz = 0; dz < dim.z; dz++) {
                if (object.getMask(dx, dy, dz)) {
                    final Material objectMaterial = object.getMaterial(dx, dy, dz);
                    final Material finalMaterial = (replaceBlocks && (objectMaterial.blockType == replaceBlockIds[0]) && (objectMaterial.data == replaceBlockIds[1])) ? Material.AIR : objectMaterial;
                    final int worldZ = z + dz + offset.z;
                    if ((bottomless || obliterate) ? (worldZ < 0) : (worldZ < 1)) {
                        continue;
                    } else if (obliterate) {
                        placeBlock(world, worldX, worldY, worldZ, finalMaterial, leafDecayMode);
                    } else {
                        final int existingBlockType = world.getBlockTypeAt(worldX, worldY, worldZ);
                        if (worldZ <= terrainHeight) {
                            switch(undergroundMode) {
                                case COLLISION_MODE_ALL:
                                    // Replace every block
                                    placeBlock(world, worldX, worldY, worldZ, finalMaterial, leafDecayMode);
                                    break;
                                case COLLISION_MODE_SOLID:
                                    // Only replace if object block is solid
                                    if (!objectMaterial.block.veryInsubstantial) {
                                        placeBlock(world, worldX, worldY, worldZ, finalMaterial, leafDecayMode);
                                    }
                                    break;
                                case COLLISION_MODE_NONE:
                                    // Only replace less solid blocks
                                    if (BLOCKS[existingBlockType].veryInsubstantial) {
                                        placeBlock(world, worldX, worldY, worldZ, finalMaterial, leafDecayMode);
                                    }
                                    break;
                            }
                        } else {
                            // Above ground only replace less solid blocks
                            if (BLOCKS[existingBlockType].veryInsubstantial) {
                                placeBlock(world, worldX, worldY, worldZ, finalMaterial, leafDecayMode);
                            }
                        }
                    }
                    if (extendFoundation && (dz == 0) && (terrainHeight != -1) && (worldZ > terrainHeight) && (!finalMaterial.block.veryInsubstantial)) {
                        int legZ = worldZ - 1;
                        while ((legZ >= 0) && world.getMaterialAt(worldX, worldY, legZ).block.veryInsubstantial) {
                            placeBlock(world, worldX, worldY, legZ, finalMaterial, leafDecayMode);
                            legZ--;
                        }
                    }
                }
            }
        }
    }
    List<Entity> entities = object.getEntities();
    if (entities != null) {
        for (Entity entity : entities) {
            double[] pos = entity.getPos();
            double entityX = x + pos[0] + offset.x, entityY = y + pos[2] + offset.y, entityZ = z + pos[1] + offset.z;
            if ((entityZ < 0) || (entityY > (world.getMaxHeight() - 1))) {
                if (logger.isTraceEnabled()) {
                    logger.trace("NOT adding entity " + entity.getId() + " @ " + entityX + "," + entityY + "," + entityZ + " because z coordinate is out of range!");
                }
            } else {
                if (logger.isTraceEnabled()) {
                    logger.trace("Adding entity " + entity.getId() + " @ " + entityX + "," + entityY + "," + entityZ);
                }
                // Make sure each entity has a unique ID, otherwise
                // Minecraft will see them all as duplicates and remove
                // them:
                entity.setUUID(UUID.randomUUID());
                world.addEntity(entityX, entityY, entityZ, entity);
            }
        }
    }
    List<TileEntity> tileEntities = object.getTileEntities();
    if (tileEntities != null) {
        for (TileEntity tileEntity : tileEntities) {
            final int tileEntityX = x + tileEntity.getX() + offset.x, tileEntityY = y + tileEntity.getZ() + offset.y, tileEntityZ = z + tileEntity.getY() + offset.z;
            final String entityId = tileEntity.getId();
            if ((tileEntityZ < 0) || (tileEntityZ >= world.getMaxHeight())) {
                if (logger.isTraceEnabled()) {
                    logger.trace("NOT adding tile entity " + entityId + " @ " + tileEntityX + "," + tileEntityY + "," + tileEntityZ + " because z coordinate is out of range!");
                }
            } else {
                final int existingBlockType = world.getBlockTypeAt(tileEntityX, tileEntityY, tileEntityZ);
                if (!TILE_ENTITY_MAP.containsKey(entityId)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Adding unknown tile entity " + entityId + " @ " + tileEntityX + "," + tileEntityY + "," + tileEntityZ + " (block type: " + BLOCK_TYPE_NAMES[existingBlockType] + "; not able to detect whether the block type is correct; map may cause errors!)");
                    }
                    world.addTileEntity(tileEntityX, tileEntityY, tileEntityZ, tileEntity);
                } else if (TILE_ENTITY_MAP.get(entityId).contains(existingBlockType)) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Adding tile entity " + entityId + " @ " + tileEntityX + "," + tileEntityY + "," + tileEntityZ + " (block type: " + BLOCK_TYPE_NAMES[existingBlockType] + ")");
                    }
                    world.addTileEntity(tileEntityX, tileEntityY, tileEntityZ, tileEntity);
                } else {
                    // the world limits)
                    if (logger.isTraceEnabled()) {
                        logger.trace("NOT adding tile entity " + entityId + " @ " + tileEntityX + "," + tileEntityY + "," + tileEntityZ + " because the block there is not a (or not the same) tile entity: " + BLOCK_TYPE_NAMES[existingBlockType] + "!");
                    }
                }
            }
        }
    }
}
Also used : TileEntity(org.pepsoft.minecraft.TileEntity) Point3i(javax.vecmath.Point3i) Entity(org.pepsoft.minecraft.Entity) TileEntity(org.pepsoft.minecraft.TileEntity) Material(org.pepsoft.minecraft.Material)

Example 7 with Point3i

use of javax.vecmath.Point3i in project WorldPainter by Captain-Chaos.

the class Bo2Object method load.

/**
 * Load a custom object in bo2 format from an input stream. The stream is
 * closed before exiting this method.
 *
 * @param objectName The name of the object.
 * @param stream The input stream from which to load the object.
 * @return A new <code>Bo2Object</code> containing the contents of the
 *     specified stream.
 * @throws IOException If an I/O error occurred while reading the stream.
 */
public static Bo2Object load(String objectName, InputStream stream) throws IOException {
    try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, Charset.forName("US-ASCII")))) {
        Map<String, String> properties = new HashMap<>();
        Map<Point3i, Bo2BlockSpec> blocks = new HashMap<>();
        boolean readingMetaData = false, readingData = false;
        String line;
        int lowestX = Integer.MAX_VALUE, highestX = Integer.MIN_VALUE;
        int lowestY = Integer.MAX_VALUE, highestY = Integer.MIN_VALUE;
        int lowestZ = Integer.MAX_VALUE, highestZ = Integer.MIN_VALUE;
        while ((line = in.readLine()) != null) {
            if (line.trim().length() == 0) {
                continue;
            }
            if (readingMetaData) {
                if (line.equals("[DATA]")) {
                    readingMetaData = false;
                    readingData = true;
                } else {
                    int p = line.indexOf('=');
                    String name = line.substring(0, p).trim();
                    String value = line.substring(p + 1).trim();
                    properties.put(name, value);
                }
            } else if (readingData) {
                int p = line.indexOf(':');
                String coordinates = line.substring(0, p);
                String spec = line.substring(p + 1);
                p = coordinates.indexOf(',');
                int x = Integer.parseInt(coordinates.substring(0, p));
                int p2 = coordinates.indexOf(',', p + 1);
                int y = Integer.parseInt(coordinates.substring(p + 1, p2));
                int z = Integer.parseInt(coordinates.substring(p2 + 1));
                if (x < lowestX) {
                    lowestX = x;
                }
                if (x > highestX) {
                    highestX = x;
                }
                if (y < lowestY) {
                    lowestY = y;
                }
                if (y > highestY) {
                    highestY = y;
                }
                if (z < lowestZ) {
                    lowestZ = z;
                }
                if (z > highestZ) {
                    highestZ = z;
                }
                p = spec.indexOf('.');
                int blockId, data = 0;
                int[] branch = null;
                if (p == -1) {
                    blockId = Integer.parseInt(spec);
                } else {
                    blockId = Integer.parseInt(spec.substring(0, p));
                    p2 = spec.indexOf('#', p + 1);
                    if (p2 == -1) {
                        data = Integer.parseInt(spec.substring(p + 1));
                    } else {
                        data = Integer.parseInt(spec.substring(p + 1, p2));
                        p = spec.indexOf('@', p2 + 1);
                        branch = new int[] { Integer.parseInt(spec.substring(p2 + 1, p)), Integer.parseInt(spec.substring(p + 1)) };
                    }
                }
                Point3i coords = new Point3i(x, y, z);
                blocks.put(coords, new Bo2BlockSpec(coords, Material.get(blockId, data), branch));
            } else {
                if (line.equals("[META]")) {
                    readingMetaData = true;
                }
            }
        }
        if (blocks.isEmpty()) {
            throw new IOException("No blocks found in the file; is this a bo2 object?");
        }
        return new Bo2Object(objectName, properties, blocks, new Point3i(-lowestX, -lowestY, -lowestZ), new Point3i(highestX - lowestX + 1, highestY - lowestY + 1, highestZ - lowestZ + 1), null);
    }
}
Also used : Point3i(javax.vecmath.Point3i) HashMap(java.util.HashMap)

Example 8 with Point3i

use of javax.vecmath.Point3i in project WorldPainter by Captain-Chaos.

the class Bo3Object method load.

/**
 * Load a custom object in bo3 format from a file.
 *
 * @param objectName The name of the object.
 * @param file The file from which to load the object.
 * @return A new <code>Bo3Object</code> containing the contents of the
 *     specified file.
 * @throws IOException If an I/O error occurred while reading the file.
 */
public static Bo3Object load(String objectName, File file) throws IOException {
    try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("US-ASCII")))) {
        Map<String, String> properties = new HashMap<>();
        Map<Point3i, Bo3BlockSpec> blocks = new HashMap<>();
        String line;
        int lowestX = Integer.MAX_VALUE, highestX = Integer.MIN_VALUE;
        int lowestY = Integer.MAX_VALUE, highestY = Integer.MIN_VALUE;
        int lowestZ = Integer.MAX_VALUE, highestZ = Integer.MIN_VALUE;
        while ((line = in.readLine()) != null) {
            line = line.trim();
            if (line.isEmpty() || line.startsWith("#")) {
                continue;
            } else if (line.startsWith("Block")) {
                // Block spec
                Deque<String> args = getArgs(line);
                int x = Integer.parseInt(args.pop());
                int z = Integer.parseInt(args.pop());
                int y = Integer.parseInt(args.pop());
                if (x < lowestX) {
                    lowestX = x;
                }
                if (x > highestX) {
                    highestX = x;
                }
                if (y < lowestY) {
                    lowestY = y;
                }
                if (y > highestY) {
                    highestY = y;
                }
                if (z < lowestZ) {
                    lowestZ = z;
                }
                if (z > highestZ) {
                    highestZ = z;
                }
                Material material = decodeMaterial(args.pop());
                TileEntity tileEntity = null;
                if (!args.isEmpty()) {
                    tileEntity = loadTileEntity(file, args.pop());
                }
                Point3i coords = new Point3i(x, y, z);
                blocks.put(coords, new Bo3BlockSpec(coords, material, tileEntity));
            } else if (line.startsWith("RandomBlock")) {
                // Random block spec
                Deque<String> args = getArgs(line);
                int x = Integer.parseInt(args.pop());
                int z = Integer.parseInt(args.pop());
                int y = Integer.parseInt(args.pop());
                if (x < lowestX) {
                    lowestX = x;
                }
                if (x > highestX) {
                    highestX = x;
                }
                if (y < lowestY) {
                    lowestY = y;
                }
                if (y > highestY) {
                    highestY = y;
                }
                if (z < lowestZ) {
                    lowestZ = z;
                }
                if (z > highestZ) {
                    highestZ = z;
                }
                List<Bo3BlockSpec.RandomBlock> randomBlocks = new ArrayList<>();
                do {
                    Material material = decodeMaterial(args.pop());
                    String nbtOrChance = args.pop();
                    TileEntity tileEntity = null;
                    int chance;
                    try {
                        chance = Integer.parseInt(nbtOrChance);
                    } catch (NumberFormatException e) {
                        tileEntity = loadTileEntity(file, nbtOrChance);
                        chance = Integer.parseInt(args.pop());
                    }
                    randomBlocks.add(new Bo3BlockSpec.RandomBlock(material, tileEntity, chance));
                } while (!args.isEmpty());
                Point3i coords = new Point3i(x, y, z);
                blocks.put(coords, new Bo3BlockSpec(coords, randomBlocks.toArray(new Bo3BlockSpec.RandomBlock[randomBlocks.size()])));
            } else if (line.startsWith("BlockCheck") || line.startsWith("LightCheck") || line.startsWith("Branch") || line.startsWith("WeightedBranch")) {
                logger.warn("Ignoring unsupported bo3 feature " + line);
            } else {
                int p = line.indexOf(':');
                if (p != -1) {
                    properties.put(line.substring(0, p).trim(), line.substring(p + 1).trim());
                } else {
                    logger.warn("Ignoring unrecognised line: " + line);
                }
            }
        }
        if (blocks.isEmpty()) {
            throw new IOException("No blocks found in the file; is this a bo3 object?");
        }
        Map<String, Serializable> attributes = new HashMap<>(Collections.singletonMap(ATTRIBUTE_FILE.key, file));
        return new Bo3Object(objectName, properties, blocks, new Point3i(-lowestX, -lowestY, -lowestZ), new Point3i(highestX - lowestX + 1, highestY - lowestY + 1, highestZ - lowestZ + 1), attributes);
    }
}
Also used : DefaultMaterial(com.khorn.terraincontrol.util.minecraftTypes.DefaultMaterial) Material(org.pepsoft.minecraft.Material) TileEntity(org.pepsoft.minecraft.TileEntity) Point3i(javax.vecmath.Point3i)

Example 9 with Point3i

use of javax.vecmath.Point3i in project WorldPainter by Captain-Chaos.

the class Structure method load.

public static Structure load(String objectName, InputStream inputStream, MCInterface mcInterface) throws IOException {
    CompoundTag root;
    try (NBTInputStream in = new NBTInputStream(new GZIPInputStream(new BufferedInputStream(inputStream)))) {
        root = (CompoundTag) in.readTag();
    }
    // Load the palette
    ListTag paletteTag = (ListTag) root.getTag("palette");
    Material[] palette = new Material[paletteTag.getValue().size()];
    for (int i = 0; i < palette.length; i++) {
        palette[i] = mcInterface.decodeStructureMaterial((CompoundTag) paletteTag.getValue().get(i));
    }
    // Load the blocks
    Map<Point3i, Material> blocks = new HashMap<>();
    ListTag blocksTag = (ListTag) root.getTag("blocks");
    for (Tag tag : blocksTag.getValue()) {
        CompoundTag blockTag = (CompoundTag) tag;
        List<Tag> posTags = ((ListTag) blockTag.getTag("pos")).getValue();
        blocks.put(new Point3i(((IntTag) posTags.get(0)).getValue(), ((IntTag) posTags.get(2)).getValue(), ((IntTag) posTags.get(1)).getValue()), palette[((IntTag) blockTag.getTag("state")).getValue()]);
    }
    // Remove palette and blocks from the tag so we don't waste space
    root.setTag("palette", null);
    root.setTag("blocks", null);
    return new Structure(root, objectName, blocks);
}
Also used : HashMap(java.util.HashMap) Material(org.pepsoft.minecraft.Material) GZIPInputStream(java.util.zip.GZIPInputStream) Point3i(javax.vecmath.Point3i)

Example 10 with Point3i

use of javax.vecmath.Point3i in project WorldPainter by Captain-Chaos.

the class Bo2LayerExporter method fitsInExportedArea.

/**
 * Determines whether an object fits completely into the area currently
 * being rendere in the horizontal dimensions.
 *
 * @return <code>true</code> if the object fits.
 */
private boolean fitsInExportedArea(final Rectangle exportedArea, final WPObject object, final int x, final int y) {
    final Point3i dimensions = object.getDimensions();
    final Point3i offset = object.getOffset();
    // This is to avoid objects getting cut off at area boundaries
    return !((x + offset.x < exportedArea.x) || (x + offset.x + dimensions.x > exportedArea.x + exportedArea.width) || (y + offset.y < exportedArea.y) || (y + offset.y + dimensions.y > exportedArea.y + exportedArea.height));
}
Also used : Point3i(javax.vecmath.Point3i)

Aggregations

Point3i (javax.vecmath.Point3i)22 Material (org.pepsoft.minecraft.Material)3 Box (org.pepsoft.util.Box)3 WPObject (org.pepsoft.worldpainter.objects.WPObject)3 HashMap (java.util.HashMap)2 TileEntity (org.pepsoft.minecraft.TileEntity)2 DefaultMaterial (com.khorn.terraincontrol.util.minecraftTypes.DefaultMaterial)1 Graphics2D (java.awt.Graphics2D)1 BufferedImage (java.awt.image.BufferedImage)1 File (java.io.File)1 IOException (java.io.IOException)1 Serializable (java.io.Serializable)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Random (java.util.Random)1 GZIPInputStream (java.util.zip.GZIPInputStream)1 NBTOutputStream (org.jnbt.NBTOutputStream)1 Block (org.pepsoft.minecraft.Block)1 Chunk (org.pepsoft.minecraft.Chunk)1 Entity (org.pepsoft.minecraft.Entity)1