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
@@ -19,8 +19,6 @@ import org.slf4j.LoggerFactory;
public class OreAddon implements AddonInitializer { public class OreAddon implements AddonInitializer {
private static final Logger logger = LoggerFactory.getLogger(OreAddon.class);
@Inject @Inject
private Platform platform; private Platform platform;
@@ -33,9 +31,7 @@ public class OreAddon implements AddonInitializer {
.getHandler(FunctionalEventHandler.class) .getHandler(FunctionalEventHandler.class)
.register(addon, ConfigPackPreLoadEvent.class) .register(addon, ConfigPackPreLoadEvent.class)
.then(event -> event.getPack().registerConfigType(new OreConfigType(), addon.key("ORE"), 1)) .then(event -> event.getPack().registerConfigType(new OreConfigType(), addon.key("ORE"), 1))
.then(event -> event.getPack().registerConfigType(new ScatteredOreConfigType(), addon.key("SCATTERED_ORE"), 1))
.failThrough(); .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.");
} }
} }
@@ -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;
}
}
@@ -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());
}
}
@@ -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;
}
}
@@ -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.util.vector.Vector3Int;
import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.WritableWorld;
import static com.dfsek.terra.addons.ore.utils.VanillaOreUtils.shouldPlace;
public class VanillaOre implements Structure { public class VanillaOre implements Structure {
private final BlockState material; protected final BlockState material;
private final double size; protected final double size;
private final MaterialSet replaceable; protected final MaterialSet replaceable;
private final boolean applyGravity; protected final boolean applyGravity;
private final double exposed; protected final double exposed;
private final Map<BlockType, BlockState> materials; protected final Map<BlockType, BlockState> materials;
public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity, public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity,
double exposed, Map<BlockType, BlockState> materials) { double exposed, Map<BlockType, BlockState> materials) {
@@ -41,16 +43,6 @@ 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) { public static double lerp(double t, double v0, double v1) {
return v0 + t * (v1 - v0); return v0 + t * (v1 - v0);
} }
@@ -58,14 +50,14 @@ public class VanillaOre implements Structure {
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
float randomRadian = random.nextFloat() * (float) Math.PI; float randomRadian = random.nextFloat() * (float) Math.PI;
double eigthSize = size / 8.0F; double eighthSize = size / 8.0F;
// Place points to form a line segment // Place points to form a line segment
double startX = (double) location.getX() + MathUtil.sin(randomRadian) * eigthSize; double startX = (double) location.getX() + MathUtil.sin(randomRadian) * eighthSize;
double endX = (double) location.getX() - MathUtil.sin(randomRadian) * eigthSize; double endX = (double) location.getX() - MathUtil.sin(randomRadian) * eighthSize;
double startZ = (double) location.getZ() + MathUtil.cos(randomRadian) * eigthSize; double startZ = (double) location.getZ() + MathUtil.cos(randomRadian) * eighthSize;
double endZ = (double) location.getZ() - MathUtil.cos(randomRadian) * eigthSize; double endZ = (double) location.getZ() - MathUtil.cos(randomRadian) * eighthSize;
double startY = location.getY() + random.nextInt(3) - 2; double startY = location.getY() + random.nextInt(3) - 2;
double endY = 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 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 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 verticalSize = 2 * (2 + outset);
int sphereCount = 0; int blockCount = 0;
BitSet visited = new BitSet(horizontalSize * verticalSize * horizontalSize); BitSet visited = new BitSet(horizontalSize * verticalSize * horizontalSize);
// Generate a sphere at each point // Generate a sphere at each point
@@ -159,10 +151,9 @@ public class VanillaOre implements Structure {
visited.set(index); visited.set(index);
BlockType block = world.getBlockState(xi, yi, zi).getBlockType(); 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()); world.setBlockState(xi, yi, zi, getMaterial(block), isApplyGravity());
++sphereCount; ++blockCount;
break;
} }
} }
} }
@@ -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) { public BlockState getMaterial(BlockType replace) {
return materials.getOrDefault(replace, material); return materials.getOrDefault(replace, material);
} }
@@ -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);
}
}
@@ -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());
}
}
}