Restructure Packages (read commit description)

There are now three root packages
- Engine: Generator & JSON Scaffolding
- Core: Managers, Commands, NMS
- Util: Random utility packages
This commit is contained in:
Daniel Mills
2021-07-16 01:46:22 -04:00
parent eef548f6a1
commit c984eb9b8c
423 changed files with 1001 additions and 1977 deletions

View File

@@ -0,0 +1,238 @@
/*
* 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.noise.FastNoiseDouble;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisCaveLayer;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.hunk.Hunk;
import com.volmit.iris.util.*;
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().getSeed() + 28934555);
gg = new FastNoiseDouble(324895L * rng.nextParallelRNG(49678).imax());
}
@Override
public void onModify(int x, int z, Hunk<BlockData> a) {
if (!getDimension().isCaves()) {
return;
}
PrecisionStopwatch p = PrecisionStopwatch.start();
for (int i = 0; i < a.getWidth(); i++) {
for (int j = 0; j < a.getDepth(); j++) {
KList<CaveResult> caves = genCaves(x + i, z + j, i, j, a);
int he = (int) Math.round(getComplex().getHeightStream().get(x + i, z + j));
if (caves != null && caves.isNotEmpty()) {
IrisBiome cave = getComplex().getCaveBiomeStream().get(x + i, 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 + i, z + j, rng, cl.getFloor(), cl.getFloor(), getData(), getComplex());
KList<BlockData> ceiling = cave.generateLayers(x + i + 656, z + j - 656, rng,
he - cl.getCeiling(),
he - cl.getCeiling(), getData(), getComplex());
for (int g = 0; g < floor.size(); g++) {
a.set(i, cl.getFloor() - g, j, floor.get(g));
}
for (int g = ceiling.size() - 1; g > 0; g--) {
a.set(i, cl.getCeiling() + g, j, ceiling.get(g));
}
}
}
}
}
getEngine().getMetrics().getCave().put(p.getMilliseconds());
}
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, wxx, wzz);
double wz = wzz + layer.getHorizontalSlope().get(rng, -wzz, -wxx);
double baseWidth = (14 * scale);
double distanceCheck = 0.0132 * baseWidth;
double distanceTake = 0.0022 * baseWidth;
double caveHeightNoise = layer.getVerticalSlope().get(rng, 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);
}
}

View File

@@ -0,0 +1,138 @@
/*
* 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.object.IrisBiome;
import com.volmit.iris.engine.object.IrisDepositGenerator;
import com.volmit.iris.engine.object.IrisObject;
import com.volmit.iris.engine.object.IrisRegion;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.hunk.Hunk;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
private final RNG rng;
public IrisDepositModifier(Engine engine) {
super(engine, "Deposit");
rng = new RNG(getEngine().getWorld().getSeed() + 12938).nextParallelRNG(28348777);
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
PrecisionStopwatch p = PrecisionStopwatch.start();
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16));
getEngine().getMetrics().getDeposit().put(p.getMilliseconds());
}
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z) {
RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z);
IrisRegion region = getComplex().getRegionStream().get((x * 16) + 7, (z * 16) + 7);
IrisBiome biome = getComplex().getTrueBiomeStream().get((x * 16) + 7, (z * 16) + 7);
for (IrisDepositGenerator k : getDimension().getDeposits()) {
generate(k, terrain, ro, x, z, false);
}
for (IrisDepositGenerator k : region.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
generate(k, terrain, ro, x, z, false);
}
}
for (IrisDepositGenerator k : biome.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
generate(k, terrain, ro, x, z, false);
}
}
}
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe) {
generate(k, data, rng, cx, cz, safe, null);
}
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, HeightMap he) {
for (int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
IrisObject clump = k.getClump(rng, getData());
int af = (int) Math.ceil(clump.getW() / 2D);
int bf = (int) Math.floor(16D - (clump.getW() / 2D));
if (af > bf || af < 0 || bf > 15 || af > 15 || bf < 0) {
af = 6;
bf = 9;
}
int x = rng.i(af, bf);
int z = rng.i(af, bf);
int height = (he != null ? he.getHeight((cx << 4) + x, (cz << 4) + z) : (int) (Math.round(
getComplex().getHeightStream().get((cx << 4) + x, (cz << 4) + z)
))) - 7;
if (height <= 0) {
return;
}
int i = Math.max(0, k.getMinHeight());
// TODO: WARNING HEIGHT
int a = Math.min(height, Math.min(256, k.getMaxHeight()));
if (i >= a) {
return;
}
int h = rng.i(i, a);
if (h > k.getMaxHeight() || h < k.getMinHeight() || h > height - 2) {
return;
}
for (BlockVector j : clump.getBlocks().keySet()) {
int nx = j.getBlockX() + x;
int ny = j.getBlockY() + h;
int nz = j.getBlockZ() + z;
if (ny > height || nx > 15 || nx < 0 || ny > 255 || ny < 0 || nz < 0 || nz > 15) {
continue;
}
boolean allow = false;
BlockData b = data.get(nx, ny, nz);
if (b != null) {
for (BlockData f : getDimension().getRockPalette().getBlockData(getData())) {
if (f.getMaterial().equals(b.getMaterial())) {
allow = true;
break;
}
}
}
if (allow) {
data.set(nx, ny, nz, clump.getBlocks().get(j));
}
}
}
}
}

View File

@@ -0,0 +1,481 @@
/*
* 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.Iris;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.hunk.Hunk;
import com.volmit.iris.engine.parallel.BurstExecutor;
import com.volmit.iris.engine.parallel.MultiBurst;
import com.volmit.iris.util.B;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Levelled;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Slab;
public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
private static final BlockData AIR = B.get("CAVE_AIR");
private static final BlockData WATER = B.get("WATER");
private final RNG rng;
public IrisPostModifier(Engine engine) {
super(engine, "Post");
rng = new RNG(getEngine().getWorld().getSeed() + 12938).nextParallelRNG(28348777);
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
PrecisionStopwatch p = PrecisionStopwatch.start();
BurstExecutor b = MultiBurst.burst.burst(output.getWidth() * output.getDepth());
int i, j;
for (i = 0; i < output.getWidth(); i++) {
int ii = i;
for (j = 0; j < output.getDepth(); j++) {
int jj = j;
b.queue(() -> post(ii, jj, output, ii + x, jj + z));
}
}
b.complete();
getEngine().getMetrics().getPost().put(p.getMilliseconds());
}
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
private void post(int currentPostX, int currentPostZ, Hunk<BlockData> currentData, int x, int z) {
int h = getFramework().getEngineParallax().trueHeight(x, z);
int ha = getFramework().getEngineParallax().trueHeight(x + 1, z);
int hb = getFramework().getEngineParallax().trueHeight(x, z + 1);
int hc = getFramework().getEngineParallax().trueHeight(x - 1, z);
int hd = getFramework().getEngineParallax().trueHeight(x, z - 1);
// Floating Nibs
int g = 0;
if (h < 1) {
return;
}
g += ha < h - 1 ? 1 : 0;
g += hb < h - 1 ? 1 : 0;
g += hc < h - 1 ? 1 : 0;
g += hd < h - 1 ? 1 : 0;
if (g == 4 && isAir(x, h - 1, z, currentPostX, currentPostZ, currentData)) {
setPostBlock(x, h, z, AIR, currentPostX, currentPostZ, currentData);
for (int i = h - 1; i > 0; i--) {
if (!isAir(x, i, z, currentPostX, currentPostZ, currentData)) {
h = i;
break;
}
}
}
// Nibs
g = 0;
g += ha == h - 1 ? 1 : 0;
g += hb == h - 1 ? 1 : 0;
g += hc == h - 1 ? 1 : 0;
g += hd == h - 1 ? 1 : 0;
if (g >= 4) {
BlockData bc = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData);
BlockData b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData);
Material m = bc.getMaterial();
if ((b.getMaterial().isOccluding() && b.getMaterial().isSolid())) {
if (m.isSolid()) {
setPostBlock(x, h, z, b, currentPostX, currentPostZ, currentData);
h--;
}
}
} else {
// Potholes
g = 0;
g += ha == h + 1 ? 1 : 0;
g += hb == h + 1 ? 1 : 0;
g += hc == h + 1 ? 1 : 0;
g += hd == h + 1 ? 1 : 0;
if (g >= 4) {
BlockData ba = getPostBlock(x, ha, z, currentPostX, currentPostZ, currentData);
BlockData bb = getPostBlock(x, hb, z, currentPostX, currentPostZ, currentData);
BlockData bc = getPostBlock(x, hc, z, currentPostX, currentPostZ, currentData);
BlockData bd = getPostBlock(x, hd, 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 >= 3) {
setPostBlock(x, h + 1, z, getPostBlock(x, h, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData);
h++;
}
}
}
// Wall Patcher
IrisBiome biome = getComplex().getTrueBiomeStream().get(x, z);
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());
if (d != null) {
if (isAirOrWater(x, i, z, currentPostX, currentPostZ, currentData)) {
if (brokeGround) {
break;
}
continue;
}
setPostBlock(x, i, z, d, currentPostX, currentPostZ, currentData);
brokeGround = true;
}
}
}
}
}
// Slab
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.getMaterial().equals(Material.SNOW) && h + 1 <= getDimension().getFluidHeight()) {
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++;
}
}
}
}
// Waterlogging
BlockData b = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData);
if (b instanceof Waterlogged) {
Waterlogged ww = (Waterlogged) b.clone();
boolean w = false;
if (h <= getDimension().getFluidHeight() + 1) {
if (isWaterOrWaterlogged(x, h + 1, z, currentPostX, currentPostZ, currentData)) {
w = true;
} else if ((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData))) {
w = true;
}
}
if (w != ww.isWaterlogged()) {
ww.setWaterlogged(w);
setPostBlock(x, h, z, ww, currentPostX, currentPostZ, currentData);
}
} else if (b.getMaterial().equals(Material.AIR) && h <= getDimension().getFluidHeight()) {
if ((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData))) {
setPostBlock(x, h, z, WATER, currentPostX, currentPostZ, currentData);
}
}
// Foliage
b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData);
if (B.isFoliage(b) || b.getMaterial().equals(Material.DEAD_BUSH)) {
Material onto = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).getMaterial();
if (!B.canPlaceOnto(b.getMaterial(), onto)) {
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) getFramework().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) {
if (floor >= currentData.getHeight()) {
return currentData.getHeight() - 1;
}
if (B.isAir(getPostBlock(x, floor, z, currentPostX, currentPostZ, currentData))) {
if (B.isAir(getPostBlock(x, floor - 1, z, currentPostX, currentPostZ, currentData))) {
return floor - 2;
}
return floor - 1;
} else {
if (!B.isAir(getPostBlock(x, floor + 1, z, currentPostX, currentPostZ, currentData))) {
if (!B.isAir(getPostBlock(x, floor + 2, z, currentPostX, currentPostZ, currentData))) {
return floor + 2;
}
return floor + 1;
}
return floor;
}
}
private int nearestCaveCeiling(int ceiling, int x, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
if (ceiling >= currentData.getHeight()) {
return currentData.getHeight() - 1;
}
if (B.isAir(getPostBlock(x, ceiling, z, currentPostX, currentPostZ, currentData))) {
if (B.isAir(getPostBlock(x, ceiling + 1, z, currentPostX, currentPostZ, currentData))) {
return ceiling + 2;
}
return ceiling + 1;
} else {
if (!B.isAir(getPostBlock(x, ceiling - 1, z, currentPostX, currentPostZ, currentData))) {
if (!B.isAir(getPostBlock(x, ceiling - 2, z, currentPostX, currentPostZ, currentData))) {
return ceiling - 2;
}
return ceiling - 1;
}
return ceiling;
}
}
public boolean isAir(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.AIR) || d.getMaterial().equals(Material.CAVE_AIR);
}
public boolean hasGravity(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.SAND) || d.getMaterial().equals(Material.RED_SAND) || d.getMaterial().equals(Material.BLACK_CONCRETE_POWDER) || d.getMaterial().equals(Material.BLUE_CONCRETE_POWDER) || d.getMaterial().equals(Material.BROWN_CONCRETE_POWDER) || d.getMaterial().equals(Material.CYAN_CONCRETE_POWDER) || d.getMaterial().equals(Material.GRAY_CONCRETE_POWDER) || d.getMaterial().equals(Material.GREEN_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIGHT_BLUE_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIGHT_GRAY_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIME_CONCRETE_POWDER) || d.getMaterial().equals(Material.MAGENTA_CONCRETE_POWDER) || d.getMaterial().equals(Material.ORANGE_CONCRETE_POWDER) || d.getMaterial().equals(Material.PINK_CONCRETE_POWDER) || d.getMaterial().equals(Material.PURPLE_CONCRETE_POWDER) || d.getMaterial().equals(Material.RED_CONCRETE_POWDER) || d.getMaterial().equals(Material.WHITE_CONCRETE_POWDER) || d.getMaterial().equals(Material.YELLOW_CONCRETE_POWDER);
}
public boolean isSolid(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().isSolid();
}
public boolean isSolidNonSlab(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().isSolid() && !(d instanceof Slab);
}
public boolean isAirOrWater(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.WATER) || d.getMaterial().equals(Material.AIR) || d.getMaterial().equals(Material.CAVE_AIR);
}
public boolean isSlab(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d instanceof Slab;
}
public boolean isSnowLayer(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.SNOW);
}
public boolean isWater(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.WATER);
}
public boolean isWaterOrWaterlogged(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.WATER) || (d instanceof Waterlogged && ((Waterlogged) d).isWaterlogged());
}
public boolean isLiquid(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d instanceof Levelled;
}
public void setPostBlock(int x, int y, int z, BlockData d, int currentPostX, int currentPostZ, Hunk<BlockData> currentData) {
if (y < currentData.getHeight()) {
currentData.set(x & 15, y, z & 15, d);
}
}
public BlockData getPostBlock(int x, int y, int z, int cpx, int cpz, Hunk<BlockData> h) {
BlockData b = h.getClosest(x & 15, y, z & 15);
return b == null ? AIR : b;
}
}

View File

@@ -0,0 +1,281 @@
/*
* 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.noise.CNG;
import com.volmit.iris.engine.object.NoiseStyle;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.hunk.Hunk;
import com.volmit.iris.util.*;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
@SuppressWarnings("ALL")
public class IrisRavineModifier extends EngineAssignedModifier<BlockData> {
private static final BlockData CAVE_AIR = B.get("CAVE_AIR");
private static final BlockData LAVA = B.get("LAVA");
private final CNG cng;
private final RNG rng;
public IrisRavineModifier(Engine engine) {
super(engine, "Ravine");
rng = new RNG(getEngine().getWorld().getSeed()).nextParallelRNG(29596878);
cng = NoiseStyle.IRIS_THICK.create(rng);
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
if (!getDimension().isRavines()) {
return;
}
PrecisionStopwatch p = PrecisionStopwatch.start();
generateRavines(rng, Math.floorDiv(x, 16), Math.floorDiv(z, 16), output);
getEngine().getMetrics().getRavine().put(p.getMilliseconds());
}
private void set(Hunk<BlockData> pos, int x, int y, int z, BlockData b) {
pos.set(x, y, z, b);
}
private BlockData get(Hunk<BlockData> pos, int x, int y, int z) {
BlockData bb = pos.get(x, y, z);
if (bb == null) {
bb = CAVE_AIR;
}
return bb;
}
private BlockData getSurfaceBlock(int n6, int i, RNG rmg) {
return getComplex().getTrueBiomeStream().get(n6, i).getSurfaceBlock(n6, i, rmg, getData());
}
private final float[] ravineCache = new float[1024];
private void doRavine(long seed, int tx, int tz, ChunkPosition pos, double sx, double sy, double sz, float f, float f2, float f3, @SuppressWarnings("SameParameterValue") int n3, @SuppressWarnings("SameParameterValue") int n4, @SuppressWarnings("SameParameterValue") double d4, RNG bbx, Hunk<BlockData> terrain) {
int n5;
RNG random = new RNG(seed);
double x = tx * 16 + 8;
double z = tz * 16 + 8;
float f4 = 0.0f;
float f5 = 0.0f;
if (n4 <= 0) {
n5 = 8 * 16 - 16;
n4 = n5 - random.nextInt(n5 / 4);
}
n5 = 0;
if (n3 == -1) {
n3 = n4 / 2;
n5 = 1;
}
float f6 = 1.0f;
// TODO: WARNING HEIGHT
for (int i = 0; i < 256; ++i) {
if (i == 0 || random.nextInt(getDimension().getRavineRibRarity()) == 0) {
f6 = 1.0f + random.nextFloat() * random.nextFloat() * 1.0f;
}
this.ravineCache[i] = f6 * f6;
}
while (n3 < n4) {
double d7 = 1.5 + (double) (MathHelper.sin((float) n3 * 3.1415927f / (float) n4) * f * 1.0f);
double d8 = d7 * d4;
d7 *= (double) random.nextFloat() * 0.25 + 0.75;
d8 *= (double) random.nextFloat() * 0.25 + 0.75;
float f7 = MathHelper.cos(f3);
float f8 = MathHelper.sin(f3);
sx = sx + (double) (MathHelper.cos(f2) * f7);
sy += f8;
sz += MathHelper.sin(f2) * f7;
f3 *= 0.7f;
f3 += f5 * 0.05f;
f2 += f4 * 0.05f;
f5 *= 0.8f;
f4 *= 0.5f;
f5 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 2.0f;
f4 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 4.0f;
if (n5 != 0 || random.nextInt(4) != 0) {
double d9 = sx - x;
double d10 = sz - z;
double d11 = n4 - n3;
double d12 = f + 2.0f + 16.0f;
if (d9 * d9 + d10 * d10 - d11 * d11 > d12 * d12) {
return;
}
if (sx >= x - 16.0 - d7 * 2.0 && sz >= z - 16.0 - d7 * 2.0 && sx <= x + 16.0 + d7 * 2.0 && sz <= z + 16.0 + d7 * 2.0) {
int n6;
int n7 = MathHelper.floor(sx - d7) - tx * 16 - 1;
int n8 = MathHelper.floor(sx + d7) - tx * 16 + 1;
int n9 = MathHelper.floor(sy - d8) - 1;
int n10 = MathHelper.floor(sy + d8) + 1;
int n11 = MathHelper.floor(sz - d7) - tz * 16 - 1;
int n12 = MathHelper.floor(sz + d7) - tz * 16 + 1;
if (n7 < 0) {
n7 = 0;
}
if (n8 > 16) {
n8 = 16;
}
if (n9 < 1) {
n9 = 1;
}
if (n10 > 248) {
n10 = 248;
}
if (n11 < 0) {
n11 = 0;
}
if (n12 > 16) {
n12 = 16;
}
boolean bl = false;
for (int i = n7; !bl && i < n8; ++i) {
for (n6 = n11; !bl && n6 < n12; ++n6) {
for (int j = n10 + 1; !bl && j >= n9 - 1; --j) {
// TODO: WARNING HEIGHT
if (j < 0 || j >= 256) {
continue;
}
BlockData bb = get(terrain, i, j, n6);
if (B.isWater(bb)) {
bl = true;
}
if (j == n9 - 1 || i == n7 || i == n8 - 1 || n6 == n11 || n6 == n12 - 1) {
continue;
}
j = n9;
}
}
}
if (!bl) {
BlockPosition bps = new BlockPosition(0, 0, 0);
for (n6 = n7; n6 < n8; ++n6) {
double d13 = ((double) (n6 + tx * 16) + 0.5 - sx) / d7;
for (int i = n11; i < n12; ++i) {
double d14 = ((double) (i + tz * 16) + 0.5 - sz) / d7;
boolean bl2 = false;
if (d13 * d13 + d14 * d14 >= 1.0) {
continue;
}
for (int j = n10; j > n9; --j) {
double d15 = ((double) (j - 1) + 0.5 - sy) / d8;
if ((d13 * d13 + d14 * d14) * (double) this.ravineCache[j - 1] + d15 * d15 / 6.0 >= 1.0) {
continue;
}
BlockData blockData = get(terrain, n6, j, i);
if (isSurface(blockData)) {
bl2 = true;
}
if (j - 1 < 10) {
set(terrain, n6, j, i, LAVA);
continue;
}
set(terrain, n6, j, i, CAVE_AIR);
if (!bl2 || !isDirt(get(terrain, n6, j - 1, i))) {
continue;
}
cSet(bps, n6 + tx * 16, 0, i + tz * 16);
set(terrain, n6, j - 1, i, getSurfaceBlock(n6, i, rng));
}
}
}
if (n5 != 0) {
break;
}
}
}
}
++n3;
}
}
private BlockPosition cSet(BlockPosition bb, double var0, @SuppressWarnings("SameParameterValue") double var2, double var4) {
bb.setX(MathHelper.floor(var0));
bb.setY(MathHelper.floor(var2));
bb.setZ(MathHelper.floor(var4));
return bb;
}
private boolean isDirt(BlockData d) {
//@builder
Material m = d.getMaterial();
return m.equals(Material.DIRT) ||
m.equals(Material.COARSE_DIRT) ||
m.equals(Material.SAND);
//@done
}
private boolean isSurface(BlockData d) {
//@builder
Material m = d.getMaterial();
return m.equals(Material.GRASS_BLOCK) ||
m.equals(Material.DIRT) ||
m.equals(Material.COARSE_DIRT) ||
m.equals(Material.PODZOL) ||
m.equals(Material.SAND);
//@done
}
public void genRavines(int n, int n2, ChunkPosition chunkSnapshot, RNG bbb, Hunk<BlockData> terrain) {
RNG b = this.rng.nextParallelRNG(21949666);
RNG bx = this.rng.nextParallelRNG(6676121);
long l = b.nextLong();
long l2 = b.nextLong();
for (int i = n - 8; i <= n + 8; ++i) {
for (int j = n2 - 8; j <= n2 + 8; ++j) {
long l3 = (long) i * l;
long l4 = (long) j * l2;
bx = this.rng.nextParallelRNG((int) (l3 ^ l4 ^ 6676121));
doRavines(i, j, n, n2, chunkSnapshot, bx, terrain);
}
}
}
private void doRavines(int tx, int tz, int sx, int sz, ChunkPosition chunkSnapshot, RNG b, Hunk<BlockData> terrain) {
if (b.nextInt(getDimension().getRavineRarity()) != 0) {
return;
}
double x = tx * 16 + b.nextInt(16);
double d2 = b.nextInt(b.nextInt(40) + 8) + 20;
double z = tz * 16 + b.nextInt(16);
int n5 = 1;
for (int i = 0; i < n5; ++i) {
float f = b.nextFloat() * 3.1415927f * 2.0f;
float f2 = (b.nextFloat() - 0.5f) * 2.0f / 8.0f;
float f3 = (b.nextFloat() * 2.0f + b.nextFloat()) * 2.0f;
this.doRavine(b.nextLong(), sx, sz, chunkSnapshot, x, d2, z, f3, f, f2, 0, 0, 3.0, b, terrain);
}
}
public void generateRavines(RNG nextParallelRNG, int x, int z, Hunk<BlockData> terrain) {
genRavines(x, z, new ChunkPosition(x, z), nextParallelRNG.nextParallelRNG(x).nextParallelRNG(z), terrain);
}
}