-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
704 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.dfsek.terra.api.world.carving; | ||
|
||
import com.dfsek.terra.api.math.vector.Vector3; | ||
import com.dfsek.terra.api.platform.world.World; | ||
import net.jafama.FastMath; | ||
|
||
import java.util.Random; | ||
import java.util.function.BiConsumer; | ||
|
||
public abstract class Carver { | ||
private final int minY; | ||
private final int maxY; | ||
private final double sixtyFourSq = FastMath.pow(64, 2); | ||
private int carvingRadius = 4; | ||
|
||
public Carver(int minY, int maxY) { | ||
this.minY = minY; | ||
this.maxY = maxY; | ||
} | ||
|
||
public abstract void carve(int chunkX, int chunkZ, World w, BiConsumer<Vector3, CarvingType> consumer); | ||
|
||
public int getCarvingRadius() { | ||
return carvingRadius; | ||
} | ||
|
||
public void setCarvingRadius(int carvingRadius) { | ||
this.carvingRadius = carvingRadius; | ||
} | ||
|
||
public abstract Worm getWorm(long seed, Vector3 l); | ||
|
||
public abstract boolean isChunkCarved(World w, int chunkX, int chunkZ, Random r); | ||
|
||
public enum CarvingType { | ||
CENTER, WALL, TOP, BOTTOM | ||
} | ||
} |
119 changes: 119 additions & 0 deletions
119
common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package com.dfsek.terra.api.world.carving; | ||
|
||
import com.dfsek.terra.api.math.vector.Vector3; | ||
import net.jafama.FastMath; | ||
|
||
import java.util.Random; | ||
import java.util.function.BiConsumer; | ||
|
||
public abstract class Worm { | ||
private final Random r; | ||
private final Vector3 origin; | ||
private final Vector3 running; | ||
private final int length; | ||
private int topCut = 0; | ||
private int bottomCut = 0; | ||
private int[] radius = new int[] {0, 0, 0}; | ||
|
||
public Worm(int length, Random r, Vector3 origin) { | ||
this.r = r; | ||
this.length = length; | ||
this.origin = origin; | ||
this.running = origin; | ||
} | ||
|
||
public void setBottomCut(int bottomCut) { | ||
this.bottomCut = bottomCut; | ||
} | ||
|
||
public void setTopCut(int topCut) { | ||
this.topCut = topCut; | ||
} | ||
|
||
public Vector3 getOrigin() { | ||
return origin; | ||
} | ||
|
||
public int getLength() { | ||
return length; | ||
} | ||
|
||
public Vector3 getRunning() { | ||
return running; | ||
} | ||
|
||
public WormPoint getPoint() { | ||
return new WormPoint(running, radius, topCut, bottomCut); | ||
} | ||
|
||
public int[] getRadius() { | ||
return radius; | ||
} | ||
|
||
public void setRadius(int[] radius) { | ||
this.radius = radius; | ||
} | ||
|
||
public Random getRandom() { | ||
return r; | ||
} | ||
|
||
public abstract void step(); | ||
|
||
public static class WormPoint { | ||
private final Vector3 origin; | ||
private final int topCut; | ||
private final int bottomCut; | ||
private final int[] rad; | ||
|
||
public WormPoint(Vector3 origin, int[] rad, int topCut, int bottomCut) { | ||
this.origin = origin; | ||
this.rad = rad; | ||
this.topCut = topCut; | ||
this.bottomCut = bottomCut; | ||
} | ||
|
||
private static double ellipseEquation(int x, int y, int z, double xr, double yr, double zr) { | ||
return (FastMath.pow2(x) / FastMath.pow2(xr + 0.5D)) + (FastMath.pow2(y) / FastMath.pow2(yr + 0.5D)) + (FastMath.pow2(z) / FastMath.pow2(zr + 0.5D)); | ||
} | ||
|
||
public Vector3 getOrigin() { | ||
return origin; | ||
} | ||
|
||
public int getRadius(int index) { | ||
return rad[index]; | ||
} | ||
|
||
public void carve(int chunkX, int chunkZ, BiConsumer<Vector3, Carver.CarvingType> consumer) { | ||
int xRad = getRadius(0); | ||
int yRad = getRadius(1); | ||
int zRad = getRadius(2); | ||
int originX = (chunkX << 4); | ||
int originZ = (chunkZ << 4); | ||
for(int x = -xRad - 1; x <= xRad + 1; x++) { | ||
if(!(FastMath.floorDiv(origin.getBlockX() + x, 16) == chunkX)) continue; | ||
for(int z = -zRad - 1; z <= zRad + 1; z++) { | ||
if(!(FastMath.floorDiv(origin.getBlockZ() + z, 16) == chunkZ)) continue; | ||
for(int y = -yRad - 1; y <= yRad + 1; y++) { | ||
Vector3 position = origin.clone().add(new Vector3(x, y, z)); | ||
if(position.getY() < 0 || position.getY() > 255) continue; | ||
double eq = ellipseEquation(x, y, z, xRad, yRad, zRad); | ||
if(eq <= 1 && | ||
y >= -yRad - 1 + bottomCut && y <= yRad + 1 - topCut) { | ||
consumer.accept(new Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), Carver.CarvingType.CENTER); | ||
} else if(eq <= 1.5) { | ||
Carver.CarvingType type = Carver.CarvingType.WALL; | ||
if(y <= -yRad - 1 + bottomCut) { | ||
type = Carver.CarvingType.BOTTOM; | ||
} else if(y >= yRad + 1 - topCut) { | ||
type = Carver.CarvingType.TOP; | ||
} | ||
consumer.accept(new Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), type); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
common/src/main/java/com/dfsek/terra/carving/CarverCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.dfsek.terra.carving; | ||
|
||
import com.dfsek.terra.api.core.TerraPlugin; | ||
import com.dfsek.terra.api.math.MathUtil; | ||
import com.dfsek.terra.api.math.vector.Vector3; | ||
import com.dfsek.terra.api.platform.world.World; | ||
import com.dfsek.terra.api.util.FastRandom; | ||
import com.dfsek.terra.api.util.GlueList; | ||
import com.dfsek.terra.api.world.carving.Worm; | ||
import com.dfsek.terra.biome.TerraBiome; | ||
import com.dfsek.terra.biome.UserDefinedBiome; | ||
import com.dfsek.terra.biome.provider.BiomeProvider; | ||
import com.google.common.cache.CacheBuilder; | ||
import com.google.common.cache.CacheLoader; | ||
import com.google.common.cache.LoadingCache; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.util.List; | ||
import java.util.Random; | ||
|
||
public class CarverCache { | ||
|
||
private final LoadingCache<Long, List<Worm.WormPoint>> cache; | ||
private final UserDefinedCarver carver; | ||
|
||
public CarverCache(World w, TerraPlugin main, UserDefinedCarver carver) { | ||
this.carver = carver; | ||
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getCarverCacheSize()) | ||
.build(new CacheLoader<Long, List<Worm.WormPoint>>() { | ||
@Override | ||
public List<Worm.WormPoint> load(@NotNull Long key) { | ||
int chunkX = (int) (key >> 32); | ||
int chunkZ = (int) key.longValue(); | ||
BiomeProvider provider = main.getWorld(w).getBiomeProvider(); | ||
if(CarverCache.this.carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + CarverCache.this.carver.hashCode())))) { | ||
long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed()); | ||
CarverCache.this.carver.getSeedVar().setValue(seed); | ||
Random r = new FastRandom(seed); | ||
Worm carving = CarverCache.this.carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), CarverCache.this.carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16))); | ||
List<Worm.WormPoint> points = new GlueList<>(); | ||
for(int i = 0; i < carving.getLength(); i++) { | ||
carving.step(); | ||
TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w)); | ||
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in | ||
return new GlueList<>(); | ||
} | ||
points.add(carving.getPoint()); | ||
} | ||
return points; | ||
} | ||
return new GlueList<>(); | ||
} | ||
}); | ||
} | ||
|
||
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ) { | ||
return cache.getUnchecked(MathUtil.squash(chunkX, chunkZ)); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
common/src/main/java/com/dfsek/terra/carving/CarverPalette.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.dfsek.terra.carving; | ||
|
||
import com.dfsek.terra.api.math.ProbabilityCollection; | ||
import com.dfsek.terra.api.platform.block.BlockData; | ||
import com.dfsek.terra.api.platform.block.MaterialData; | ||
import com.dfsek.terra.util.MaterialSet; | ||
|
||
import java.util.Map; | ||
import java.util.TreeMap; | ||
|
||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) | ||
public class CarverPalette { | ||
private final boolean blacklist; | ||
private final MaterialSet replace; | ||
private final TreeMap<Integer, ProbabilityCollection<BlockData>> map = new TreeMap<>(); | ||
private ProbabilityCollection<BlockData>[] layers; | ||
|
||
public CarverPalette(MaterialSet replaceable, boolean blacklist) { | ||
this.blacklist = blacklist; | ||
this.replace = replaceable; | ||
} | ||
|
||
public CarverPalette add(ProbabilityCollection<BlockData> collection, int y) { | ||
map.put(y, collection); | ||
return this; | ||
} | ||
|
||
public ProbabilityCollection<BlockData> get(int y) { | ||
return layers[y]; | ||
} | ||
|
||
public boolean canReplace(MaterialData material) { | ||
return blacklist != replace.contains(material); | ||
} | ||
|
||
/** | ||
* Build the palette to an array. | ||
*/ | ||
public void build() { | ||
int size = map.lastKey() + 1; | ||
layers = new ProbabilityCollection[size]; | ||
for(int y = 0; y < size; y++) { | ||
ProbabilityCollection<BlockData> d = null; | ||
for(Map.Entry<Integer, ProbabilityCollection<BlockData>> e : map.entrySet()) { | ||
if(e.getKey() >= y) { | ||
d = e.getValue(); | ||
break; | ||
} | ||
} | ||
if(d == null) throw new IllegalArgumentException("Null collection at Y=" + y); | ||
layers[y] = d; | ||
} | ||
} | ||
} |
Oops, something went wrong.