Search in sources :

Example 1 with MixedMaterial

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

the class GetTerrainOp method go.

@Override
public MixedMaterial go() throws ScriptException {
    goCalled();
    File file = sanityCheckFileName(fileName);
    try {
        try (ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new FileInputStream(file)))) {
            return (MixedMaterial) in.readObject();
        }
    } catch (IOException e) {
        throw new ScriptException("I/O error while loading terrain " + fileName, e);
    } catch (ClassCastException e) {
        throw new ScriptException(fileName + " is not a WorldPainter custom terrain file", e);
    } catch (ClassNotFoundException e) {
        throw new ScriptException("Class not found exception while loading terrain " + fileName + " (not a WorldPainter custom terrain?)", e);
    }
}
Also used : GZIPInputStream(java.util.zip.GZIPInputStream) IOException(java.io.IOException) File(java.io.File) FileInputStream(java.io.FileInputStream) MixedMaterial(org.pepsoft.worldpainter.MixedMaterial) ObjectInputStream(java.io.ObjectInputStream)

Example 2 with MixedMaterial

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

the class RiverExporter method render.

@Override
public List<Fixup> render(final Dimension dimension, final Rectangle area, final Rectangle exportedArea, final MinecraftWorld minecraftWorld) {
    final RiverSettings settings = new RiverSettings();
    final int shoreHeight = settings.getShoreHeight();
    final boolean shore = shoreHeight > 0;
    final MixedMaterial riverBedMaterial = settings.getRiverBedMaterial();
    final int riverConnectionRadius = settings.getRiverConnectionRadius();
    final int maxDepth = shoreHeight + settings.getMaxDepth();
    final int depthVariation = settings.getMaxDepth() - settings.getMinDepth();
    final long seed = dimension.getSeed();
    if (floorNoise.getSeed() != seed) {
        floorNoise.setSeed(seed);
    }
    // First pass. Dig out the riverbed and flood the river
    for (int x = area.x; x < area.x + area.width; x++) {
        for (int y = area.y; y < area.y + area.height; y++) {
            if (dimension.getBitLayerValueAt(River.INSTANCE, x, y)) {
                final float distanceToShore = dimension.getDistanceToEdge(River.INSTANCE, x, y, maxDepth);
                final int depth = (int) Math.min(distanceToShore, maxDepth - (int) ((floorNoise.getPerlinNoise(x / TINY_BLOBS, y / TINY_BLOBS) + 0.5f) * depthVariation + 0.5f));
                final int terrainHeight = dimension.getIntHeightAt(x, y);
                final int waterLevel = dimension.getWaterLevelAt(x, y);
                if ((waterLevel > terrainHeight) && (!dimension.getBitLayerValueAt(FloodWithLava.INSTANCE, x, y))) {
                    // river bed
                    for (int dz = 0; dz >= (-depth - 1); dz--) {
                        final int z = waterLevel + dz;
                        if (dz > -depth) {
                            minecraftWorld.setMaterialAt(x, y, z, STATIONARY_WATER);
                        } else if (z <= terrainHeight) {
                            minecraftWorld.setMaterialAt(x, y, z, riverBedMaterial.getMaterial(seed, x, y, z));
                        }
                    }
                } else {
                    // check for it
                    for (int dz = 0; dz >= (-depth - 1); dz--) {
                        final int z = terrainHeight + dz;
                        if (z <= 0) {
                            break;
                        }
                        if (dz <= -depth) {
                            // River bed
                            int existingBlockType = minecraftWorld.getBlockTypeAt(x, y, z);
                            if (!BLOCKS[existingBlockType].veryInsubstantial) {
                                minecraftWorld.setMaterialAt(x, y, z, riverBedMaterial.getMaterial(seed, x, y, z));
                            }
                        } else if (dz > -shoreHeight) {
                            // The air above the river
                            int existingBlockType = minecraftWorld.getBlockTypeAt(x, y, z);
                            if ((existingBlockType != BLK_WATER) && (existingBlockType != BLK_STATIONARY_WATER)) {
                                minecraftWorld.setMaterialAt(x, y, z, AIR);
                            }
                        } else if (dz == -shoreHeight) {
                            // The surface of the river
                            minecraftWorld.setMaterialAt(x, y, z, STATIONARY_WATER);
                        } else {
                            // The river itself below the surface
                            minecraftWorld.setMaterialAt(x, y, z, STATIONARY_WATER);
                        }
                    }
                }
            }
        }
    }
    // flood the connecting areas
    if (shore) {
        for (int x = area.x; x < area.x + area.width; x++) {
            for (int y = area.y; y < area.y + area.height; y++) {
                final int waterLevel = dimension.getWaterLevelAt(x, y);
                if (// River
                dimension.getBitLayerValueAt(River.INSTANCE, x, y) && // Flooded
                (waterLevel > dimension.getIntHeightAt(x, y)) && (dimension.getFloodedCount(x, y, 1, false) < 9)) {
                    // Not every surrounding block flooded
                    // We're at the edge of a flooded area. Check
                    // whether it needs to be expanded to flood the
                    // connecting riverbed, where the water will be
                    // lower (if the shore height is higher than zero)
                    final int finalX = x, finalY = y;
                    // First see if there is any river around with a
                    // water level that's higher
                    final boolean[] higherRiverAround = new boolean[1];
                    GeometryUtil.visitFilledCircle(riverConnectionRadius, (dx, dy, d) -> {
                        final int x1 = finalX + dx, y1 = finalY + dy;
                        if ((dimension.getBitLayerValueAt(River.INSTANCE, x1, y1)) && ((dimension.getIntHeightAt(x1, y1) - shoreHeight) > waterLevel)) {
                            higherRiverAround[0] = true;
                            return false;
                        } else {
                            return true;
                        }
                    });
                    if (higherRiverAround[0]) {
                        // There is a river near with a water level
                        // that's higher, so flood the surroundings to
                        // the height of the body of water
                        GeometryUtil.visitFilledCircle(riverConnectionRadius, (dx, dy, d) -> {
                            final int x1 = finalX + dx, y1 = finalY + dy;
                            if ((dimension.getBitLayerValueAt(River.INSTANCE, x1, y1)) && (dimension.getWaterLevelAt(x1, y1) < waterLevel)) {
                                int z = waterLevel;
                                int existingBlockType = minecraftWorld.getBlockTypeAt(x1, y1, z);
                                while ((z > 0) && (existingBlockType != BLK_WATER) && (existingBlockType != BLK_STATIONARY_WATER) && (existingBlockType != BLK_ICE) && BLOCKS[existingBlockType].veryInsubstantial) {
                                    minecraftWorld.setMaterialAt(x1, y1, z, STATIONARY_WATER);
                                    z--;
                                    existingBlockType = minecraftWorld.getBlockTypeAt(x1, y1, z);
                                }
                            }
                            return true;
                        });
                    } else {
                        // There is no river near with a water level
                        // that's higher, so flood the surroundings
                        // sloping down just in case there's *lower*
                        // river water which we want to connect to a bit
                        // less abruptly than with a sheer wall of water
                        GeometryUtil.visitFilledCircle(riverConnectionRadius, (dx, dy, d) -> {
                            final int x1 = finalX + dx, y1 = finalY + dy;
                            if ((dimension.getBitLayerValueAt(River.INSTANCE, x1, y1)) && (dimension.getWaterLevelAt(x1, y1) < waterLevel)) {
                                int z = waterLevel - ((int) d);
                                int existingBlockType = minecraftWorld.getBlockTypeAt(x1, y1, z);
                                while ((z > 0) && (existingBlockType != BLK_WATER) && (existingBlockType != BLK_STATIONARY_WATER) && (existingBlockType != BLK_ICE) && BLOCKS[existingBlockType].veryInsubstantial) {
                                    minecraftWorld.setMaterialAt(x1, y1, z, STATIONARY_WATER);
                                    z--;
                                    existingBlockType = minecraftWorld.getBlockTypeAt(x1, y1, z);
                                }
                            }
                            return true;
                        });
                    }
                }
            }
        }
    }
    // overflowing problems
    for (int x = area.x; x < area.x + area.width; x++) {
        for (int y = area.y; y < area.y + area.height; y++) {
            if (dimension.getBitLayerValueAt(River.INSTANCE, x, y)) {
                int lowestWaterHeight = -1;
                for (int z = dimension.getIntHeightAt(x, y); z > 0; z--) {
                    if (((minecraftWorld.getBlockTypeAt(x, y, z) == BLK_WATER) || (minecraftWorld.getBlockTypeAt(x, y, z) == BLK_STATIONARY_WATER)) && (minecraftWorld.getBlockTypeAt(x, y, z - 1) != BLK_WATER) && (minecraftWorld.getBlockTypeAt(x, y, z - 1) != BLK_STATIONARY_WATER)) {
                        lowestWaterHeight = z;
                        break;
                    }
                }
                if (lowestWaterHeight != -1) {
                    // There is water in this column. Raise the water in
                    // surrounding columns to at least the height of the
                    // lowest water block in this column.
                    raiseWaterTo(dimension, minecraftWorld, x + 1, y, lowestWaterHeight - 1);
                    raiseWaterTo(dimension, minecraftWorld, x, y + 1, lowestWaterHeight - 1);
                    raiseWaterTo(dimension, minecraftWorld, x - 1, y, lowestWaterHeight - 1);
                    raiseWaterTo(dimension, minecraftWorld, x, y - 1, lowestWaterHeight - 1);
                }
            }
        }
    }
    return null;
}
Also used : MixedMaterial(org.pepsoft.worldpainter.MixedMaterial)

