mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-04 00:45:57 +00:00
merge ovre-v2 into ore(v1)
This commit is contained in:
parent
9292d3de17
commit
6f08908bb4
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020-2021 Polyhedral Development
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,3 +0,0 @@
|
|||||||
# config-ore-v2
|
|
||||||
|
|
||||||
Registers the default configuration for Terra Ores, `ORE`.
|
|
@ -1,5 +0,0 @@
|
|||||||
version = version("1.0.0")
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnlyApi(project(":common:addons:manifest-addon-loader"))
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020-2021 Polyhedral Development
|
|
||||||
*
|
|
||||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
|
||||||
* reference the LICENSE file in this module's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.addons.ore.v2;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
|
||||||
import com.dfsek.terra.api.Platform;
|
|
||||||
import com.dfsek.terra.api.addon.BaseAddon;
|
|
||||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
|
||||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
|
||||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
|
||||||
|
|
||||||
|
|
||||||
public class OreAddon implements AddonInitializer {
|
|
||||||
@Inject
|
|
||||||
private Platform platform;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private BaseAddon addon;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize() {
|
|
||||||
platform.getEventManager()
|
|
||||||
.getHandler(FunctionalEventHandler.class)
|
|
||||||
.register(addon, ConfigPackPreLoadEvent.class)
|
|
||||||
.then(event -> event.getPack().registerConfigType(new OreConfigType(), addon.key("ORE"), 1))
|
|
||||||
.failThrough();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020-2021 Polyhedral Development
|
|
||||||
*
|
|
||||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
|
||||||
* reference the LICENSE file in this module's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.addons.ore.v2;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.Platform;
|
|
||||||
import com.dfsek.terra.api.config.ConfigFactory;
|
|
||||||
import com.dfsek.terra.api.config.ConfigPack;
|
|
||||||
import com.dfsek.terra.api.config.ConfigType;
|
|
||||||
import com.dfsek.terra.api.structure.Structure;
|
|
||||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
|
||||||
|
|
||||||
|
|
||||||
public class OreConfigType implements ConfigType<OreTemplate, Structure> {
|
|
||||||
public static final TypeKey<Structure> ORE_TYPE_TOKEN = new TypeKey<>() {
|
|
||||||
};
|
|
||||||
private final OreFactory factory = new OreFactory();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public OreTemplate getTemplate(ConfigPack pack, Platform platform) {
|
|
||||||
return new OreTemplate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConfigFactory<OreTemplate, Structure> getFactory() {
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeKey<Structure> getTypeKey() {
|
|
||||||
return ORE_TYPE_TOKEN;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020-2021 Polyhedral Development
|
|
||||||
*
|
|
||||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
|
||||||
* reference the LICENSE file in this module's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.addons.ore.v2;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.ore.v2.ores.VanillaOre;
|
|
||||||
import com.dfsek.terra.api.Platform;
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
|
||||||
import com.dfsek.terra.api.config.ConfigFactory;
|
|
||||||
import com.dfsek.terra.api.structure.Structure;
|
|
||||||
|
|
||||||
|
|
||||||
public class OreFactory implements ConfigFactory<OreTemplate, Structure> {
|
|
||||||
@Override
|
|
||||||
public VanillaOre build(OreTemplate config, Platform platform) {
|
|
||||||
BlockState m = config.getMaterial();
|
|
||||||
return new VanillaOre(m, config.getSize(), config.getReplaceable(), config.doPhysics(), config.isExposed(),
|
|
||||||
config.getMaterialOverrides());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020-2021 Polyhedral Development
|
|
||||||
*
|
|
||||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
|
||||||
* reference the LICENSE file in this module's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.addons.ore.v2;
|
|
||||||
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Final;
|
|
||||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.block.BlockType;
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
|
||||||
import com.dfsek.terra.api.config.AbstractableTemplate;
|
|
||||||
import com.dfsek.terra.api.config.meta.Meta;
|
|
||||||
import com.dfsek.terra.api.util.collection.MaterialSet;
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unused", "FieldMayBeFinal" })
|
|
||||||
public class OreTemplate implements AbstractableTemplate {
|
|
||||||
@Value("id")
|
|
||||||
@Final
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
@Value("material")
|
|
||||||
private @Meta BlockState material;
|
|
||||||
|
|
||||||
@Value("material-overrides")
|
|
||||||
@Default
|
|
||||||
private @Meta Map<@Meta BlockType, @Meta BlockState> materials = new HashMap<>();
|
|
||||||
|
|
||||||
@Value("replace")
|
|
||||||
private @Meta MaterialSet replaceable;
|
|
||||||
|
|
||||||
@Value("physics")
|
|
||||||
@Default
|
|
||||||
private @Meta boolean physics = false;
|
|
||||||
|
|
||||||
@Value("size")
|
|
||||||
private @Meta double size;
|
|
||||||
|
|
||||||
@Value("exposed")
|
|
||||||
@Default
|
|
||||||
@Description("The chance that ore blocks bordering air will be discarded as candidates for ore. 0 = 0%, 1 = 100%")
|
|
||||||
private @Meta double exposed = 0.0f;
|
|
||||||
|
|
||||||
public boolean doPhysics() {
|
|
||||||
return physics;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState getMaterial() {
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaterialSet getReplaceable() {
|
|
||||||
return replaceable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<BlockType, BlockState> getMaterialOverrides() {
|
|
||||||
return materials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double isExposed() {
|
|
||||||
return exposed;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2020-2021 Polyhedral Development
|
|
||||||
*
|
|
||||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
|
||||||
* reference the LICENSE file in this module's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.dfsek.terra.addons.ore.v2.ores;
|
|
||||||
|
|
||||||
import java.util.BitSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.block.BlockType;
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
|
||||||
import com.dfsek.terra.api.structure.Structure;
|
|
||||||
import com.dfsek.terra.api.util.MathUtil;
|
|
||||||
import com.dfsek.terra.api.util.Rotation;
|
|
||||||
import com.dfsek.terra.api.util.collection.MaterialSet;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3Int;
|
|
||||||
import com.dfsek.terra.api.world.WritableWorld;
|
|
||||||
|
|
||||||
|
|
||||||
public class VanillaOre implements Structure {
|
|
||||||
|
|
||||||
private final BlockState material;
|
|
||||||
|
|
||||||
private final double size;
|
|
||||||
private final MaterialSet replaceable;
|
|
||||||
private final boolean applyGravity;
|
|
||||||
private final double exposed;
|
|
||||||
private final Map<BlockType, BlockState> materials;
|
|
||||||
|
|
||||||
public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity,
|
|
||||||
double exposed, Map<BlockType, BlockState> materials) {
|
|
||||||
this.material = material;
|
|
||||||
this.size = size;
|
|
||||||
this.replaceable = replaceable;
|
|
||||||
this.applyGravity = applyGravity;
|
|
||||||
this.exposed = exposed;
|
|
||||||
this.materials = materials;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static boolean shouldNotDiscard(Random random, double chance) {
|
|
||||||
if(chance <= 0.0F) {
|
|
||||||
return true;
|
|
||||||
} else if(chance >= 1.0F) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return random.nextFloat() >= chance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double lerp(double t, double v0, double v1) {
|
|
||||||
return v0 + t * (v1 - v0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
|
|
||||||
float randomRadian = random.nextFloat() * (float) Math.PI;
|
|
||||||
double eigthSize = size / 8.0F;
|
|
||||||
|
|
||||||
// Place points to form a line segment
|
|
||||||
double startX = (double) location.getX() + MathUtil.sin(randomRadian) * eigthSize;
|
|
||||||
double endX = (double) location.getX() - MathUtil.sin(randomRadian) * eigthSize;
|
|
||||||
|
|
||||||
double startZ = (double) location.getZ() + MathUtil.cos(randomRadian) * eigthSize;
|
|
||||||
double endZ = (double) location.getZ() - MathUtil.cos(randomRadian) * eigthSize;
|
|
||||||
|
|
||||||
double startY = location.getY() + random.nextInt(3) - 2;
|
|
||||||
double endY = location.getY() + random.nextInt(3) - 2;
|
|
||||||
|
|
||||||
int sizeInt = (int) size;
|
|
||||||
double[] points = new double[sizeInt * 4];
|
|
||||||
|
|
||||||
// Compute initial point positions and radius
|
|
||||||
for(int i = 0; i < sizeInt; ++i) {
|
|
||||||
float t = (float) i / (float) sizeInt;
|
|
||||||
double xt = lerp(t, startX, endX);
|
|
||||||
double yt = lerp(t, startY, endY);
|
|
||||||
double zt = lerp(t, startZ, endZ);
|
|
||||||
double roll = random.nextDouble() * size / 16.0;
|
|
||||||
// Taper radius closer to line ends
|
|
||||||
double radius = ((MathUtil.sin((float) Math.PI * t) + 1.0F) * roll + 1.0) / 2.0;
|
|
||||||
points[i * 4] = xt;
|
|
||||||
points[i * 4 + 1] = yt;
|
|
||||||
points[i * 4 + 2] = zt;
|
|
||||||
points[i * 4 + 3] = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare every point to every other point
|
|
||||||
for(int a = 0; a < sizeInt - 1; ++a) {
|
|
||||||
double radiusA = points[a * 4 + 3];
|
|
||||||
if(radiusA > 0.0) {
|
|
||||||
for(int b = a + 1; b < sizeInt; ++b) {
|
|
||||||
double radiusB = points[b * 4 + 3];
|
|
||||||
if(radiusB > 0.0) {
|
|
||||||
double dxt = points[a * 4] - points[b * 4];
|
|
||||||
double dyt = points[a * 4 + 1] - points[b * 4 + 1];
|
|
||||||
double dzt = points[a * 4 + 2] - points[b * 4 + 2];
|
|
||||||
double dRadius = radiusA - radiusB;
|
|
||||||
|
|
||||||
// If the radius difference is greater than the distance between the two points
|
|
||||||
if(dRadius * dRadius > dxt * dxt + dyt * dyt + dzt * dzt) {
|
|
||||||
// Set smaller of two radii to -1
|
|
||||||
if(dRadius > 0.0) {
|
|
||||||
points[b * 4 + 3] = -1.0;
|
|
||||||
} else {
|
|
||||||
points[a * 4 + 3] = -1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int outset = (int) Math.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F);
|
|
||||||
int x = (int) (location.getX() - Math.ceil(eigthSize) - outset);
|
|
||||||
int y = location.getY() - 2 - outset;
|
|
||||||
int z = (int) (location.getZ() - Math.ceil(eigthSize) - outset);
|
|
||||||
|
|
||||||
int horizontalSize = (int) (2 * (Math.ceil(eigthSize) + outset));
|
|
||||||
int verticalSize = 2 * (2 + outset);
|
|
||||||
|
|
||||||
int sphereCount = 0;
|
|
||||||
BitSet visited = new BitSet(horizontalSize * verticalSize * horizontalSize);
|
|
||||||
|
|
||||||
// Generate a sphere at each point
|
|
||||||
for(int i = 0; i < sizeInt; ++i) {
|
|
||||||
double radius = points[i * 4 + 3];
|
|
||||||
if(radius > 0.0) {
|
|
||||||
double xt = points[i * 4];
|
|
||||||
double yt = points[i * 4 + 1];
|
|
||||||
double zt = points[i * 4 + 2];
|
|
||||||
|
|
||||||
int xLowerBound = (int) Math.max(Math.floor(xt - radius), x);
|
|
||||||
int xUpperBound = (int) Math.max(Math.floor(xt + radius), xLowerBound);
|
|
||||||
|
|
||||||
int yLowerBound = (int) Math.max(Math.floor(yt - radius), y);
|
|
||||||
int yUpperBound = (int) Math.max(Math.floor(yt + radius), yLowerBound);
|
|
||||||
|
|
||||||
int zLowerBound = (int) Math.max(Math.floor(zt - radius), z);
|
|
||||||
int zUpperBound = (int) Math.max(Math.floor(zt + radius), zLowerBound);
|
|
||||||
|
|
||||||
// Iterate over coordinates within bounds
|
|
||||||
for(int xi = xLowerBound; xi <= xUpperBound; ++xi) {
|
|
||||||
double dx = ((double) xi + 0.5 - xt) / radius;
|
|
||||||
if(dx * dx < 1.0) {
|
|
||||||
for(int yi = yLowerBound; yi <= yUpperBound; ++yi) {
|
|
||||||
double dy = ((double) yi + 0.5 - yt) / radius;
|
|
||||||
if(dx * dx + dy * dy < 1.0) {
|
|
||||||
for(int zi = zLowerBound; zi <= zUpperBound; ++zi) {
|
|
||||||
double dz = ((double) zi + 0.5 - zt) / radius;
|
|
||||||
|
|
||||||
// If position is inside the sphere
|
|
||||||
if(dx * dx + dy * dy + dz * dz < 1.0 && !(yi < world.getMinHeight() || yi >= world.getMaxHeight())) {
|
|
||||||
int index = xi - x + (yi - y) * horizontalSize + (zi - z) * horizontalSize * verticalSize;
|
|
||||||
if(!visited.get(index)) { // Skip blocks that have already been visited
|
|
||||||
|
|
||||||
visited.set(index);
|
|
||||||
BlockType block = world.getBlockState(xi, yi, zi).getBlockType();
|
|
||||||
if(shouldPlace(block, random, world, xi, yi, zi)) {
|
|
||||||
world.setBlockState(xi, yi, zi, getMaterial(block), isApplyGravity());
|
|
||||||
++sphereCount;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sphereCount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldPlace(BlockType type, Random random, WritableWorld world, int x, int y, int z) {
|
|
||||||
if(!getReplaceable().contains(type)) {
|
|
||||||
return false;
|
|
||||||
} else if(shouldNotDiscard(random, exposed)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return !(world.getBlockState(x, y, z - 1).isAir() ||
|
|
||||||
world.getBlockState(x, y, z + 1).isAir() ||
|
|
||||||
world.getBlockState(x, y - 1, z).isAir() ||
|
|
||||||
world.getBlockState(x, y + 1, z).isAir() ||
|
|
||||||
world.getBlockState(x - 1, y, z).isAir() ||
|
|
||||||
world.getBlockState(x + 1, y, z).isAir());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState getMaterial(BlockType replace) {
|
|
||||||
return materials.getOrDefault(replace, material);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MaterialSet getReplaceable() {
|
|
||||||
return replaceable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isApplyGravity() {
|
|
||||||
return applyGravity;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
schema-version: 1
|
|
||||||
contributors:
|
|
||||||
- Terra contributors
|
|
||||||
id: config-ore-v2
|
|
||||||
version: @VERSION@
|
|
||||||
entrypoints:
|
|
||||||
- "com.dfsek.terra.addons.ore.v2.OreAddon"
|
|
||||||
website:
|
|
||||||
issues: https://github.com/PolyhedralDev/Terra/issues
|
|
||||||
source: https://github.com/PolyhedralDev/Terra
|
|
||||||
docs: https://terra.polydev.org
|
|
||||||
license: MIT License
|
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.addons.ore.ores;
|
package com.dfsek.terra.addons.ore.ores;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -40,67 +41,156 @@ public class VanillaOre implements Structure {
|
|||||||
this.materials = materials;
|
this.materials = materials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static boolean shouldNotDiscard(Random random, double chance) {
|
||||||
|
if(chance <= 0.0F) {
|
||||||
|
return true;
|
||||||
|
} else if(chance >= 1.0F) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return random.nextFloat() >= chance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double lerp(double t, double v0, double v1) {
|
||||||
|
return v0 + t * (v1 - v0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
|
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
|
||||||
int centerX = location.getX();
|
float randomRadian = random.nextFloat() * (float) Math.PI;
|
||||||
int centerZ = location.getZ();
|
double eigthSize = size / 8.0F;
|
||||||
int centerY = location.getY();
|
|
||||||
|
|
||||||
|
// Place points to form a line segment
|
||||||
|
double startX = (double) location.getX() + MathUtil.sin(randomRadian) * eigthSize;
|
||||||
|
double endX = (double) location.getX() - MathUtil.sin(randomRadian) * eigthSize;
|
||||||
|
|
||||||
float f = random.nextFloat() * (float) Math.PI;
|
double startZ = (double) location.getZ() + MathUtil.cos(randomRadian) * eigthSize;
|
||||||
|
double endZ = (double) location.getZ() - MathUtil.cos(randomRadian) * eigthSize;
|
||||||
|
|
||||||
double d1 = centerX + 8 + MathUtil.sin(f) * size / 8.0F;
|
double startY = location.getY() + random.nextInt(3) - 2;
|
||||||
double d2 = centerX + 8 - MathUtil.sin(f) * size / 8.0F;
|
double endY = location.getY() + random.nextInt(3) - 2;
|
||||||
double d3 = centerZ + 8 + MathUtil.cos(f) * size / 8.0F;
|
|
||||||
double d4 = centerZ + 8 - MathUtil.cos(f) * size / 8.0F;
|
|
||||||
|
|
||||||
double d5 = centerY + random.nextInt(3) - 2D;
|
int sizeInt = (int) size;
|
||||||
double d6 = centerY + random.nextInt(3) - 2D;
|
double[] points = new double[sizeInt * 4];
|
||||||
|
|
||||||
for(int i = 0; i < size; i++) {
|
// Compute initial point positions and radius
|
||||||
float iFactor = (float) i / (float) size;
|
for(int i = 0; i < sizeInt; ++i) {
|
||||||
|
float t = (float) i / (float) sizeInt;
|
||||||
|
double xt = lerp(t, startX, endX);
|
||||||
|
double yt = lerp(t, startY, endY);
|
||||||
|
double zt = lerp(t, startZ, endZ);
|
||||||
|
double roll = random.nextDouble() * size / 16.0;
|
||||||
|
// Taper radius closer to line ends
|
||||||
|
double radius = ((MathUtil.sin((float) Math.PI * t) + 1.0F) * roll + 1.0) / 2.0;
|
||||||
|
points[i * 4] = xt;
|
||||||
|
points[i * 4 + 1] = yt;
|
||||||
|
points[i * 4 + 2] = zt;
|
||||||
|
points[i * 4 + 3] = radius;
|
||||||
|
}
|
||||||
|
|
||||||
double d10 = random.nextDouble() * size / 16.0D;
|
// Compare every point to every other point
|
||||||
double d11 = (MathUtil.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0;
|
for(int a = 0; a < sizeInt - 1; ++a) {
|
||||||
double d12 = (MathUtil.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0;
|
double radiusA = points[a * 4 + 3];
|
||||||
|
if(radiusA > 0.0) {
|
||||||
|
for(int b = a + 1; b < sizeInt; ++b) {
|
||||||
|
double radiusB = points[b * 4 + 3];
|
||||||
|
if(radiusB > 0.0) {
|
||||||
|
double dxt = points[a * 4] - points[b * 4];
|
||||||
|
double dyt = points[a * 4 + 1] - points[b * 4 + 1];
|
||||||
|
double dzt = points[a * 4 + 2] - points[b * 4 + 2];
|
||||||
|
double dRadius = radiusA - radiusB;
|
||||||
|
|
||||||
int xStart = (int) Math.round(Math.floor(d1 + (d2 - d1) * iFactor - d11 / 2.0D));
|
// If the radius difference is greater than the distance between the two points
|
||||||
int yStart = (int) Math.round(Math.floor(d5 + (d6 - d5) * iFactor - d12 / 2.0D));
|
if(dRadius * dRadius > dxt * dxt + dyt * dyt + dzt * dzt) {
|
||||||
int zStart = (int) Math.round(Math.floor(d3 + (d4 - d3) * iFactor - d11 / 2.0D));
|
// Set smaller of two radii to -1
|
||||||
|
if(dRadius > 0.0) {
|
||||||
|
points[b * 4 + 3] = -1.0;
|
||||||
|
} else {
|
||||||
|
points[a * 4 + 3] = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int xEnd = (int) Math.round(Math.floor(d1 + (d2 - d1) * iFactor + d11 / 2.0D));
|
int outset = (int) Math.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F);
|
||||||
int yEnd = (int) Math.round(Math.floor(d5 + (d6 - d5) * iFactor + d12 / 2.0D));
|
int x = (int) (location.getX() - Math.ceil(eigthSize) - outset);
|
||||||
int zEnd = (int) Math.round(Math.floor(d3 + (d4 - d3) * iFactor + d11 / 2.0D));
|
int y = location.getY() - 2 - outset;
|
||||||
|
int z = (int) (location.getZ() - Math.ceil(eigthSize) - outset);
|
||||||
|
|
||||||
for(int x = xStart; x <= xEnd; x++) {
|
int horizontalSize = (int) (2 * (Math.ceil(eigthSize) + outset));
|
||||||
double d13 = (x + 0.5D - (d1 + (d2 - d1) * iFactor)) / (d11 / 2.0D);
|
int verticalSize = 2 * (2 + outset);
|
||||||
|
|
||||||
if(d13 * d13 < 1.0D) {
|
int sphereCount = 0;
|
||||||
for(int y = yStart; y <= yEnd; y++) {
|
BitSet visited = new BitSet(horizontalSize * verticalSize * horizontalSize);
|
||||||
double d14 = (y + 0.5D - (d5 + (d6 - d5) * iFactor)) / (d12 / 2.0D);
|
|
||||||
if(d13 * d13 + d14 * d14 < 1.0D) {
|
// Generate a sphere at each point
|
||||||
for(int z = zStart; z <= zEnd; z++) {
|
for(int i = 0; i < sizeInt; ++i) {
|
||||||
double d15 = (z + 0.5D - (d3 + (d4 - d3) * iFactor)) / (d11 / 2.0D);
|
double radius = points[i * 4 + 3];
|
||||||
if(y >= world.getMaxHeight() || y < world.getMinHeight()) continue;
|
if(radius > 0.0) {
|
||||||
BlockType block = world.getBlockState(x, y, z).getBlockType();
|
double xt = points[i * 4];
|
||||||
if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(block)) {
|
double yt = points[i * 4 + 1];
|
||||||
if(exposed > random.nextDouble() || !(world.getBlockState(x, y, z - 1).isAir() ||
|
double zt = points[i * 4 + 2];
|
||||||
|
|
||||||
|
int xLowerBound = (int) Math.max(Math.floor(xt - radius), x);
|
||||||
|
int xUpperBound = (int) Math.max(Math.floor(xt + radius), xLowerBound);
|
||||||
|
|
||||||
|
int yLowerBound = (int) Math.max(Math.floor(yt - radius), y);
|
||||||
|
int yUpperBound = (int) Math.max(Math.floor(yt + radius), yLowerBound);
|
||||||
|
|
||||||
|
int zLowerBound = (int) Math.max(Math.floor(zt - radius), z);
|
||||||
|
int zUpperBound = (int) Math.max(Math.floor(zt + radius), zLowerBound);
|
||||||
|
|
||||||
|
// Iterate over coordinates within bounds
|
||||||
|
for(int xi = xLowerBound; xi <= xUpperBound; ++xi) {
|
||||||
|
double dx = ((double) xi + 0.5 - xt) / radius;
|
||||||
|
if(dx * dx < 1.0) {
|
||||||
|
for(int yi = yLowerBound; yi <= yUpperBound; ++yi) {
|
||||||
|
double dy = ((double) yi + 0.5 - yt) / radius;
|
||||||
|
if(dx * dx + dy * dy < 1.0) {
|
||||||
|
for(int zi = zLowerBound; zi <= zUpperBound; ++zi) {
|
||||||
|
double dz = ((double) zi + 0.5 - zt) / radius;
|
||||||
|
|
||||||
|
// If position is inside the sphere
|
||||||
|
if(dx * dx + dy * dy + dz * dz < 1.0 && !(yi < world.getMinHeight() || yi >= world.getMaxHeight())) {
|
||||||
|
int index = xi - x + (yi - y) * horizontalSize + (zi - z) * horizontalSize * verticalSize;
|
||||||
|
if(!visited.get(index)) { // Skip blocks that have already been visited
|
||||||
|
|
||||||
|
visited.set(index);
|
||||||
|
BlockType block = world.getBlockState(xi, yi, zi).getBlockType();
|
||||||
|
if(shouldPlace(block, random, world, xi, yi, zi)) {
|
||||||
|
world.setBlockState(xi, yi, zi, getMaterial(block), isApplyGravity());
|
||||||
|
++sphereCount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sphereCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldPlace(BlockType type, Random random, WritableWorld world, int x, int y, int z) {
|
||||||
|
if(!getReplaceable().contains(type)) {
|
||||||
|
return false;
|
||||||
|
} else if(shouldNotDiscard(random, exposed)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return !(world.getBlockState(x, y, z - 1).isAir() ||
|
||||||
world.getBlockState(x, y, z + 1).isAir() ||
|
world.getBlockState(x, y, z + 1).isAir() ||
|
||||||
world.getBlockState(x, y - 1, z).isAir() ||
|
world.getBlockState(x, y - 1, z).isAir() ||
|
||||||
world.getBlockState(x, y + 1, z).isAir() ||
|
world.getBlockState(x, y + 1, z).isAir() ||
|
||||||
world.getBlockState(x - 1, y, z).isAir() ||
|
world.getBlockState(x - 1, y, z).isAir() ||
|
||||||
world.getBlockState(x + 1, y, z).isAir())) {
|
world.getBlockState(x + 1, y, z).isAir());
|
||||||
world.setBlockState(x, y, z, getMaterial(block), isApplyGravity());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockState getMaterial(BlockType replace) {
|
public BlockState getMaterial(BlockType replace) {
|
||||||
return materials.getOrDefault(replace, material);
|
return materials.getOrDefault(replace, material);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user