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);
}
}
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;
}
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));
}
}
}
}
}
}
}
}
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());
}
}
}
}
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())));
}
Aggregations