Example 3 with MixedMaterial

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

the class GroundCoverLayerExporter method render.

@Override
public void render(Dimension dimension, Tile tile, Chunk chunk) {
    if (noiseHeightMap != null) {
        noiseHeightMap.setSeed(dimension.getSeed());
    }
    final int xOffset = (chunk.getxPos() & 7) << 4;
    final int zOffset = (chunk.getzPos() & 7) << 4;
    final int minY = dimension.isBottomless() ? 0 : 1;
    final int maxY = dimension.getMaxHeight() - 1;
    final MixedMaterial mixedMaterial = layer.getMaterial();
    final int thickness = layer.getThickness(), edgeThickness = Math.abs(thickness) - 2;
    final GroundCoverLayer.EdgeShape edgeShape = layer.getEdgeShape();
    final boolean taperedEdge = (edgeShape != GroundCoverLayer.EdgeShape.SHEER) && (Math.abs(thickness) > 1);
    final int edgeWidth = layer.getEdgeWidth(), edgeWidthPlusOne = edgeWidth + 1, edgeWidthMinusOne = edgeWidth - 1;
    final double edgeFactor = edgeThickness / 2.0, edgeOffset = 1.5 + edgeFactor;
    final long seed = dimension.getSeed();
    final boolean smooth = layer.isSmooth();
    for (int x = 0; x < 16; x++) {
        final int localX = xOffset + x;
        final int worldX = (chunk.getxPos() << 4) + x;
        for (int z = 0; z < 16; z++) {
            final int localY = zOffset + z;
            if (tile.getBitLayerValue(layer, localX, localY)) {
                final int terrainheight = tile.getIntHeight(localX, localY);
                final int blockBelow = chunk.getBlockType(x, terrainheight, z);
                if ((blockBelow != BLK_AIR) && (!Block.BLOCKS[blockBelow].insubstantial)) {
                    int effectiveThickness = Math.abs(thickness);
                    final int worldY = (chunk.getzPos() << 4) + z;
                    if (taperedEdge) {
                        float distanceToEdge = dimension.getDistanceToEdge(layer, worldX, worldY, edgeWidthPlusOne);
                        if (distanceToEdge < edgeWidthPlusOne) {
                            final double normalisedDistance = (distanceToEdge - 1) / edgeWidthMinusOne;
                            switch(edgeShape) {
                                case LINEAR:
                                    effectiveThickness = (int) (1.5 + normalisedDistance * edgeThickness);
                                    break;
                                case SMOOTH:
                                    effectiveThickness = (int) (edgeOffset + -Math.cos(normalisedDistance * Math.PI) * edgeFactor);
                                    break;
                                case ROUNDED:
                                    double reversedNormalisedDistance = 1 - (distanceToEdge - 0.5) / edgeWidth;
                                    effectiveThickness = (int) (1.5 + Math.sqrt(1 - reversedNormalisedDistance * reversedNormalisedDistance) * edgeThickness);
                                    break;
                            }
                        }
                    }
                    if (noiseHeightMap != null) {
                        effectiveThickness += noiseHeightMap.getHeight(worldX, worldY) - noiseOffset;
                    }
                    if (thickness > 0) {
                        for (int dy = 0; dy < effectiveThickness; dy++) {
                            final int y = terrainheight + dy + 1;
                            if (y > maxY) {
                                break;
                            }
                            final int existingBlockType = chunk.getBlockType(x, y, z);
                            final Material material = mixedMaterial.getMaterial(seed, worldX, worldY, y);
                            if ((material != Material.AIR) && ((!material.block.veryInsubstantial) || (existingBlockType == BLK_AIR) || Block.BLOCKS[existingBlockType].insubstantial)) {
                                if (smooth && (dy == (effectiveThickness - 1))) {
                                    // Top layer, smooth enabled
                                    int layerHeight = (int) ((dimension.getHeightAt(worldX, worldY) + 0.5f - dimension.getIntHeightAt(worldX, worldY)) / 0.125f);
                                    if (layerHeight > 0) {
                                        layerHeight = Math.max(Math.min(layerHeight, dimension.getBitLayerCount(layer, worldX, worldY, 1) - 2), 0);
                                    }
                                    chunk.setBlockType(x, y, z, material.blockType);
                                    chunk.setDataValue(x, y, z, layerHeight);
                                } else {
                                    chunk.setMaterial(x, y, z, material);
                                }
                            }
                        }
                    } else {
                        for (int dy = 0; dy < effectiveThickness; dy++) {
                            final int y = terrainheight - dy;
                            if (y < minY) {
                                break;
                            }
                            int existingBlockType = chunk.getBlockType(x, y, z);
                            if (existingBlockType != BLK_AIR) {
                                chunk.setMaterial(x, y, z, mixedMaterial.getMaterial(seed, worldX, worldY, y));
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : Material(org.pepsoft.minecraft.Material) MixedMaterial(org.pepsoft.worldpainter.MixedMaterial) MixedMaterial(org.pepsoft.worldpainter.MixedMaterial)

Example 4 with MixedMaterial

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

the class UndergroundPocketsDialog method updateNameAndColour.

private void updateNameAndColour() {
    if (fieldName.isEnabled()) {
        if (radioButtonCustomMaterial.isSelected()) {
            MixedMaterial material = mixedMaterialChooser.getMaterial();
            if (material != null) {
                fieldName.setText(material.toString());
                if (material.getColour() != null) {
                    selectedColour = material.getColour();
                    setLabelColour();
                }
            }
        } else {
            Terrain terrain = (Terrain) comboBoxTerrain.getSelectedItem();
            if (terrain != null) {
                fieldName.setText(terrain.getName());
            }
        }
    }
}
Also used : Terrain(org.pepsoft.worldpainter.Terrain) MixedMaterial(org.pepsoft.worldpainter.MixedMaterial)

Example 5 with MixedMaterial

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

the class UndergroundPocketsDialog method updatePreview.

private void updatePreview() {
    if (previewUpdateTimer != null) {
        // Superfluous?
        previewUpdateTimer.stop();
        previewUpdateTimer = null;
    }
    MixedMaterial material = radioButtonCustomMaterial.isSelected() ? mixedMaterialChooser.getMaterial() : null;
    Terrain terrain = radioButtonTerrain.isSelected() ? (Terrain) comboBoxTerrain.getSelectedItem() : null;
    if ((material == null) && (terrain == null)) {
        return;
    }
    int occurrence = (Integer) spinnerOccurrence.getValue();
    int scale = (Integer) spinnerScale.getValue();
    int minLevel = (Integer) spinnerMinLevel.getValue();
    int maxLevel = (Integer) spinnerMaxLevel.getValue();
    UndergroundPocketsLayer tmpLayer = new UndergroundPocketsLayer("tmp", material, terrain, occurrence, minLevel, maxLevel, scale, 0);
    labelPreview.setIcon(new ImageIcon(((UndergroundPocketsLayerExporter) tmpLayer.getExporter()).createPreview(labelPreview.getWidth(), labelPreview.getHeight())));
}
Also used : Terrain(org.pepsoft.worldpainter.Terrain) MixedMaterial(org.pepsoft.worldpainter.MixedMaterial)

Aggregations

MixedMaterial (org.pepsoft.worldpainter.MixedMaterial)13 Terrain (org.pepsoft.worldpainter.Terrain)3 File (java.io.File)2 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 Material (org.pepsoft.minecraft.Material)2 CustomLayer (org.pepsoft.worldpainter.layers.CustomLayer)2 Layer (org.pepsoft.worldpainter.layers.Layer)2 Point (java.awt.Point)1 FileInputStream (java.io.FileInputStream)1 ObjectInputStream (java.io.ObjectInputStream)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Random (java.util.Random)1 GZIPInputStream (java.util.zip.GZIPInputStream)1 JFrame (javax.swing.JFrame)1 TreePath (javax.swing.tree.TreePath)1 Point3i (javax.vecmath.Point3i)1 ProgressReceiver (org.pepsoft.util.ProgressReceiver)1 TiledImageViewer (org.pepsoft.util.swing.TiledImageViewer)1