Search in sources :

Example 1 with MinecraftWorldObject

use of org.pepsoft.worldpainter.objects.MinecraftWorldObject in project WorldPainter by Captain-Chaos.

the class JavaPostProcessor method postProcess.

/**
 * Post process (part of) a {@link MinecraftWorld} to make sure it conforms
 * to Minecraft's rules. For instance:
 *
 * <ul><li>Remove plants that are on the wrong underground or floating
 * in air.
 * <li>Change the lowest block of a column of Sand to Sandstone.
 * <li>Remove snow on top of blocks which don't support snow, or floating in
 * air.
 * <li>Change covered grass and mycelium blocks to dirt.
 * </ul>
 *
 * @param minecraftWorld The <code>MinecraftWorld</code> to post process.
 * @param volume The three dimensional area of the world to post process.
 * @param progressReceiver The optional progress receiver to which to report
 *                         progress. May be <code>null</code>.
 * @throws ProgressReceiver.OperationCancelled If the progress receiver
 * threw an <code>OperationCancelled</code> exception.
 */
@Override
public void postProcess(MinecraftWorld minecraftWorld, Box volume, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled {
    if (!enabled) {
        return;
    }
    if (progressReceiver != null) {
        progressReceiver.setMessage("Enforcing Minecraft rules on exported blocks");
    }
    final int worldMaxZ = minecraftWorld.getMaxHeight() - 1;
    final int x1, y1, x2, y2, minZ, maxZ;
    // TODO: make these configurable:
    final FloatMode sandMode = "false".equalsIgnoreCase(System.getProperty("org.pepsoft.worldpainter.supportSand")) ? FloatMode.LEAVE_FLOATING : FloatMode.SUPPORT;
    final FloatMode gravelMode = FloatMode.LEAVE_FLOATING;
    final FloatMode cementMode = FloatMode.LEAVE_FLOATING;
    if (minecraftWorld instanceof MinecraftWorldObject) {
        // Special support for MinecraftWorldObjects to constrain the area
        // further
        Box objectVolume = ((MinecraftWorldObject) minecraftWorld).getVolume();
        objectVolume.intersect(volume);
        if (objectVolume.isEmpty()) {
            // do
            return;
        } else {
            x1 = objectVolume.getX1();
            x2 = objectVolume.getX2() - 1;
            y1 = objectVolume.getY1();
            y2 = objectVolume.getY2() - 1;
            minZ = objectVolume.getZ1();
            maxZ = objectVolume.getZ2() - 1;
        }
    } else {
        x1 = volume.getX1();
        y1 = volume.getY1();
        x2 = volume.getX2() - 1;
        y2 = volume.getY2() - 1;
        minZ = volume.getZ1();
        maxZ = volume.getZ2() - 1;
    }
    final boolean traceEnabled = logger.isTraceEnabled();
    for (int x = x1; x <= x2; x++) {
        for (int y = y1; y <= y2; y++) {
            int blockTypeBelow = BLK_AIR;
            int blockTypeAbove = minecraftWorld.getBlockTypeAt(x, y, minZ);
            // }
            for (int z = minZ; z <= maxZ; z++) {
                int blockType = blockTypeAbove;
                blockTypeAbove = (z < worldMaxZ) ? minecraftWorld.getBlockTypeAt(x, y, z + 1) : BLK_AIR;
                if (((blockTypeBelow == BLK_GRASS) || (blockTypeBelow == BLK_MYCELIUM) || (blockTypeBelow == BLK_TILLED_DIRT)) && ((blockType == BLK_WATER) || (blockType == BLK_STATIONARY_WATER) || (blockType == BLK_ICE) || ((blockType <= HIGHEST_KNOWN_BLOCK_ID) && (BLOCK_TRANSPARENCY[blockType] == 15)))) {
                    // Covered grass, mycelium or tilled earth block, should
                    // be dirt. Note that unknown blocks are treated as
                    // transparent for this check so that grass underneath
                    // custom plants doesn't turn to dirt, for instance
                    minecraftWorld.setMaterialAt(x, y, z - 1, Material.DIRT);
                    blockTypeBelow = BLK_DIRT;
                }
                switch(blockType) {
                    case BLK_SAND:
                        if (BLOCKS[blockTypeBelow].veryInsubstantial) {
                            switch(sandMode) {
                                case DROP:
                                    dropBlock(minecraftWorld, x, y, z);
                                    blockType = BLK_AIR;
                                    break;
                                case SUPPORT:
                                    // All unsupported sand should be supported by sandstone
                                    minecraftWorld.setMaterialAt(x, y, z, (minecraftWorld.getDataAt(x, y, z) == 1) ? Material.RED_SANDSTONE : Material.SANDSTONE);
                                    blockType = minecraftWorld.getBlockTypeAt(x, y, z);
                                    break;
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case BLK_GRAVEL:
                        if (BLOCKS[blockTypeBelow].veryInsubstantial) {
                            switch(gravelMode) {
                                case DROP:
                                    dropBlock(minecraftWorld, x, y, z);
                                    blockType = BLK_AIR;
                                    break;
                                case SUPPORT:
                                    // All unsupported gravel should be supported by stone
                                    minecraftWorld.setMaterialAt(x, y, z, Material.STONE);
                                    blockType = BLK_STONE;
                                    break;
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case BLK_CEMENT:
                        if (BLOCKS[blockTypeBelow].veryInsubstantial) {
                            switch(cementMode) {
                                case DROP:
                                    dropBlock(minecraftWorld, x, y, z);
                                    blockType = BLK_AIR;
                                    break;
                                case SUPPORT:
                                    throw new UnsupportedOperationException("Don't know how to support cement yet");
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case BLK_DEAD_SHRUBS:
                        if ((blockTypeBelow != BLK_SAND) && (blockTypeBelow != BLK_DIRT) && (blockTypeBelow != BLK_STAINED_CLAY) && (blockTypeBelow != BLK_HARDENED_CLAY)) {
                            // Dead shrubs can only exist on Sand
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_TALL_GRASS:
                    case BLK_ROSE:
                    case BLK_DANDELION:
                        if ((blockTypeBelow != BLK_GRASS) && (blockTypeBelow != BLK_DIRT)) {
                            // Tall grass and flowers can only exist on Grass or Dirt blocks
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_RED_MUSHROOM:
                    case BLK_BROWN_MUSHROOM:
                        if ((blockTypeBelow != BLK_GRASS) && (blockTypeBelow != BLK_DIRT) && (blockTypeBelow != BLK_MYCELIUM) && (blockTypeBelow != BLK_STONE)) {
                            // Mushrooms can only exist on Grass, Dirt, Mycelium or Stone (in caves) blocks
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_SNOW:
                        if ((blockTypeBelow == BLK_ICE) || (blockTypeBelow == BLK_SNOW) || (blockTypeBelow == BLK_AIR) || (blockTypeBelow == BLK_PACKED_ICE)) {
                            // Snow can't be on ice, or another snow block, or air
                            // (well it could be, but it makes no sense, would
                            // disappear when touched, and it makes this algorithm
                            // remove stacks of snow blocks correctly)
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_WHEAT:
                        if (blockTypeBelow != BLK_TILLED_DIRT) {
                            // Wheat can only exist on Tilled Dirt blocks
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_LARGE_FLOWERS:
                        int data = minecraftWorld.getDataAt(x, y, z);
                        if ((data & 0x8) == 0x8) {
                            // in the previous iteration
                            if (blockTypeBelow != BLK_LARGE_FLOWERS) {
                                // replace this block with air
                                if (traceEnabled) {
                                    logger.trace("Block @ " + x + "," + z + "," + y + " is upper large flower block; block below is " + BLOCK_TYPE_NAMES[blockTypeBelow] + "; removing block");
                                }
                                minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                                blockType = BLK_AIR;
                            }
                        } else {
                            // there's a top half above and grass or dirt below
                            if (blockTypeAbove == BLK_LARGE_FLOWERS) {
                                if ((minecraftWorld.getDataAt(x, y, z + 1) & 0x8) == 0) {
                                    // this block with air
                                    if (traceEnabled) {
                                        logger.trace("Block @ " + x + "," + z + "," + y + " is lower large flower block; block above is another lower large flower block; removing block");
                                    }
                                    minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                                    blockType = BLK_AIR;
                                } else if ((blockTypeBelow != BLK_GRASS) && (blockTypeBelow != BLK_DIRT)) {
                                    // check) only exist on grass or dirt
                                    if (traceEnabled) {
                                        logger.trace("Block @ " + x + "," + z + "," + y + " is lower large flower block; block above is " + BLOCK_TYPE_NAMES[blockTypeBelow] + "; removing block");
                                    }
                                    minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                                    blockType = BLK_AIR;
                                }
                            } else {
                                // replace this block with air
                                if (traceEnabled) {
                                    logger.trace("Block @ " + x + "," + z + "," + y + " is lower large flower block; block above is " + BLOCK_TYPE_NAMES[blockTypeBelow] + "; removing block");
                                }
                                minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                                blockType = BLK_AIR;
                            }
                        }
                        break;
                    case BLK_CACTUS:
                        if ((blockTypeBelow != BLK_SAND) && (blockTypeBelow != BLK_CACTUS)) {
                            // Cactus blocks can only be on top of sand or other cactus blocks
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_SUGAR_CANE:
                        if ((blockTypeBelow != BLK_GRASS) && (blockTypeBelow != BLK_DIRT) && (blockTypeBelow != BLK_SAND) && (blockTypeBelow != BLK_SUGAR_CANE)) {
                            // Sugar cane blocks can only be on top of grass, dirt, sand or other sugar cane blocks
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_NETHER_WART:
                        if (blockTypeBelow != BLK_SOUL_SAND) {
                            // Nether wart blocks can only be on top of soul sand
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_CHORUS_FLOWER:
                    case BLK_CHORUS_PLANT:
                        if ((blockTypeBelow != BLK_END_STONE) && (blockTypeBelow != BLK_CHORUS_PLANT)) {
                            // Chorus flower and plant blocks can only be on top of end stone or other chorus plant blocks
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                    case BLK_FIRE:
                        // the air
                        if ((blockTypeBelow == BLK_AIR) && (blockTypeAbove == BLK_AIR) && (minecraftWorld.getBlockTypeAt(x - 1, y, z) == BLK_AIR) && (minecraftWorld.getBlockTypeAt(x + 1, y, z) == BLK_AIR) && (minecraftWorld.getBlockTypeAt(x, y - 1, z) == BLK_AIR) && (minecraftWorld.getBlockTypeAt(x, y + 1, z) == BLK_AIR)) {
                            minecraftWorld.setMaterialAt(x, y, z, Material.AIR);
                            blockType = BLK_AIR;
                        }
                        break;
                }
                blockTypeBelow = blockType;
            }
        }
        if (progressReceiver != null) {
            progressReceiver.setProgress((float) (x - x1 + 1) / (x2 - x1 + 1));
        }
    }
}
Also used : MinecraftWorldObject(org.pepsoft.worldpainter.objects.MinecraftWorldObject) Box(org.pepsoft.util.Box)

Example 2 with MinecraftWorldObject

use of org.pepsoft.worldpainter.objects.MinecraftWorldObject in project WorldPainter by Captain-Chaos.

the class Java1_15PostProcessor method postProcess.

/**
 * Post process (part of) a {@link MinecraftWorld} to make sure it conforms
 * to Minecraft's rules. For instance:
 *
 * <ul><li>Remove plants that are on the wrong underground or floating
 * in air.
 * <li>Change the lowest block of a column of Sand to Sandstone.
 * <li>Remove snow on top of blocks which don't support snow, or floating in
 * air.
 * <li>Change covered grass and mycelium blocks to dirt.
 * </ul>
 *
 * @param minecraftWorld The {@code MinecraftWorld} to post process.
 * @param volume The three dimensional area of the world to post process.
 * @param progressReceiver The optional progress receiver to which to report
 *                         progress. May be {@code null}.
 * @throws ProgressReceiver.OperationCancelled If the progress receiver
 * threw an {@code OperationCancelled} exception.
 */
@Override
public void postProcess(MinecraftWorld minecraftWorld, Box volume, ProgressReceiver progressReceiver) throws ProgressReceiver.OperationCancelled {
    if (!enabled) {
        return;
    }
    if (progressReceiver != null) {
        progressReceiver.setMessage("Enforcing Minecraft rules on exported blocks");
    }
    final int worldMaxZ = minecraftWorld.getMaxHeight() - 1;
    final int x1, y1, x2, y2, minZ, maxZ;
    // TODO: make these configurable:
    final FloatMode sandMode = "false".equalsIgnoreCase(System.getProperty("org.pepsoft.worldpainter.supportSand")) ? FloatMode.LEAVE_FLOATING : FloatMode.SUPPORT;
    final FloatMode gravelMode = FloatMode.LEAVE_FLOATING;
    final FloatMode cementMode = FloatMode.LEAVE_FLOATING;
    final FloatMode waterMode = FloatMode.LEAVE_FLOATING;
    final FloatMode lavaMode = FloatMode.LEAVE_FLOATING;
    if (minecraftWorld instanceof MinecraftWorldObject) {
        // Special support for MinecraftWorldObjects to constrain the area
        // further
        Box objectVolume = ((MinecraftWorldObject) minecraftWorld).getVolume();
        objectVolume.intersect(volume);
        if (objectVolume.isEmpty()) {
            // do
            return;
        } else {
            x1 = objectVolume.getX1();
            x2 = objectVolume.getX2() - 1;
            y1 = objectVolume.getY1();
            y2 = objectVolume.getY2() - 1;
            minZ = objectVolume.getZ1();
            maxZ = objectVolume.getZ2() - 1;
        }
    } else {
        x1 = volume.getX1();
        y1 = volume.getY1();
        x2 = volume.getX2() - 1;
        y2 = volume.getY2() - 1;
        minZ = volume.getZ1();
        maxZ = volume.getZ2() - 1;
    }
    for (int x = x1; x <= x2; x++) {
        for (int y = y1; y <= y2; y++) {
            Material materialBelow = (minZ <= 0) ? AIR : minecraftWorld.getMaterialAt(x, y, minZ - 1);
            Material materialAbove = minecraftWorld.getMaterialAt(x, y, minZ);
            // }
            for (int z = minZ; z <= maxZ; z++) {
                Material material = materialAbove;
                materialAbove = (z < worldMaxZ) ? minecraftWorld.getMaterialAt(x, y, z + 1) : AIR;
                if (((materialBelow.isNamed(MC_GRASS_BLOCK)) || (materialBelow.isNamed(MC_MYCELIUM)) || (materialBelow.isNamed(MC_FARMLAND))) && (material.containsWater() || (material == ICE) || material.opaque)) {
                    // Covered grass, mycelium or tilled earth block, should
                    // be dirt
                    minecraftWorld.setMaterialAt(x, y, z - 1, DIRT);
                    materialBelow = DIRT;
                }
                if (materialBelow.hasPropertySnowy) {
                    // The material below has a "snowy" property, so make sure it is set correctly
                    if (material.isNamed(MC_SNOW) || material.isNamed(MC_SNOW_BLOCK)) {
                        // It should be snowy, change it if it isn't
                        if (!materialBelow.getProperty(SNOWY)) {
                            materialBelow = materialBelow.withProperty(SNOWY, true);
                            minecraftWorld.setMaterialAt(x, y, z - 1, materialBelow);
                        }
                    } else {
                        // It should NOT be snowy, change it if it is
                        if (materialBelow.getProperty(SNOWY)) {
                            materialBelow = materialBelow.withProperty(SNOWY, false);
                            minecraftWorld.setMaterialAt(x, y, z - 1, materialBelow);
                        }
                    }
                }
                // upper large flower blocks into modern ones
                if ((material.blockType == BLK_LARGE_FLOWERS) && ((material.data & 0x8) == 0x8) && (materialBelow.blockType == BLK_LARGE_FLOWERS)) {
                    material = materialBelow.withProperty(HALF, "upper");
                    minecraftWorld.setMaterialAt(x, y, z, material);
                }
                switch(material.name) {
                    case MC_SAND:
                    case MC_RED_SAND:
                        if (materialBelow.veryInsubstantial) {
                            switch(sandMode) {
                                case DROP:
                                    dropBlock(minecraftWorld, x, y, z);
                                    material = AIR;
                                    break;
                                case SUPPORT:
                                    // All unsupported sand should be supported by sandstone
                                    minecraftWorld.setMaterialAt(x, y, z, (material == RED_SAND) ? RED_SANDSTONE : SANDSTONE);
                                    material = minecraftWorld.getMaterialAt(x, y, z);
                                    break;
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case MC_GRAVEL:
                        if (materialBelow.veryInsubstantial) {
                            switch(gravelMode) {
                                case DROP:
                                    dropBlock(minecraftWorld, x, y, z);
                                    material = AIR;
                                    break;
                                case SUPPORT:
                                    // All unsupported gravel should be supported by stone
                                    minecraftWorld.setMaterialAt(x, y, z, STONE);
                                    material = STONE;
                                    break;
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case MC_WHITE_CONCRETE_POWDER:
                    case MC_ORANGE_CONCRETE_POWDER:
                    case MC_MAGENTA_CONCRETE_POWDER:
                    case MC_LIGHT_BLUE_CONCRETE_POWDER:
                    case MC_YELLOW_CONCRETE_POWDER:
                    case MC_LIME_CONCRETE_POWDER:
                    case MC_PINK_CONCRETE_POWDER:
                    case MC_GRAY_CONCRETE_POWDER:
                    case MC_LIGHT_GRAY_CONCRETE_POWDER:
                    case MC_CYAN_CONCRETE_POWDER:
                    case MC_PURPLE_CONCRETE_POWDER:
                    case MC_BLUE_CONCRETE_POWDER:
                    case MC_BROWN_CONCRETE_POWDER:
                    case MC_GREEN_CONCRETE_POWDER:
                    case MC_RED_CONCRETE_POWDER:
                    case MC_BLACK_CONCRETE_POWDER:
                        if (materialBelow.veryInsubstantial) {
                            switch(cementMode) {
                                case DROP:
                                    dropBlock(minecraftWorld, x, y, z);
                                    material = AIR;
                                    break;
                                case SUPPORT:
                                    throw new UnsupportedOperationException("Don't know how to support cement yet");
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case MC_WATER:
                        if (materialBelow.veryInsubstantial) {
                            switch(waterMode) {
                                case DROP:
                                    dropFluid(minecraftWorld, x, y, z);
                                    break;
                                case SUPPORT:
                                    throw new UnsupportedOperationException("Don't know how to support water yet");
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case MC_LAVA:
                        if (materialBelow.veryInsubstantial) {
                            switch(lavaMode) {
                                case DROP:
                                    dropFluid(minecraftWorld, x, y, z);
                                    break;
                                case SUPPORT:
                                    throw new UnsupportedOperationException("Don't know how to support lava yet");
                                default:
                                    // Do nothing
                                    break;
                            }
                        }
                        break;
                    case MC_DEAD_BUSH:
                        if ((materialBelow != SAND) && (materialBelow != RED_SAND) && (materialBelow != DIRT) && (materialBelow != PODZOL) && (materialBelow != PERMADIRT) && (!materialBelow.name.endsWith("_terracotta")) && (materialBelow != TERRACOTTA)) {
                            // Dead shrubs can only exist on materials
                            // present in Mesa biome
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_GRASS:
                    case MC_FERN:
                    case MC_DANDELION:
                    case MC_POPPY:
                    case MC_BLUE_ORCHID:
                    case MC_ALLIUM:
                    case MC_AZURE_BLUET:
                    case MC_RED_TULIP:
                    case MC_ORANGE_TULIP:
                    case MC_WHITE_TULIP:
                    case MC_PINK_TULIP:
                    case MC_OXEYE_DAISY:
                        if ((materialBelow != GRASS_BLOCK) && (materialBelow != DIRT) && (materialBelow != PODZOL) && (materialBelow != PERMADIRT)) {
                            // Tall grass and flowers can only exist on Grass or Dirt blocks
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_RED_MUSHROOM:
                    case MC_BROWN_MUSHROOM:
                        if ((materialBelow != GRASS_BLOCK) && (materialBelow != DIRT) && (materialBelow != PODZOL) && (materialBelow != PERMADIRT) && (materialBelow != MYCELIUM) && (materialBelow != STONE) && (materialBelow != GRANITE) && (materialBelow != DIORITE) && (materialBelow != ANDESITE)) {
                            // Mushrooms can only exist on Grass, Dirt, Mycelium or Stone (in caves) blocks
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_SNOW:
                        if ((materialBelow == ICE) || materialBelow.isNamed(MC_SNOW) || (materialBelow == AIR) || (materialBelow == PACKED_ICE)) {
                            // Snow can't be on ice, or another snow block, or air
                            // (well it could be, but it makes no sense, would
                            // disappear when touched, and it makes this algorithm
                            // remove stacks of snow blocks correctly)
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_WHEAT:
                        if (materialBelow.isNotNamed(MC_FARMLAND)) {
                            // Wheat can only exist on Tilled Dirt blocks
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_SUNFLOWER:
                    case MC_LILAC:
                    case MC_TALL_GRASS:
                    case MC_LARGE_FERN:
                    case MC_ROSE_BUSH:
                    case MC_PEONY:
                        // TODOMC13 recognise legacy "top half" block and replace it with the proper block
                        if (material.getProperty(HALF).equals("upper")) {
                            // Top half of double high plant.
                            if (materialBelow.isNotNamedSameAs(material) || (!materialBelow.getProperty(HALF).equals("lower"))) {
                                // There is not a corresponding lower half
                                // below; remove this block
                                minecraftWorld.setMaterialAt(x, y, z, AIR);
                                material = AIR;
                            }
                        } else {
                            // and grass or dirt below
                            if (materialAbove.isNamedSameAs(material) && materialAbove.getProperty(HALF).equals("upper")) {
                                if (materialBelow.isNotNamed(MC_GRASS_BLOCK) && (materialBelow != DIRT) && (materialBelow.isNotNamed(MC_PODZOL)) && (materialBelow != PERMADIRT)) {
                                    // Double high plants can (presumably; TODO:
                                    // check) only exist on grass or dirt
                                    minecraftWorld.setMaterialAt(x, y, z, AIR);
                                    material = AIR;
                                }
                            } else {
                                // There's a non-double high plant block above;
                                // replace this block with air
                                minecraftWorld.setMaterialAt(x, y, z, AIR);
                                material = AIR;
                            }
                        }
                        break;
                    case MC_CACTUS:
                        if ((materialBelow != SAND) && (materialBelow != RED_SAND) && materialBelow.isNotNamed(MC_CACTUS)) {
                            // Cactus blocks can only be on top of sand or other cactus blocks
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_SUGAR_CANE:
                        if (materialBelow.isNotNamed(MC_GRASS_BLOCK) && (materialBelow != DIRT) && materialBelow.isNotNamed(MC_PODZOL) && (materialBelow != PERMADIRT) && (materialBelow != SAND) && (materialBelow != RED_SAND) && materialBelow.isNotNamed(MC_SUGAR_CANE)) {
                            // Sugar cane blocks can only be on top of grass, dirt, sand or other sugar cane blocks
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_NETHER_WART:
                        if (materialBelow != SOUL_SAND) {
                            // Nether wart blocks can only be on top of soul sand
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_CHORUS_FLOWER:
                    case MC_CHORUS_PLANT:
                        if ((materialBelow != END_STONE) && (materialBelow.isNotNamed(MC_CHORUS_PLANT))) {
                            // Chorus flower and plant blocks can only be on top of end stone or other chorus plant blocks
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                    case MC_FIRE:
                        // the air
                        if ((materialBelow == AIR) && (materialAbove == AIR) && (minecraftWorld.getMaterialAt(x - 1, y, z) == AIR) && (minecraftWorld.getMaterialAt(x + 1, y, z) == AIR) && (minecraftWorld.getMaterialAt(x, y - 1, z) == AIR) && (minecraftWorld.getMaterialAt(x, y + 1, z) == AIR)) {
                            minecraftWorld.setMaterialAt(x, y, z, AIR);
                            material = AIR;
                        }
                        break;
                }
                materialBelow = material;
            }
        }
        if (progressReceiver != null) {
            progressReceiver.setProgress((float) (x - x1 + 1) / (x2 - x1 + 1));
        }
    }
}
Also used : MinecraftWorldObject(org.pepsoft.worldpainter.objects.MinecraftWorldObject) Box(org.pepsoft.util.Box) Material(org.pepsoft.minecraft.Material)

Example 3 with MinecraftWorldObject

use of org.pepsoft.worldpainter.objects.MinecraftWorldObject in project WorldPainter by Captain-Chaos.

the class LayerPreviewCreator method renderPreview.

public MinecraftWorldObject renderPreview() {
    // Phase one: setup
    long timestamp = System.currentTimeMillis();
    long seed = 0L;
    TileFactory tileFactory = subterranean ? TileFactoryFactory.createNoiseTileFactory(seed, Terrain.BARE_GRASS, previewHeight, 56, 62, false, true, 20f, 0.5) : TileFactoryFactory.createNoiseTileFactory(seed, Terrain.BARE_GRASS, previewHeight, 8, 14, false, true, 20f, 0.5);
    Dimension dimension = new World2(DefaultPlugin.JAVA_MCREGION, seed, tileFactory, previewHeight).getDimension(DIM_NORMAL);
    dimension.setSubsurfaceMaterial(Terrain.STONE);
    MinecraftWorldObject minecraftWorldObject = new MinecraftWorldObject(layer.getName() + " Preview", new Box(-8, 136, -8, 136, 0, previewHeight), previewHeight, null, new Point3i(-64, -64, 0));
    long now = System.currentTimeMillis();
    if (logger.isDebugEnabled()) {
        logger.debug("Creating data structures took " + (now - timestamp) + " ms");
    }
    // Phase two: apply layer to dimension
    timestamp = now;
    Tile tile = tileFactory.createTile(0, 0);
    switch(layer.getDataSize()) {
        case BIT:
            Random random = new Random(seed);
            for (int x = 0; x < 128; x++) {
                for (int y = 0; y < 128; y++) {
                    if (random.nextFloat() < pattern.getStrength(x, y)) {
                        tile.setBitLayerValue(layer, x, y, true);
                    }
                }
            }
            break;
        case BIT_PER_CHUNK:
            random = new Random(seed);
            for (int x = 0; x < 128; x += 16) {
                for (int y = 0; y < 128; y += 16) {
                    if (random.nextFloat() < pattern.getStrength(x, y)) {
                        tile.setBitLayerValue(layer, x, y, true);
                    }
                }
            }
            break;
        case BYTE:
            for (int x = 0; x < 128; x++) {
                for (int y = 0; y < 128; y++) {
                    tile.setLayerValue(layer, x, y, Math.min((int) (pattern.getStrength(x, y) * 256), 255));
                }
            }
            break;
        case NIBBLE:
            // any
            if (layer instanceof CombinedLayer) {
                final Terrain terrain = ((CombinedLayer) layer).getTerrain();
                final int biome = ((CombinedLayer) layer).getBiome();
                final boolean terrainConfigured = terrain != null;
                final boolean biomeConfigured = biome != -1;
                for (int x = 0; x < 128; x++) {
                    for (int y = 0; y < 128; y++) {
                        float strength = pattern.getStrength(x, y);
                        tile.setLayerValue(layer, x, y, Math.min((int) (strength * 16), 15));
                        // Double the strength so that 50% intensity results
                        // in full coverage for terrain and biome, which is
                        // inaccurate but probably more closely resembles
                        // practical usage
                        strength = Math.min(strength * 2, 1.0f);
                        if (terrainConfigured && ((strength > 0.95f) || (Math.random() < strength))) {
                            tile.setTerrain(x, y, terrain);
                        }
                        if (biomeConfigured && ((strength > 0.95f) || (Math.random() < strength))) {
                            tile.setLayerValue(Biome.INSTANCE, x, y, biome);
                        }
                    }
                }
            } else {
                for (int x = 0; x < 128; x++) {
                    for (int y = 0; y < 128; y++) {
                        tile.setLayerValue(layer, x, y, Math.min((int) (pattern.getStrength(x, y) * 16), 15));
                    }
                }
            }
            break;
        default:
            throw new IllegalArgumentException("Unsupported data size " + layer.getDataSize() + " encountered");
    }
    // If the layer is a combined layer, apply it recursively and collect
    // the added layers
    List<Layer> layers;
    if (layer instanceof CombinedLayer) {
        layers = new ArrayList<>();
        layers.add(layer);
        while (true) {
            List<Layer> addedLayers = new ArrayList<>();
            for (Iterator<Layer> i = layers.iterator(); i.hasNext(); ) {
                Layer tmpLayer = i.next();
                if (tmpLayer instanceof CombinedLayer) {
                    i.remove();
                    addedLayers.addAll(((CombinedLayer) tmpLayer).apply(tile));
                }
            }
            if (!addedLayers.isEmpty()) {
                layers.addAll(addedLayers);
            } else {
                break;
            }
        }
    } else {
        layers = Collections.singletonList(layer);
    }
    dimension.addTile(tile);
    now = System.currentTimeMillis();
    if (logger.isDebugEnabled()) {
        logger.debug("Applying layer(s) took " + (now - timestamp) + " ms");
    }
    // Collect the exporters (could be multiple if the layer was a combined
    // layer)
    Map<Layer, LayerExporter> pass1Exporters = new HashMap<>();
    Map<Layer, SecondPassLayerExporter> pass2Exporters = new HashMap<>();
    for (Layer tmpLayer : layers) {
        LayerExporter exporter = tmpLayer.getExporter();
        if (tmpLayer.equals(layer)) {
            exporter.setSettings(settings);
        }
        if (exporter instanceof FirstPassLayerExporter) {
            pass1Exporters.put(layer, exporter);
        }
        if (exporter instanceof SecondPassLayerExporter) {
            pass2Exporters.put(layer, (SecondPassLayerExporter) exporter);
        }
    }
    // Phase three: generate terrain and render first pass layers, if any
    timestamp = now;
    WorldPainterChunkFactory chunkFactory = new WorldPainterChunkFactory(dimension, pass1Exporters, JAVA_ANVIL_1_15, previewHeight);
    for (int x = 0; x < 8; x++) {
        for (int y = 0; y < 8; y++) {
            Chunk chunk = chunkFactory.createChunk(x, y).chunk;
            minecraftWorldObject.addChunk(chunk);
        }
    }
    now = System.currentTimeMillis();
    if (logger.isDebugEnabled()) {
        logger.debug("Generating terrain and rendering first pass layer(s) (if any) took " + (now - timestamp) + " ms");
    }
    if (!pass2Exporters.isEmpty()) {
        // Phase four: render the second pass layers, if any
        timestamp = now;
        Rectangle area = new Rectangle(128, 128);
        for (SecondPassLayerExporter exporter : pass2Exporters.values()) {
            exporter.render(dimension, area, area, minecraftWorldObject, JAVA_ANVIL_1_15);
        }
        now = System.currentTimeMillis();
        if (logger.isDebugEnabled()) {
            logger.debug("Rendering second pass layer(s) took " + (now - timestamp) + " ms");
        }
    }
    // Final phase: post processing
    timestamp = now;
    now = System.currentTimeMillis();
    try {
        new Java1_15PostProcessor().postProcess(minecraftWorldObject, new Rectangle(-8, -8, 136, 136), null);
    } catch (ProgressReceiver.OperationCancelled e) {
        // Can't happen since we didn't pass in a progress receiver
        throw new InternalError();
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Post processing took " + (now - timestamp) + " ms");
    }
    return minecraftWorldObject;
}
Also used : Point3i(javax.vecmath.Point3i) MinecraftWorldObject(org.pepsoft.worldpainter.objects.MinecraftWorldObject) Box(org.pepsoft.util.Box) Dimension(org.pepsoft.worldpainter.Dimension) Chunk(org.pepsoft.minecraft.Chunk) TunnelLayer(org.pepsoft.worldpainter.layers.tunnel.TunnelLayer) UndergroundPocketsLayer(org.pepsoft.worldpainter.layers.pockets.UndergroundPocketsLayer) GroundCoverLayer(org.pepsoft.worldpainter.layers.groundcover.GroundCoverLayer) ProgressReceiver(org.pepsoft.util.ProgressReceiver)

Example 4 with MinecraftWorldObject

use of org.pepsoft.worldpainter.objects.MinecraftWorldObject in project WorldPainter by Captain-Chaos.

the class EditLayerDialog method updatePreview.

private void updatePreview() {
    // chance is remote
    if (!editor.isCommitAvailable()) {
        return;
    }
    final ExporterSettings settings = editor.getSettings();
    synchronized (PREVIEW_STATE_LOCK) {
        switch(previewRenderState) {
            case IDLE:
                // Not rendering anything yet
                new Thread("Preview Creator for " + editor.getLayer().getName()) {

                    @Override
                    public void run() {
                        renderLoop: do {
                            synchronized (PREVIEW_RENDERER_LOCK) {
                                previewCreator.setLayer(settings.getLayer());
                                previewCreator.setSettings(settings);
                                final MinecraftWorldObject preview = previewCreator.renderPreview();
                                SwingUtilities.invokeLater(() -> dynMapPreviewer1.setObject(preview, app.getDimension()));
                            }
                            synchronized (PREVIEW_STATE_LOCK) {
                                switch(previewRenderState) {
                                    case SECOND_RENDER_SCHEDULED:
                                        previewRenderState = PreviewRenderState.RENDERING;
                                        // Loop again
                                        break;
                                    case RENDERING:
                                        previewRenderState = PreviewRenderState.IDLE;
                                    // Fall through to break loop
                                    default:
                                        // Break loop
                                        break renderLoop;
                                }
                            }
                        } while (true);
                    }
                }.start();
                previewRenderState = PreviewRenderState.RENDERING;
                break;
            case RENDERING:
                // A preview is already being rendered; set the state such
                // that when it is finished another render will immediately
                // be started
                previewRenderState = PreviewRenderState.SECOND_RENDER_SCHEDULED;
                break;
            case SECOND_RENDER_SCHEDULED:
                // do
                break;
        }
    }
}
Also used : MinecraftWorldObject(org.pepsoft.worldpainter.objects.MinecraftWorldObject) ExporterSettings(org.pepsoft.worldpainter.layers.exporters.ExporterSettings)

Example 5 with MinecraftWorldObject

use of org.pepsoft.worldpainter.objects.MinecraftWorldObject in project WorldPainter by Captain-Chaos.

the class LayerPreviewCreator method main.

public static void main(String[] args) throws IOException, ClassNotFoundException {
    Configuration config = Configuration.load();
    if (config == null) {
        config = new Configuration();
    }
    Configuration.setInstance(config);
    WPPluginManager.initialise(config.getUuid());
    Dimension dimension = WorldFactory.createDefaultWorldWithoutTiles(config, 0L).getDimension(DIM_NORMAL);
    for (Layer layer : LayerManager.getInstance().getLayers()) {
        // Layer layer = Caverns.INSTANCE;
        LayerPreviewCreator renderer = createPreviewerForLayer(layer, dimension);
        long start = System.currentTimeMillis();
        MinecraftWorldObject preview = renderer.renderPreview();
        System.out.println("Total: " + (System.currentTimeMillis() - start) + " ms");
        // JFrame frame = new JFrame("LayerPreviewCreator Test");
        // frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        DynMapPreviewer previewer = new DynMapPreviewer();
        previewer.setZoom(-2);
        previewer.setInclination(30.0);
        previewer.setAzimuth(60.0);
        if ((layer instanceof Caverns) || (layer instanceof Chasms) || (layer instanceof TunnelLayer)) {
            previewer.setCaves(true);
        }
        previewer.setObject(preview, dimension);
        // frame.getContentPane().add(previewer, BorderLayout.CENTER);
        // frame.setSize(800, 600);
        // frame.setLocationRelativeTo(null); // Center on screen
        // frame.setVisible(true);
        start = System.currentTimeMillis();
        BufferedImage image = previewer.createImage();
        System.out.println("Creating image took " + (System.currentTimeMillis() - start) + " ms");
        ImageIO.write(image, "png", new File(layer.getName().toLowerCase().replaceAll("\\s", "") + "-preview.png"));
    }
}
Also used : DynMapPreviewer(org.pepsoft.worldpainter.dynmap.DynMapPreviewer) MinecraftWorldObject(org.pepsoft.worldpainter.objects.MinecraftWorldObject) TunnelLayer(org.pepsoft.worldpainter.layers.tunnel.TunnelLayer) Dimension(org.pepsoft.worldpainter.Dimension) TunnelLayer(org.pepsoft.worldpainter.layers.tunnel.TunnelLayer) UndergroundPocketsLayer(org.pepsoft.worldpainter.layers.pockets.UndergroundPocketsLayer) GroundCoverLayer(org.pepsoft.worldpainter.layers.groundcover.GroundCoverLayer) File(java.io.File) BufferedImage(java.awt.image.BufferedImage)

Aggregations

MinecraftWorldObject (org.pepsoft.worldpainter.objects.MinecraftWorldObject)6 Box (org.pepsoft.util.Box)4 Dimension (org.pepsoft.worldpainter.Dimension)2 GroundCoverLayer (org.pepsoft.worldpainter.layers.groundcover.GroundCoverLayer)2 UndergroundPocketsLayer (org.pepsoft.worldpainter.layers.pockets.UndergroundPocketsLayer)2 TunnelLayer (org.pepsoft.worldpainter.layers.tunnel.TunnelLayer)2 BufferedImage (java.awt.image.BufferedImage)1 File (java.io.File)1 Point3i (javax.vecmath.Point3i)1 Chunk (org.pepsoft.minecraft.Chunk)1 Material (org.pepsoft.minecraft.Material)1 ProgressReceiver (org.pepsoft.util.ProgressReceiver)1 DynMapPreviewer (org.pepsoft.worldpainter.dynmap.DynMapPreviewer)1 ExporterSettings (org.pepsoft.worldpainter.layers.exporters.ExporterSettings)1