Underwater caves

This commit is contained in:
cyberpwn 2021-08-29 09:07:38 -04:00
parent b1aa7a8e88
commit e540596c20
11 changed files with 114 additions and 63 deletions

View File

@ -238,11 +238,6 @@ public interface EngineMantle extends IObjectPlacer {
getMantle().set(x, y, z, UpdateMatter.ON); getMantle().set(x, y, z, UpdateMatter.ON);
} }
@BlockCoordinates
default void cavernBlock(int x, int y, int z) {
getMantle().set(x, y, z, CavernMatter.ON);
}
@BlockCoordinates @BlockCoordinates
default void dropCavernBlock(int x, int y, int z) { default void dropCavernBlock(int x, int y, int z) {
Matter matter = getMantle().getChunk(x & 15, z & 15).get(y & 15); Matter matter = getMantle().getChunk(x & 15, z & 15).get(y & 15);

View File

@ -31,22 +31,26 @@ import com.volmit.iris.engine.object.decoration.IrisDecorator;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.B;
import com.volmit.iris.util.function.Consumer4;
import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.mantle.MantleChunk; import com.volmit.iris.util.mantle.MantleChunk;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.MatterCavern; import com.volmit.iris.util.matter.MatterCavern;
import com.volmit.iris.util.matter.slices.CavernMatter;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data; import lombok.Data;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier; import java.util.function.Supplier;
public class IrisCarveModifier extends EngineAssignedModifier<BlockData> { public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
private final RNG rng; private final RNG rng;
private final BlockData AIR = Material.CAVE_AIR.createBlockData(); private final BlockData AIR = Material.CAVE_AIR.createBlockData();
private final BlockData WATER = Material.WATER.createBlockData();
public IrisCarveModifier(Engine engine) { public IrisCarveModifier(Engine engine) {
super(engine, "Carve"); super(engine, "Carve");
@ -60,14 +64,19 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
MantleChunk mc = getEngine().getMantle().getMantle().getChunk(x, z); MantleChunk mc = getEngine().getMantle().getMantle().getChunk(x, z);
KMap<Long, KList<Integer>> positions = new KMap<>(); KMap<Long, KList<Integer>> positions = new KMap<>();
KMap<IrisPosition, MatterCavern> walls = new KMap<>(); KMap<IrisPosition, MatterCavern> walls = new KMap<>();
Consumer4<Integer, Integer, Integer, MatterCavern> iterator = (xx, yy, zz, c) -> {
if(c == null)
{
return;
}
mc.iterate(MatterCavern.class, (xx, yy, zz, c) -> {
if (yy > 256 || yy < 0) { if (yy > 256 || yy < 0) {
return; return;
} }
int rx = xx & 15; int rx = xx & 15;
int rz = zz & 15; int rz = zz & 15;
BlockData current = output.get(rx, yy, rz); BlockData current = output.get(rx, yy, rz);
if (B.isFluid(current)) { if (B.isFluid(current)) {
@ -96,8 +105,18 @@ public class IrisCarveModifier extends EngineAssignedModifier<BlockData> {
return; return;
} }
output.set(rx, yy, rz, AIR); if(c.isWater())
}); {
output.set(rx, yy, rz, WATER);
}
else
{
output.set(rx, yy, rz, AIR);
}
};
mc.iterate(MatterCavern.class, iterator);
walls.forEach((i, v) -> { walls.forEach((i, v) -> {
IrisBiome biome = v.getCustomBiome().isEmpty() IrisBiome biome = v.getCustomBiome().isEmpty()

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine.object.carving; package com.volmit.iris.engine.object.carving;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
@ -25,9 +26,14 @@ import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.MantleWriter; import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.annotations.Desc; import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.RegistryListResource; import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.basic.IrisRange; import com.volmit.iris.engine.object.basic.IrisRange;
import com.volmit.iris.engine.object.biome.IrisBiome; import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.block.IrisBlockData;
import com.volmit.iris.engine.object.noise.IrisWorm; import com.volmit.iris.engine.object.noise.IrisWorm;
import com.volmit.iris.engine.object.objects.IrisObjectLimit;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.json.JSONObject; import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.MatterCavern; import com.volmit.iris.util.matter.MatterCavern;
@ -38,6 +44,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.bukkit.block.data.BlockData;
import java.util.List;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Accessors(chain = true) @Accessors(chain = true)
@ -52,6 +61,10 @@ public class IrisCave extends IrisRegistrant {
@Desc("Define potential forking features") @Desc("Define potential forking features")
private IrisCarving fork = new IrisCarving(); private IrisCarving fork = new IrisCarving();
@RegistryListResource(IrisBiome.class)
@Desc("Force this cave to only generate the specified custom biome")
private String customBiome = "";
@Desc("Limit the worm from ever getting higher or lower than this range") @Desc("Limit the worm from ever getting higher or lower than this range")
private IrisRange verticalRange = new IrisRange(3, 255); private IrisRange verticalRange = new IrisRange(3, 255);
@ -65,12 +78,27 @@ public class IrisCave extends IrisRegistrant {
return "Cave"; return "Cave";
} }
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, MatterCavern biome) { public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z) {
writer.setLine(getWorm().generate(rng, engine.getData(), writer, verticalRange, x, y, z, double girth = getWorm().getGirth().get(rng, x, z, engine.getData());
(at) -> fork.doCarving(writer, rng, engine, at.getX(), at.getY(), at.getZ())), KList<IrisPosition> points = getWorm().generate(rng, engine.getData(), writer, verticalRange, x, y, z,
getWorm().getGirth().get(rng, x, z, engine.getData()), true, (at) -> fork.doCarving(writer, rng, engine, at.getX(), at.getY(), at.getZ()));
biome); boolean water = false;
for(IrisPosition i : points)
{
double yy = i.getY() + girth;
int th = engine.getHeight(x, z, true);
if(yy > th && th < engine.getDimension().getFluidHeight())
{
water = true;
break;
}
}
writer.setLine(points,
girth, true,
new MatterCavern(true, customBiome, water));
} }
@Override @Override

View File

@ -23,19 +23,15 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.MantleWriter; import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.modifier.IrisCarveModifier;
import com.volmit.iris.engine.object.annotations.Desc; import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MinNumber; import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource; import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required; import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.IRare; import com.volmit.iris.engine.object.common.IRare;
import com.volmit.iris.engine.object.noise.IrisGeneratorStyle; import com.volmit.iris.engine.object.noise.IrisGeneratorStyle;
import com.volmit.iris.engine.object.noise.IrisStyledRange; import com.volmit.iris.engine.object.noise.IrisStyledRange;
import com.volmit.iris.engine.object.noise.NoiseStyle; import com.volmit.iris.engine.object.noise.NoiseStyle;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.MatterCavern;
import com.volmit.iris.util.matter.slices.CavernMatter;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -66,11 +62,6 @@ public class IrisCavePlacer implements IRare {
@Desc("The height range this cave can spawn at. If breakSurface is false, the output of this range will be clamped by the current world height to prevent surface breaking.") @Desc("The height range this cave can spawn at. If breakSurface is false, the output of this range will be clamped by the current world height to prevent surface breaking.")
private IrisStyledRange caveStartHeight = new IrisStyledRange(13, 120, new IrisGeneratorStyle(NoiseStyle.STATIC)); private IrisStyledRange caveStartHeight = new IrisStyledRange(13, 120, new IrisGeneratorStyle(NoiseStyle.STATIC));
@RegistryListResource(IrisBiome.class)
@Desc("Force this cave to only generate the specified custom biome")
private String customBiome = "";
private transient final AtomicCache<MatterCavern> matterNodeCache = new AtomicCache<>();
private transient final AtomicCache<IrisCave> caveCache = new AtomicCache<>(); private transient final AtomicCache<IrisCave> caveCache = new AtomicCache<>();
private transient final AtomicBoolean fail = new AtomicBoolean(false); private transient final AtomicBoolean fail = new AtomicBoolean(false);
@ -103,8 +94,7 @@ public class IrisCavePlacer implements IRare {
} }
try { try {
cave.generate(mantle, rng, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), cave.generate(mantle, rng, engine, x + rng.nextInt(15), y, z + rng.nextInt(15));
matterNodeCache.aquire(() -> customBiome.isEmpty() ? CavernMatter.ON : CavernMatter.get(customBiome)));
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
fail.set(true); fail.set(true);

View File

@ -62,7 +62,7 @@ public class IrisElipsoid implements IRare {
writer.setElipsoid(x, y, z, writer.setElipsoid(x, y, z,
xRadius.get(rng, z, y, engine.getData()), xRadius.get(rng, z, y, engine.getData()),
yRadius.get(rng, x, z, engine.getData()), yRadius.get(rng, x, z, engine.getData()),
zRadius.get(rng, y, x, engine.getData()), true, matterNodeCache.aquire(() -> CavernMatter.get(getCustomBiome()))); zRadius.get(rng, y, x, engine.getData()), true, matterNodeCache.aquire(() -> CavernMatter.get(getCustomBiome(), false)));
} }
public double maxSize() { public double maxSize() {

View File

@ -53,7 +53,7 @@ public class IrisPyramid implements IRare {
private transient final AtomicCache<MatterCavern> matterNodeCache = new AtomicCache<>(); private transient final AtomicCache<MatterCavern> matterNodeCache = new AtomicCache<>();
public void generate(RNG rng, Engine engine, MantleWriter writer, int x, int y, int z) { public void generate(RNG rng, Engine engine, MantleWriter writer, int x, int y, int z) {
writer.setPyramid(x, y, z, matterNodeCache.aquire(() -> CavernMatter.get(getCustomBiome())), writer.setPyramid(x, y, z, matterNodeCache.aquire(() -> CavernMatter.get(getCustomBiome(), false)),
(int) baseWidth.get(rng, z, y, engine.getData()), true); (int) baseWidth.get(rng, z, y, engine.getData()), true);
} }

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine.object.carving; package com.volmit.iris.engine.object.carving;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant; import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
@ -28,6 +29,7 @@ import com.volmit.iris.engine.object.annotations.MaxNumber;
import com.volmit.iris.engine.object.annotations.MinNumber; import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource; import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.basic.IrisPosition; import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.basic.IrisRange;
import com.volmit.iris.engine.object.biome.IrisBiome; import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.noise.IrisShapedGeneratorStyle; import com.volmit.iris.engine.object.noise.IrisShapedGeneratorStyle;
import com.volmit.iris.engine.object.noise.IrisWorm; import com.volmit.iris.engine.object.noise.IrisWorm;
@ -55,6 +57,10 @@ public class IrisRavine extends IrisRegistrant {
@Desc("Define the shape of this ravine (2d, ignores Y)") @Desc("Define the shape of this ravine (2d, ignores Y)")
private IrisWorm worm; private IrisWorm worm;
@RegistryListResource(IrisBiome.class)
@Desc("Force this cave to only generate the specified custom biome")
private String customBiome = "";
@Desc("Define potential forking features") @Desc("Define potential forking features")
private IrisCarving fork = new IrisCarving(); private IrisCarving fork = new IrisCarving();
@ -92,54 +98,80 @@ public class IrisRavine extends IrisRegistrant {
return "Ravine"; return "Ravine";
} }
public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z, MatterCavern biome) { public void generate(MantleWriter writer, RNG rng, Engine engine, int x, int y, int z) {
KList<IrisPosition> pos = getWorm().generate(rng, engine.getData(), writer, null, x, y, z, (at) -> { KList<IrisPosition> pos = getWorm().generate(rng, engine.getData(), writer, null, x, y, z, (at) -> {});
});
CNG dg = depthStyle.getGenerator().createNoCache(rng, engine.getData()); CNG dg = depthStyle.getGenerator().createNoCache(rng, engine.getData());
CNG bw = baseWidthStyle.getGenerator().createNoCache(rng, engine.getData()); CNG bw = baseWidthStyle.getGenerator().createNoCache(rng, engine.getData());
if (pos.size() < nodeThreshold) { boolean water = false;
for(IrisPosition i : pos)
{
int rsurface = y == -1 ? engine.getComplex().getHeightStream().get(x, z).intValue() : y;
int depth = (int) Math.round(dg.fitDouble(depthStyle.getMin(), depthStyle.getMax(), i.getX(), i.getZ()));
int width = (int) Math.round(bw.fitDouble(baseWidthStyle.getMin(), baseWidthStyle.getMax(), i.getX(), i.getZ()));
int surface = (int) Math.round(rsurface - depth * 0.45);
int yy = surface + depth;
int th = engine.getHeight(x, z, true);
if(yy > th && th < engine.getDimension().getFluidHeight())
{
water = true;
break;
}
}
MatterCavern c = new MatterCavern(true, customBiome, water);
if(pos.size() < nodeThreshold)
{
return; return;
} }
for (IrisPosition p : pos) { for(IrisPosition p : pos)
{
int rsurface = y == -1 ? engine.getComplex().getHeightStream().get(x, z).intValue() : y; int rsurface = y == -1 ? engine.getComplex().getHeightStream().get(x, z).intValue() : y;
int depth = (int) Math.round(dg.fitDouble(depthStyle.getMin(), depthStyle.getMax(), p.getX(), p.getZ())); int depth = (int) Math.round(dg.fitDouble(depthStyle.getMin(), depthStyle.getMax(), p.getX(), p.getZ()));
int width = (int) Math.round(bw.fitDouble(baseWidthStyle.getMin(), baseWidthStyle.getMax(), p.getX(), p.getZ())); int width = (int) Math.round(bw.fitDouble(baseWidthStyle.getMin(), baseWidthStyle.getMax(), p.getX(), p.getZ()));
int surface = (int) Math.round(rsurface - depth * 0.45); int surface = (int) Math.round(rsurface - depth * 0.45);
fork.doCarving(writer, rng, engine, p.getX(), rng.i(surface - depth, surface), p.getZ()); fork.doCarving(writer, rng, engine, p.getX(), rng.i(surface-depth, surface), p.getZ());
for (int i = surface + depth; i >= surface; i--) { for(int i = surface + depth; i >= surface; i--)
if (i % ribThickness == 0) { {
if(i % ribThickness == 0) {
double v = width + ((((surface + depth) - i) * (angle / 360D))); double v = width + ((((surface + depth) - i) * (angle / 360D)));
if (v <= 0.25) { if(v <= 0.25)
{
break; break;
} }
if (i <= ribThickness + 2) { if(i <= ribThickness+2)
{
break; break;
} }
writer.setElipsoid(p.getX(), i, p.getZ(), v, ribThickness, v, true, biome); writer.setElipsoid(p.getX(), i, p.getZ(), v, ribThickness, v, true, c);
} }
} }
for (int i = surface - depth; i <= surface; i++) { for(int i = surface - depth; i <= surface; i++)
if (i % ribThickness == 0) { {
if(i % ribThickness == 0) {
double v = width - ((((surface - depth) - i) * (angle / 360D))); double v = width - ((((surface - depth) - i) * (angle / 360D)));
if (v <= 0.25) { if(v <= 0.25)
{
break; break;
} }
if (i <= ribThickness + 2) { if(i <= ribThickness+2)
{
break; break;
} }
writer.setElipsoid(p.getX(), i, p.getZ(), v, ribThickness, v, true, biome); writer.setElipsoid(p.getX(), i, p.getZ(), v, ribThickness, v, true, c);
} }
} }
} }

View File

@ -27,11 +27,8 @@ import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MinNumber; import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource; import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required; import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.IRare; import com.volmit.iris.engine.object.common.IRare;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.MatterCavern;
import com.volmit.iris.util.matter.slices.CavernMatter;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -56,11 +53,6 @@ public class IrisRavinePlacer implements IRare {
@RegistryListResource(IrisRavine.class) @RegistryListResource(IrisRavine.class)
private String ravine; private String ravine;
@RegistryListResource(IrisBiome.class)
@Desc("Force this cave to only generate the specified custom biome")
private String customBiome = "";
private transient final AtomicCache<MatterCavern> matterNodeCache = new AtomicCache<>();
private transient final AtomicCache<IrisRavine> ravineCache = new AtomicCache<>(); private transient final AtomicCache<IrisRavine> ravineCache = new AtomicCache<>();
private transient final AtomicBoolean fail = new AtomicBoolean(false); private transient final AtomicBoolean fail = new AtomicBoolean(false);
@ -89,8 +81,7 @@ public class IrisRavinePlacer implements IRare {
try { try {
int xx = x + rng.nextInt(15); int xx = x + rng.nextInt(15);
int zz = z + rng.nextInt(15); int zz = z + rng.nextInt(15);
ravine.generate(mantle, rng, engine, xx, y, zz, ravine.generate(mantle, rng, engine, xx, y, zz);
matterNodeCache.aquire(() -> customBiome.isEmpty() ? CavernMatter.ON : CavernMatter.get(customBiome)));
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
fail.set(true); fail.set(true);

View File

@ -53,7 +53,7 @@ public class IrisSphere implements IRare {
private transient final AtomicCache<MatterCavern> matterNodeCache = new AtomicCache<>(); private transient final AtomicCache<MatterCavern> matterNodeCache = new AtomicCache<>();
public void generate(RNG rng, Engine engine, MantleWriter writer, int x, int y, int z) { public void generate(RNG rng, Engine engine, MantleWriter writer, int x, int y, int z) {
writer.setSphere(x, y, z, radius.get(rng, z, y, engine.getData()), true, matterNodeCache.aquire(() -> CavernMatter.get(getCustomBiome()))); writer.setSphere(x, y, z, radius.get(rng, z, y, engine.getData()), true, matterNodeCache.aquire(() -> CavernMatter.get(getCustomBiome(), false)));
} }
public double maxSize() { public double maxSize() {

View File

@ -26,4 +26,5 @@ import lombok.Data;
public class MatterCavern { public class MatterCavern {
private final boolean cavern; private final boolean cavern;
private final String customBiome; private final String customBiome;
private final boolean water;
} }

View File

@ -27,15 +27,8 @@ import java.io.IOException;
@Sliced @Sliced
public class CavernMatter extends RawMatter<MatterCavern> { public class CavernMatter extends RawMatter<MatterCavern> {
public static final MatterCavern ON = new MatterCavern(true, ""); public static MatterCavern get(String customBiome, boolean underwater) {
public static final MatterCavern OFF = new MatterCavern(false, ""); return new MatterCavern(true, customBiome, underwater);
public static MatterCavern get(String customBiome) {
if (customBiome.isEmpty()) {
return ON;
}
return new MatterCavern(true, customBiome);
} }
public CavernMatter() { public CavernMatter() {
@ -49,14 +42,16 @@ public class CavernMatter extends RawMatter<MatterCavern> {
@Override @Override
public void writeNode(MatterCavern b, DataOutputStream dos) throws IOException { public void writeNode(MatterCavern b, DataOutputStream dos) throws IOException {
dos.writeBoolean(b.isCavern()); dos.writeBoolean(b.isCavern());
dos.writeBoolean(b.isWater());
dos.writeUTF(b.getCustomBiome()); dos.writeUTF(b.getCustomBiome());
} }
@Override @Override
public MatterCavern readNode(DataInputStream din) throws IOException { public MatterCavern readNode(DataInputStream din) throws IOException {
boolean b = din.readBoolean(); boolean b = din.readBoolean();
boolean w = din.readBoolean();
String v = din.readUTF(); String v = din.readUTF();
return v.isEmpty() ? b ? ON : OFF : new MatterCavern(b, v); return new MatterCavern(b, v, w);
} }
} }