Scattered ore (#424)

* Scattered Ore Impl

* remove break

* remove another break

* sphereCount -> blockCount

---------

Co-authored-by: Astrash <astrash@protonmail.com>
This commit is contained in:
Zoë
2023-10-29 23:33:50 +00:00
committed by GitHub
parent c41bf55b7b
commit 648da95e7d
7 changed files with 212 additions and 50 deletions

View File

@@ -19,8 +19,6 @@ import org.slf4j.LoggerFactory;
public class OreAddon implements AddonInitializer {
private static final Logger logger = LoggerFactory.getLogger(OreAddon.class);
@Inject
private Platform platform;
@@ -33,9 +31,7 @@ public class OreAddon implements AddonInitializer {
.getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().registerConfigType(new OreConfigType(), addon.key("ORE"), 1))
.then(event -> event.getPack().registerConfigType(new ScatteredOreConfigType(), addon.key("SCATTERED_ORE"), 1))
.failThrough();
if(platform.getTerraConfig().isDebugLog())
logger.warn("The ore-config addon is deprecated and scheduled for removal in Terra 7.0. It is recommended to use the ore-config-v2 addon for future pack development instead.");
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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;
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 ScatteredOreConfigType implements ConfigType<ScatteredOreTemplate, Structure> {
public static final TypeKey<Structure> ORE_TYPE_TOKEN = new TypeKey<>() {
};
private final ScatteredOreFactory factory = new ScatteredOreFactory();
@Override
public ScatteredOreTemplate getTemplate(ConfigPack pack, Platform platform) {
return new ScatteredOreTemplate();
}
@Override
public ConfigFactory<ScatteredOreTemplate, Structure> getFactory() {
return factory;
}
@Override
public TypeKey<Structure> getTypeKey() {
return ORE_TYPE_TOKEN;
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.terra.addons.ore.ores.VanillaOre;
import com.dfsek.terra.addons.ore.ores.VanillaScatteredOre;
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 ScatteredOreFactory implements ConfigFactory<ScatteredOreTemplate, Structure> {
@Override
public Structure build(ScatteredOreTemplate config, Platform platform) throws LoadException {
BlockState m = config.getMaterial();
return new VanillaScatteredOre(m, config.getSize(), config.getReplaceable(), config.doPhysics(), config.isExposed(),
config.getMaterialOverrides(), config.getSpread());
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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;
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 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;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({ "unused", "FieldMayBeFinal" })
public class ScatteredOreTemplate extends OreTemplate {
@Value("size")
private @Meta int spread = 7;
public int getSpread() {
return spread;
}
}

View File

@@ -20,16 +20,18 @@ import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.util.vector.Vector3Int;
import com.dfsek.terra.api.world.WritableWorld;
import static com.dfsek.terra.addons.ore.utils.VanillaOreUtils.shouldPlace;
public class VanillaOre implements Structure {
private final BlockState material;
protected 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;
protected final double size;
protected final MaterialSet replaceable;
protected final boolean applyGravity;
protected final double exposed;
protected final Map<BlockType, BlockState> materials;
public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity,
double exposed, Map<BlockType, BlockState> materials) {
@@ -41,16 +43,6 @@ public class VanillaOre implements Structure {
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);
}
@@ -58,14 +50,14 @@ public class VanillaOre implements Structure {
@Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
float randomRadian = random.nextFloat() * (float) Math.PI;
double eigthSize = size / 8.0F;
double eighthSize = 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 startX = (double) location.getX() + MathUtil.sin(randomRadian) * eighthSize;
double endX = (double) location.getX() - MathUtil.sin(randomRadian) * eighthSize;
double startZ = (double) location.getZ() + MathUtil.cos(randomRadian) * eigthSize;
double endZ = (double) location.getZ() - MathUtil.cos(randomRadian) * eigthSize;
double startZ = (double) location.getZ() + MathUtil.cos(randomRadian) * eighthSize;
double endZ = (double) location.getZ() - MathUtil.cos(randomRadian) * eighthSize;
double startY = location.getY() + random.nextInt(3) - 2;
double endY = location.getY() + random.nextInt(3) - 2;
@@ -115,14 +107,14 @@ public class VanillaOre implements Structure {
}
int outset = (int) Math.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F);
int x = (int) (location.getX() - Math.ceil(eigthSize) - outset);
int x = (int) (location.getX() - Math.ceil(eighthSize) - outset);
int y = location.getY() - 2 - outset;
int z = (int) (location.getZ() - Math.ceil(eigthSize) - outset);
int z = (int) (location.getZ() - Math.ceil(eighthSize) - outset);
int horizontalSize = (int) (2 * (Math.ceil(eigthSize) + outset));
int horizontalSize = (int) (2 * (Math.ceil(eighthSize) + outset));
int verticalSize = 2 * (2 + outset);
int sphereCount = 0;
int blockCount = 0;
BitSet visited = new BitSet(horizontalSize * verticalSize * horizontalSize);
// Generate a sphere at each point
@@ -159,10 +151,9 @@ public class VanillaOre implements Structure {
visited.set(index);
BlockType block = world.getBlockState(xi, yi, zi).getBlockType();
if(shouldPlace(block, random, world, xi, yi, zi)) {
if(shouldPlace(getReplaceable(), block, exposed, random, world, xi, yi, zi)) {
world.setBlockState(xi, yi, zi, getMaterial(block), isApplyGravity());
++sphereCount;
break;
++blockCount;
}
}
}
@@ -174,24 +165,8 @@ public class VanillaOre implements Structure {
}
}
return sphereCount > 0;
return blockCount > 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);
}

View File

@@ -0,0 +1,56 @@
package com.dfsek.terra.addons.ore.ores;
import com.dfsek.terra.addons.ore.utils.VanillaOreUtils;
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.Rotation;
import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.util.vector.Vector3Int;
import com.dfsek.terra.api.world.WritableWorld;
import java.util.Map;
import java.util.Random;
import static com.dfsek.terra.addons.ore.utils.VanillaOreUtils.shouldPlace;
public class VanillaScatteredOre extends VanillaOre {
protected final int spread;
public VanillaScatteredOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity, double exposed,
Map<BlockType, BlockState> materials, int spread) {
super(material, size, replaceable, applyGravity, exposed, materials);
this.spread = spread;
}
@Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
int i = random.nextInt((int) (size + 1));
Vector3Int.Mutable mutable = Vector3Int.zero().mutable();
for(int j = 0; j < i; ++j) {
this.setPos(mutable, random, location, Math.min(j, spread));
BlockType block = world.getBlockState(mutable).getBlockType();
if (shouldPlace(getReplaceable(), block, exposed, random, world, mutable.getX(), mutable.getY(), mutable.getZ())) {
world.setBlockState(mutable, getMaterial(block), isApplyGravity());
}
}
return true;
}
private void setPos(Vector3Int.Mutable mutable, Random random, Vector3Int location, int spread) {
int x = this.getSpread(random, spread);
int y = this.getSpread(random, spread);
int z = this.getSpread(random, spread);
mutable.setX(location.getX() + x);
mutable.setY(location.getY() + y);
mutable.setZ(location.getZ() + z);
}
private int getSpread(Random random, int spread) {
return Math.round((random.nextFloat() - random.nextFloat()) * (float)spread);
}
}

View File

@@ -0,0 +1,37 @@
package com.dfsek.terra.addons.ore.utils;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.util.collection.MaterialSet;
import com.dfsek.terra.api.world.WritableWorld;
import java.util.Random;
public class VanillaOreUtils {
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 boolean shouldPlace(MaterialSet replaceable, BlockType type, Double exposed, Random random, WritableWorld world, int x, int y, int z) {
if(!replaceable.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());
}
}
}