mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-07 08:16:31 +00:00
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.volmit.iris.engine.modifier;
|
||||
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineAssignedModifier;
|
||||
import com.volmit.iris.engine.object.biome.IrisBiome;
|
||||
import com.volmit.iris.engine.object.carve.IrisCaveLayer;
|
||||
import com.volmit.iris.engine.object.common.CaveResult;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.noise.FastNoiseDouble;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class IrisCaveModifier extends EngineAssignedModifier<BlockData> {
|
||||
public static final BlockData CAVE_AIR = B.get("CAVE_AIR");
|
||||
public static final BlockData AIR = B.get("AIR");
|
||||
private static final KList<CaveResult> EMPTY = new KList<>();
|
||||
private final FastNoiseDouble gg;
|
||||
private final RNG rng;
|
||||
|
||||
public IrisCaveModifier(Engine engine) {
|
||||
super(engine, "Cave");
|
||||
rng = new RNG(engine.getWorld().seed() + 28934555);
|
||||
gg = new FastNoiseDouble(324895L * rng.nextParallelRNG(49678).imax());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModify(int x, int z, Hunk<BlockData> a, boolean multicore) {
|
||||
if (!getDimension().isCaves()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
if (multicore) {
|
||||
BurstExecutor e = getEngine().burst().burst(a.getWidth());
|
||||
for (int i = 0; i < a.getWidth(); i++) {
|
||||
int finalI = i;
|
||||
e.queue(() -> modifySliver(x, z, finalI, a));
|
||||
}
|
||||
|
||||
e.complete();
|
||||
} else {
|
||||
for (int i = 0; i < a.getWidth(); i++) {
|
||||
modifySliver(x, z, i, a);
|
||||
}
|
||||
}
|
||||
|
||||
getEngine().getMetrics().getCave().put(p.getMilliseconds());
|
||||
}
|
||||
|
||||
public void modifySliver(int x, int z, int finalI, Hunk<BlockData> a) {
|
||||
for (int j = 0; j < a.getDepth(); j++) {
|
||||
KList<CaveResult> caves = genCaves(x + finalI, z + j, finalI, j, a);
|
||||
int he = (int) Math.round(getComplex().getHeightStream().get(x + finalI, z + j));
|
||||
if (caves != null && caves.isNotEmpty()) {
|
||||
IrisBiome cave = getComplex().getCaveBiomeStream().get(x + finalI, z + j);
|
||||
|
||||
if (cave == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (CaveResult cl : caves) {
|
||||
if (cl.getFloor() < 0 || cl.getFloor() > getEngine().getHeight() || cl.getCeiling() > getEngine().getHeight() || cl.getCeiling() < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
KList<BlockData> floor = cave.generateLayers(x + finalI, z + j, rng, cl.getFloor(), cl.getFloor(), getData(), getComplex());
|
||||
KList<BlockData> ceiling = cave.generateLayers(x + finalI + 656, z + j - 656, rng,
|
||||
he - cl.getCeiling(),
|
||||
he - cl.getCeiling(), getData(), getComplex());
|
||||
|
||||
for (int g = 0; g < floor.size(); g++) {
|
||||
a.set(finalI, cl.getFloor() - g, j, floor.get(g));
|
||||
}
|
||||
|
||||
for (int g = ceiling.size() - 1; g > 0; g--) {
|
||||
a.set(finalI, cl.getCeiling() + g, j, ceiling.get(g));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public KList<CaveResult> genCaves(double wxx, double wzz) {
|
||||
return genCaves(wxx, wzz, 0, 0, null);
|
||||
}
|
||||
|
||||
public KList<CaveResult> genCaves(double wxx, double wzz, int x, int z, Hunk<BlockData> data) {
|
||||
if (!getDimension().isCaves()) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
KList<CaveResult> result = new KList<>();
|
||||
gg.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
|
||||
gg.setCellularReturnType(FastNoiseDouble.CellularReturnType.Distance2Sub);
|
||||
gg.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
|
||||
|
||||
for (int i = 0; i < getDimension().getCaveLayers().size(); i++) {
|
||||
IrisCaveLayer layer = getDimension().getCaveLayers().get(i);
|
||||
generateCave(result, wxx, wzz, x, z, data, layer, i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void generateCave(KList<CaveResult> result, double wxx, double wzz, int x, int z, Hunk<BlockData> data, IrisCaveLayer layer, int seed) {
|
||||
double scale = layer.getCaveZoom();
|
||||
Function<Integer, BlockData> fluid = (height) ->
|
||||
{
|
||||
if (!layer.getFluid().hasFluid(getData())) {
|
||||
return CAVE_AIR;
|
||||
}
|
||||
|
||||
if (layer.getFluid().isInverseHeight() && height >= layer.getFluid().getFluidHeight()) {
|
||||
return layer.getFluid().getFluid(getData());
|
||||
} else if (!layer.getFluid().isInverseHeight() && height <= layer.getFluid().getFluidHeight()) {
|
||||
return layer.getFluid().getFluid(getData());
|
||||
}
|
||||
|
||||
return CAVE_AIR;
|
||||
};
|
||||
|
||||
int surface = (int) Math.round(getComplex().getHeightStream().get(wxx, wzz));
|
||||
double wx = wxx + layer.getHorizontalSlope().get(rng, getData(), wxx, wzz);
|
||||
double wz = wzz + layer.getHorizontalSlope().get(rng, getData(), -wzz, -wxx);
|
||||
double baseWidth = (14 * scale);
|
||||
double distanceCheck = 0.0132 * baseWidth;
|
||||
double distanceTake = 0.0022 * baseWidth;
|
||||
double caveHeightNoise = layer.getVerticalSlope().get(rng, getData(), wxx, wzz);
|
||||
|
||||
if (caveHeightNoise > 259 || caveHeightNoise < -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: WARNING HEIGHT
|
||||
int ceiling = -256;
|
||||
int floor = 512;
|
||||
|
||||
for (double tunnelHeight = 1; tunnelHeight <= baseWidth; tunnelHeight++) {
|
||||
double distance = (gg.GetCellular(((wx + (10000 * seed)) / layer.getCaveZoom()), ((wz - (10000 * seed)) / layer.getCaveZoom())) + 1D) / 2D;
|
||||
if (distance < distanceCheck - (tunnelHeight * distanceTake)) {
|
||||
int caveHeight = (int) Math.round(caveHeightNoise);
|
||||
int pu = (int) (caveHeight + tunnelHeight);
|
||||
int pd = (int) (caveHeight - tunnelHeight);
|
||||
|
||||
if (pd > surface + 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!layer.isCanBreakSurface() && pu > surface - 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pu > 255 && pd > 255) || (pu < 0 && pd < 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
ceiling = Math.max(pu, ceiling);
|
||||
floor = Math.min(pu, floor);
|
||||
ceiling = Math.max(pd, ceiling);
|
||||
floor = Math.min(pd, floor);
|
||||
|
||||
if (tunnelHeight == 1) {
|
||||
ceiling = Math.max(caveHeight, ceiling);
|
||||
floor = Math.min(caveHeight, floor);
|
||||
}
|
||||
} else {
|
||||
if (dig(x, pu, z, data, fluid)) {
|
||||
ceiling = Math.max(pu, ceiling);
|
||||
floor = Math.min(pu, floor);
|
||||
}
|
||||
|
||||
if (dig(x, pd, z, data, fluid)) {
|
||||
ceiling = Math.max(pd, ceiling);
|
||||
floor = Math.min(pd, floor);
|
||||
}
|
||||
|
||||
if (tunnelHeight == 1) {
|
||||
if (dig(x, caveHeight, z, data, fluid)) {
|
||||
ceiling = Math.max(caveHeight, ceiling);
|
||||
floor = Math.min(caveHeight, floor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (floor >= 0 && ceiling <= 255) {
|
||||
result.add(new CaveResult(floor, ceiling));
|
||||
}
|
||||
}
|
||||
|
||||
private Material mat(int x, int y, int z, Hunk<BlockData> data) {
|
||||
BlockData d = data.get(Math.max(x, 0), Math.max(y, 0), Math.max(z, 0));
|
||||
|
||||
if (d != null) {
|
||||
return d.getMaterial();
|
||||
}
|
||||
|
||||
return Material.CAVE_AIR;
|
||||
}
|
||||
|
||||
public boolean dig(int x, int y, int z, Hunk<BlockData> data, Function<Integer, BlockData> caveFluid) {
|
||||
Material a = mat(x, y, z, data);
|
||||
Material c = mat(x, y + 1, z, data);
|
||||
Material d = mat(x, y + 2, z, data);
|
||||
Material e = mat(x, y + 3, z, data);
|
||||
Material f = mat(x, y - 1, z, data);
|
||||
BlockData b = caveFluid.apply(y);
|
||||
BlockData b2 = caveFluid.apply(y + 1);
|
||||
|
||||
if (can(a) && canAir(c, b) && canAir(f, b) && canWater(d) && canWater(e)) {
|
||||
data.set(x, y, z, b);
|
||||
data.set(x, y + 1, z, b2);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canAir(Material m, BlockData caveFluid) {
|
||||
return (B.isSolid(m) ||
|
||||
(B.isDecorant(m.createBlockData())) || m.equals(Material.AIR)
|
||||
|| m.equals(caveFluid.getMaterial()) ||
|
||||
m.equals(B.getMaterial("CAVE_AIR")))
|
||||
&& !m.equals(Material.BEDROCK);
|
||||
}
|
||||
|
||||
public boolean canWater(Material m) {
|
||||
return !m.equals(Material.WATER);
|
||||
}
|
||||
|
||||
public boolean can(Material m) {
|
||||
return B.isSolid(m) && !m.equals(Material.BEDROCK);
|
||||
}
|
||||
}
|
||||
@@ -159,54 +159,58 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
|
||||
// Wall Patcher
|
||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(x, z);
|
||||
|
||||
if (!biome.getWall().getPalette().isEmpty()) {
|
||||
if (ha < h - 2 || hb < h - 2 || hc < h - 2 || hd < h - 2) {
|
||||
boolean brokeGround = false;
|
||||
int max = Math.abs(Math.max(h - ha, Math.max(h - hb, Math.max(h - hc, h - hd))));
|
||||
if (getDimension().isPostProcessingWalls()) {
|
||||
if (!biome.getWall().getPalette().isEmpty()) {
|
||||
if (ha < h - 2 || hb < h - 2 || hc < h - 2 || hd < h - 2) {
|
||||
boolean brokeGround = false;
|
||||
int max = Math.abs(Math.max(h - ha, Math.max(h - hb, Math.max(h - hc, h - hd))));
|
||||
|
||||
for (int i = h; i > h - max; i--) {
|
||||
BlockData d = biome.getWall().get(rng, x + i, i + h, z + i, getData());
|
||||
for (int i = h; i > h - max; i--) {
|
||||
BlockData d = biome.getWall().get(rng, x + i, i + h, z + i, getData());
|
||||
|
||||
if (d != null) {
|
||||
if (isAirOrWater(x, i, z, currentPostX, currentPostZ, currentData)) {
|
||||
if (brokeGround) {
|
||||
break;
|
||||
if (d != null) {
|
||||
if (isAirOrWater(x, i, z, currentPostX, currentPostZ, currentData)) {
|
||||
if (brokeGround) {
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
setPostBlock(x, i, z, d, currentPostX, currentPostZ, currentData);
|
||||
brokeGround = true;
|
||||
}
|
||||
|
||||
setPostBlock(x, i, z, d, currentPostX, currentPostZ, currentData);
|
||||
brokeGround = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Slab
|
||||
//@builder
|
||||
if ((ha == h + 1 && isSolidNonSlab(x + 1, ha, z, currentPostX, currentPostZ, currentData))
|
||||
|| (hb == h + 1 && isSolidNonSlab(x, hb, z + 1, currentPostX, currentPostZ, currentData))
|
||||
|| (hc == h + 1 && isSolidNonSlab(x - 1, hc, z, currentPostX, currentPostZ, currentData))
|
||||
|| (hd == h + 1 && isSolidNonSlab(x, hd, z - 1, currentPostX, currentPostZ, currentData)))
|
||||
//@done
|
||||
{
|
||||
BlockData d = biome.getSlab().get(rng, x, h, z, getData());
|
||||
if (getDimension().isPostProcessingSlabs()) {
|
||||
//@builder
|
||||
if ((ha == h + 1 && isSolidNonSlab(x + 1, ha, z, currentPostX, currentPostZ, currentData))
|
||||
|| (hb == h + 1 && isSolidNonSlab(x, hb, z + 1, currentPostX, currentPostZ, currentData))
|
||||
|| (hc == h + 1 && isSolidNonSlab(x - 1, hc, z, currentPostX, currentPostZ, currentData))
|
||||
|| (hd == h + 1 && isSolidNonSlab(x, hd, z - 1, currentPostX, currentPostZ, currentData)))
|
||||
//@done
|
||||
{
|
||||
BlockData d = biome.getSlab().get(rng, x, h, z, getData());
|
||||
|
||||
if (d != null) {
|
||||
boolean cancel = B.isAir(d);
|
||||
if (d != null) {
|
||||
boolean cancel = B.isAir(d);
|
||||
|
||||
if (d.getMaterial().equals(Material.SNOW) && h + 1 <= getDimension().getFluidHeight()) {
|
||||
cancel = true;
|
||||
}
|
||||
if (d.getMaterial().equals(Material.SNOW) && h + 1 <= getDimension().getFluidHeight()) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
if (isSnowLayer(x, h, z, currentPostX, currentPostZ, currentData)) {
|
||||
cancel = true;
|
||||
}
|
||||
if (isSnowLayer(x, h, z, currentPostX, currentPostZ, currentData)) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
if (!cancel && isAirOrWater(x, h + 1, z, currentPostX, currentPostZ, currentData)) {
|
||||
setPostBlock(x, h + 1, z, d, currentPostX, currentPostZ, currentData);
|
||||
h++;
|
||||
if (!cancel && isAirOrWater(x, h + 1, z, currentPostX, currentPostZ, currentData)) {
|
||||
setPostBlock(x, h + 1, z, d, currentPostX, currentPostZ, currentData);
|
||||
h++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,6 +250,141 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
|
||||
setPostBlock(x, h + 1, z, AIR, currentPostX, currentPostZ, currentData);
|
||||
}
|
||||
}
|
||||
|
||||
if (getDimension().isPostProcessCaves()) {
|
||||
IrisBiome cave = getComplex().getCaveBiomeStream().get(x, z);
|
||||
|
||||
if (cave != null) {
|
||||
for (CaveResult i : ((IrisCaveModifier) getEngine().getCaveModifier()).genCaves(x, z, 0, 0, null)) {
|
||||
if (i.getCeiling() >= currentData.getMax2DParallelism() || i.getFloor() < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int f = i.getFloor();
|
||||
int fa = nearestCaveFloor(f, x + 1, z, currentPostX, currentPostZ, currentData);
|
||||
int fb = nearestCaveFloor(f, x, z + 1, currentPostX, currentPostZ, currentData);
|
||||
int fc = nearestCaveFloor(f, x - 1, z, currentPostX, currentPostZ, currentData);
|
||||
int fd = nearestCaveFloor(f, x, z - 1, currentPostX, currentPostZ, currentData);
|
||||
int c = i.getCeiling();
|
||||
int ca = nearestCaveCeiling(c, x + 1, z, currentPostX, currentPostZ, currentData);
|
||||
int cb = nearestCaveCeiling(c, x, z + 1, currentPostX, currentPostZ, currentData);
|
||||
int cc = nearestCaveCeiling(c, x - 1, z, currentPostX, currentPostZ, currentData);
|
||||
int cd = nearestCaveCeiling(c, x, z - 1, currentPostX, currentPostZ, currentData);
|
||||
|
||||
// Cave Nibs
|
||||
g = 0;
|
||||
g += fa == f - 1 ? 1 : 0;
|
||||
g += fb == f - 1 ? 1 : 0;
|
||||
g += fc == f - 1 ? 1 : 0;
|
||||
g += fd == f - 1 ? 1 : 0;
|
||||
|
||||
if (g >= 4) {
|
||||
BlockData bc = getPostBlock(x, f, z, currentPostX, currentPostZ, currentData);
|
||||
b = getPostBlock(x, f + 1, z, currentPostX, currentPostZ, currentData);
|
||||
Material m = bc.getMaterial();
|
||||
|
||||
if (m.isSolid()) {
|
||||
setPostBlock(x, f, z, b, currentPostX, currentPostZ, currentData);
|
||||
h--;
|
||||
}
|
||||
} else {
|
||||
// Cave Potholes
|
||||
g = 0;
|
||||
g += fa == f + 1 ? 1 : 0;
|
||||
g += fb == f + 1 ? 1 : 0;
|
||||
g += fc == f + 1 ? 1 : 0;
|
||||
g += fd == f + 1 ? 1 : 0;
|
||||
|
||||
if (g >= 4) {
|
||||
BlockData ba = getPostBlock(x, fa, z, currentPostX, currentPostZ, currentData);
|
||||
BlockData bb = getPostBlock(x, fb, z, currentPostX, currentPostZ, currentData);
|
||||
BlockData bc = getPostBlock(x, fc, z, currentPostX, currentPostZ, currentData);
|
||||
BlockData bd = getPostBlock(x, fd, z, currentPostX, currentPostZ, currentData);
|
||||
g = 0;
|
||||
g = B.isSolid(ba) ? g + 1 : g;
|
||||
g = B.isSolid(bb) ? g + 1 : g;
|
||||
g = B.isSolid(bc) ? g + 1 : g;
|
||||
g = B.isSolid(bd) ? g + 1 : g;
|
||||
|
||||
if (g >= 4) {
|
||||
setPostBlock(x, f + 1, z, getPostBlock(x, f, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData);
|
||||
h++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getDimension().isPostProcessingSlabs()) {
|
||||
//@builder
|
||||
if ((fa == f + 1 && isSolidNonSlab(x + 1, fa, z, currentPostX, currentPostZ, currentData))
|
||||
|| (fb == f + 1 && isSolidNonSlab(x, fb, z + 1, currentPostX, currentPostZ, currentData))
|
||||
|| (fc == f + 1 && isSolidNonSlab(x - 1, fc, z, currentPostX, currentPostZ, currentData))
|
||||
|| (fd == f + 1 && isSolidNonSlab(x, fd, z - 1, currentPostX, currentPostZ, currentData)))
|
||||
//@done
|
||||
{
|
||||
BlockData d = cave.getSlab().get(rng, x, f, z, getData());
|
||||
|
||||
if (d != null) {
|
||||
boolean cancel = B.isAir(d);
|
||||
|
||||
if (d.getMaterial().equals(Material.SNOW) && f + 1 <= getDimension().getFluidHeight()) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
if (isSnowLayer(x, f, z, currentPostX, currentPostZ, currentData)) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
if (!cancel && isAirOrWater(x, f + 1, z, currentPostX, currentPostZ, currentData)) {
|
||||
setPostBlock(x, f + 1, z, d, currentPostX, currentPostZ, currentData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@builder
|
||||
if ((ca == c - 1 && isSolidNonSlab(x + 1, ca, z, currentPostX, currentPostZ, currentData))
|
||||
|| (cb == c - 1 && isSolidNonSlab(x, cb, z + 1, currentPostX, currentPostZ, currentData))
|
||||
|| (cc == c - 1 && isSolidNonSlab(x - 1, cc, z, currentPostX, currentPostZ, currentData))
|
||||
|| (cd == c - 1 && isSolidNonSlab(x, cd, z - 1, currentPostX, currentPostZ, currentData)))
|
||||
//@done
|
||||
{
|
||||
BlockData d = cave.getSlab().get(rng, x, c, z, getData());
|
||||
|
||||
if (d != null) {
|
||||
boolean cancel = B.isAir(d);
|
||||
|
||||
if (!(d instanceof Slab)) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
if (isSnowLayer(x, c, z, currentPostX, currentPostZ, currentData)) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
if (!cancel && isAirOrWater(x, c, z, currentPostX, currentPostZ, currentData)) {
|
||||
try {
|
||||
Slab slab = (Slab) d.clone();
|
||||
slab.setType(Slab.Type.TOP);
|
||||
setPostBlock(x, c, z, slab, currentPostX, currentPostZ, currentData);
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
try {
|
||||
Slab slab = (Slab) d.clone();
|
||||
|
||||
synchronized (slab) {
|
||||
slab.setType(Slab.Type.TOP);
|
||||
setPostBlock(x, c, z, slab, currentPostX, currentPostZ, currentData);
|
||||
}
|
||||
} catch (Throwable ee) {
|
||||
Iris.reportError(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int nearestCaveFloor(int floor, int x, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
|
||||
|
||||
Reference in New Issue
Block a user