diff --git a/common/addons/config-ore-v2/LICENSE b/common/addons/config-ore-v2/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-ore-v2/LICENSE @@ -0,0 +1,21 @@ +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. \ No newline at end of file diff --git a/common/addons/config-ore-v2/README.md b/common/addons/config-ore-v2/README.md new file mode 100644 index 000000000..1b72835ea --- /dev/null +++ b/common/addons/config-ore-v2/README.md @@ -0,0 +1,3 @@ +# config-ore + +Registers the default configuration for Terra Ores, `ORE`. \ No newline at end of file diff --git a/common/addons/config-ore-v2/build.gradle.kts b/common/addons/config-ore-v2/build.gradle.kts new file mode 100644 index 000000000..3799c6be1 --- /dev/null +++ b/common/addons/config-ore-v2/build.gradle.kts @@ -0,0 +1,11 @@ +version = version("2.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.ore.lib.jafama") +} diff --git a/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreAddon.java b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreAddon.java new file mode 100644 index 000000000..4e6f1751b --- /dev/null +++ b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreAddon.java @@ -0,0 +1,33 @@ +/* + * 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.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(); + } +} diff --git a/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreConfigType.java b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreConfigType.java new file mode 100644 index 000000000..2bdc87bdd --- /dev/null +++ b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreConfigType.java @@ -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 OreConfigType implements ConfigType { + public static final TypeKey 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 getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return ORE_TYPE_TOKEN; + } +} diff --git a/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreFactory.java b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreFactory.java new file mode 100644 index 000000000..9d8b1055a --- /dev/null +++ b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreFactory.java @@ -0,0 +1,24 @@ +/* + * 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.addons.ore.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 { + @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()); + } +} diff --git a/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreTemplate.java b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreTemplate.java new file mode 100644 index 000000000..8bfbc82d3 --- /dev/null +++ b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/OreTemplate.java @@ -0,0 +1,80 @@ +/* + * 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 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 exposed. 0 = 0%, 1 = 100%") + private @Meta double exposed = 1; + + 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 getMaterialOverrides() { + return materials; + } + + public double isExposed() { + return exposed; + } +} diff --git a/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/ores/VanillaOre.java b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/ores/VanillaOre.java new file mode 100644 index 000000000..32f5c7c22 --- /dev/null +++ b/common/addons/config-ore-v2/src/main/java/com/dfsek/terra/addons/ore/ores/VanillaOre.java @@ -0,0 +1,188 @@ +/* + * 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.ores; + +import net.jafama.FastMath; + +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.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 materials; + + public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity, + double exposed, Map 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 f = random.nextFloat() * (float) Math.PI; + double g = size / 8.0F; + int i = (int) FastMath.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F); + double startX = (double) location.getX() + FastMath.sin(f) * g; + double endX = (double) location.getX() - FastMath.sin(f) * g; + double startZ = (double) location.getZ() + FastMath.cos(f) * g; + double endZ = (double) location.getZ() - FastMath.cos(f) * g; + double startY = location.getY() + random.nextInt(3) - 2; + double endY = location.getY() + random.nextInt(3) - 2; + int x = (int) (location.getX() - FastMath.ceil(g) - i); + int y = location.getY() - 2 - i; + int z = (int) (location.getZ() - FastMath.ceil(g) - i); + int horizontalSize = (int) (2 * (FastMath.ceil(g) + i)); + int verticalSize = 2 * (2 + i); + + int i1 = 0; + BitSet bitSet = new BitSet(horizontalSize * verticalSize * horizontalSize); + + int j1 = (int) size; + double[] ds = new double[j1 * 4]; + + for(int k1 = 0; k1 < j1; ++k1) { + float f1 = (float) k1 / (float) j1; + double d1 = lerp(f1, startX, endX); + double e1 = lerp(f1, startY, endY); + double g1 = lerp(f1, startZ, endZ); + double h1 = random.nextDouble() * (double) j1 / 16.0; + double l1 = ((FastMath.sin((float) Math.PI * f1) + 1.0F) * h1 + 1.0) / 2.0; + ds[k1 * 4] = d1; + ds[k1 * 4 + 1] = e1; + ds[k1 * 4 + 2] = g1; + ds[k1 * 4 + 3] = l1; + } + + for(int k1 = 0; k1 < j1 - 1; ++k1) { + if(!(ds[k1 * 4 + 3] <= 0.0)) { + for(int m1 = k1 + 1; m1 < j1; ++m1) { + if(!(ds[m1 * 4 + 3] <= 0.0)) { + double d1 = ds[k1 * 4] - ds[m1 * 4]; + double e1 = ds[k1 * 4 + 1] - ds[m1 * 4 + 1]; + double g1 = ds[k1 * 4 + 2] - ds[m1 * 4 + 2]; + double h1 = ds[k1 * 4 + 3] - ds[m1 * 4 + 3]; + if(h1 * h1 > d1 * d1 + e1 * e1 + g1 * g1) { + if(h1 > 0.0) { + ds[m1 * 4 + 3] = -1.0; + } else { + ds[k1 * 4 + 3] = -1.0; + } + } + } + } + } + } + + for(int m1 = 0; m1 < j1; ++m1) { + double d1 = ds[m1 * 4 + 3]; + if(!(d1 < 0.0)) { + double e1 = ds[m1 * 4]; + double g1 = ds[m1 * 4 + 1]; + double h1 = ds[m1 * 4 + 2]; + int n1 = (int) FastMath.max(FastMath.floor(e1 - d1), x); + int o1 = (int) FastMath.max(FastMath.floor(g1 - d1), y); + int p1 = (int) FastMath.max(FastMath.floor(h1 - d1), z); + int q1 = (int) FastMath.max(FastMath.floor(e1 + d1), n1); + int r1 = (int) FastMath.max(FastMath.floor(g1 + d1), o1); + int s1 = (int) FastMath.max(FastMath.floor(h1 + d1), p1); + + for(int t1 = n1; t1 <= q1; ++t1) { + double u1 = ((double) t1 + 0.5 - e1) / d1; + if(u1 * u1 < 1.0) { + for(int v1 = o1; v1 <= r1; ++v1) { + double w1 = ((double) v1 + 0.5 - g1) / d1; + if(u1 * u1 + w1 * w1 < 1.0) { + for(int aa = p1; aa <= s1; ++aa) { + double ab = ((double) aa + 0.5 - h1) / d1; + if(u1 * u1 + w1 * w1 + ab * ab < 1.0 && !(v1 < world.getMinHeight() || v1 >= world.getMaxHeight())) { + int ac = t1 - x + (v1 - y) * horizontalSize + (aa - z) * horizontalSize * verticalSize; + if(!bitSet.get(ac)) { + bitSet.set(ac); + + BlockType block = world.getBlockState(x, y, z).getBlockType(); + + if(shouldPlace(block, random, world, t1, v1, aa)) { + world.setBlockState(t1, v1, aa, getMaterial(block), isApplyGravity()); + ++i1; + break; + } + } + } + } + } + } + } + } + } + } + + + return i1 > 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; + } +} diff --git a/common/addons/config-ore-v2/src/main/resources/terra.addon.yml b/common/addons/config-ore-v2/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..7edad8d07 --- /dev/null +++ b/common/addons/config-ore-v2/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-ore-v2 +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.ore.OreAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file