diff --git a/src/main/java/com/volmit/iris/engine/IrisEngine.java b/src/main/java/com/volmit/iris/engine/IrisEngine.java
index beccb012d..21660fccd 100644
--- a/src/main/java/com/volmit/iris/engine/IrisEngine.java
+++ b/src/main/java/com/volmit/iris/engine/IrisEngine.java
@@ -34,6 +34,7 @@ import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.modifier.IrisBodyModifier;
import com.volmit.iris.engine.modifier.IrisCarveModifier;
import com.volmit.iris.engine.modifier.IrisDepositModifier;
+import com.volmit.iris.engine.modifier.IrisPerfectionModifier;
import com.volmit.iris.engine.modifier.IrisPostModifier;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
@@ -186,6 +187,7 @@ public class IrisEngine implements Engine {
var post = new IrisPostModifier(this);
var deposit = new IrisDepositModifier(this);
var bodies = new IrisBodyModifier(this);
+ var perfection = new IrisPerfectionModifier(this);
registerStage((x, z, k, p, m) -> getMantle().generateMatter(x >> 4, z >> 4, m));
registerStage((x, z, k, p, m) -> terrain.actuate(x, z, k, m));
@@ -196,6 +198,7 @@ public class IrisEngine implements Engine {
registerStage((x, z, k, p, m) -> post.modify(x, z, k, m));
registerStage((x, z, k, p, m) -> deposit.modify(x, z, k, m));
registerStage((x, z, K, p, m) -> getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, K, m));
+ registerStage((x, z, k, p, m) -> perfection.modify(x, z, k, m));
}
@Override
diff --git a/src/main/java/com/volmit/iris/engine/modifier/IrisPerfectionModifier.java b/src/main/java/com/volmit/iris/engine/modifier/IrisPerfectionModifier.java
new file mode 100644
index 000000000..911cd7a79
--- /dev/null
+++ b/src/main/java/com/volmit/iris/engine/modifier/IrisPerfectionModifier.java
@@ -0,0 +1,167 @@
+/*
+ * 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 .
+ */
+
+package com.volmit.iris.engine.modifier;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.engine.framework.Engine;
+import com.volmit.iris.engine.framework.EngineAssignedModifier;
+import com.volmit.iris.engine.object.IrisBiome;
+import com.volmit.iris.util.data.B;
+import com.volmit.iris.util.data.HeightMap;
+import com.volmit.iris.util.format.Form;
+import com.volmit.iris.util.hunk.Hunk;
+import com.volmit.iris.util.math.RNG;
+import com.volmit.iris.util.scheduling.PrecisionStopwatch;
+import net.minecraft.world.level.block.TallSeagrassBlock;
+import org.bukkit.Material;
+import org.bukkit.block.data.Bisected;
+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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class IrisPerfectionModifier extends EngineAssignedModifier {
+ private static final BlockData AIR = B.get("AIR");
+ private static final BlockData WATER = B.get("WATER");
+ private final RNG rng;
+
+ public IrisPerfectionModifier(Engine engine) {
+ super(engine, "Perfection");
+ rng = new RNG(getEngine().getSeedManager().getPost());
+ }
+
+ @Override
+ public void onModify(int x, int z, Hunk output, boolean multicore) {
+ PrecisionStopwatch p = PrecisionStopwatch.start();
+ boolean changed = true;
+ int passes = 0;
+ int changes = 0;
+ List surfaces = new ArrayList<>();
+ List ceilings = new ArrayList<>();
+
+ while(changed)
+ {
+ passes++;
+ changed = false;
+ for(int i = 0; i < 16; i++)
+ {
+ for(int j = 0; j < 16; j++)
+ {
+ surfaces.clear();
+ ceilings.clear();
+ int top = getHeight(output, i, j);
+ boolean inside = true;
+ surfaces.add(top);
+
+ for(int k = top; k >= 0; k--)
+ {
+ BlockData b = output.get(i, k, j);
+ boolean now = b != null && !(B.isAir(b) || B.isFluid(b));
+
+ if(now != inside)
+ {
+ inside = now;
+
+ if(inside)
+ {
+ surfaces.add(k);
+ }
+
+ else
+ {
+ ceilings.add(k+1);
+ }
+ }
+ }
+
+ for(int k : surfaces)
+ {
+ BlockData tip = output.get(i, k, j);
+
+ if(tip == null)
+ {
+ continue;
+ }
+
+ boolean remove = false;
+ boolean remove2 = false;
+
+ if(B.isDecorant(tip))
+ {
+ BlockData bel = output.get(i, k-1, j);
+
+ if(bel == null)
+ {
+ remove = true;
+ }
+
+ else if(!B.canPlaceOnto(tip.getMaterial(), bel.getMaterial()))
+ {
+ remove = true;
+ }
+
+ else if(bel instanceof Bisected)
+ {
+ BlockData bb = output.get(i, k-2, j);
+ if(bb == null || !B.canPlaceOnto(bel.getMaterial(), bb.getMaterial()))
+ {
+ remove = true;
+ remove2 = true;
+ }
+ }
+
+ if(remove)
+ {
+ changed = true;
+ changes++;
+ output.set(i, k, j, AIR);
+
+ if(remove2)
+ {
+ changes++;
+ output.set(i, k-1, j, AIR);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ getEngine().getMetrics().getPerfection().put(p.getMilliseconds());
+ }
+
+ private int getHeight(Hunk output, int x, int z) {
+ for(int i = output.getHeight()-1; i >= 0; i--)
+ {
+ BlockData b = output.get(x, i, z);
+
+ if(b != null && !B.isAir(b) && !B.isFluid(b))
+ {
+ return i;
+ }
+ }
+
+ return 0;
+ }
+}