aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/WorldgenStone.java
diff options
context:
space:
mode:
authorNotAPenguin <michiel.vandeginste@gmail.com>2024-09-02 23:17:17 +0200
committerGitHub <noreply@github.com>2024-09-02 23:17:17 +0200
commit1b820de08a05070909a267e17f033fcf58ac8710 (patch)
tree02831a025986a06b20f87e5bcc69d1e0c639a342 /src/main/java/gregtech/common/WorldgenStone.java
parentafd3fd92b6a6ab9ab0d0dc3214e6bc8ff7a86c9b (diff)
downloadGT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.gz
GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.bz2
GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.zip
The Great Renaming (#3014)
* move kekztech to a single root dir * move detrav to a single root dir * move gtnh-lanthanides to a single root dir * move tectech and delete some gross reflection in gt++ * remove more reflection inside gt5u * delete more reflection in gt++ * fix imports * move bartworks and bwcrossmod * fix proxies * move galactigreg and ggfab * move gtneioreplugin * try to fix gt++ bee loader * apply the rename rules to BW * apply rename rules to bwcrossmod * apply rename rules to detrav scanner mod * apply rename rules to galacticgreg * apply rename rules to ggfab * apply rename rules to goodgenerator * apply rename rules to gtnh-lanthanides * apply rename rules to gt++ * apply rename rules to kekztech * apply rename rules to kubatech * apply rename rules to tectech * apply rename rules to gt apply the rename rules to gt * fix tt import * fix mui hopefully * fix coremod except intergalactic * rename assline recipe class * fix a class name i stumbled on * rename StructureUtility to GTStructureUtility to prevent conflict with structurelib * temporary rename of GTTooltipDataCache to old name * fix gt client/server proxy names
Diffstat (limited to 'src/main/java/gregtech/common/WorldgenStone.java')
-rw-r--r--src/main/java/gregtech/common/WorldgenStone.java297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/WorldgenStone.java b/src/main/java/gregtech/common/WorldgenStone.java
new file mode 100644
index 0000000000..d995375437
--- /dev/null
+++ b/src/main/java/gregtech/common/WorldgenStone.java
@@ -0,0 +1,297 @@
+package gregtech.common;
+
+import static gregtech.api.enums.GTValues.debugStones;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Random;
+
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.IChunkProvider;
+
+import gregtech.api.GregTechAPI;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GTLog;
+import gregtech.api.world.GTWorldgen;
+import gregtech.common.blocks.BlockOresAbstract;
+import gregtech.common.blocks.TileEntityOres;
+
+public class WorldgenStone extends GTWorldgen {
+
+ static final double[] sizeConversion = { 1, 1, 1.333333, 1.333333, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; // Bias
+ // the
+ // sizes
+ // towards
+ // skinnier
+ // boulders,
+ // ie
+ // more
+ // "shafts"
+ // than
+ // dikes
+ // or
+ // sills.
+
+ public final int mBlockMeta, mAmount, mSize, mMinY, mMaxY, mProbability, mDimensionType;
+ public final Block mBlock;
+ public final Collection<String> mBiomeList;
+ public final boolean mAllowToGenerateinVoid;
+ private final String aTextWorldgen = "worldgen.";
+
+ public Hashtable<Long, StoneSeeds> validStoneSeeds = new Hashtable<>(1024);
+
+ static class StoneSeeds {
+
+ public boolean mExists;
+
+ StoneSeeds(boolean exists) {
+ mExists = exists;
+ }
+ }
+
+ static class ValidSeeds {
+
+ public int mX;
+ public int mZ;
+
+ ValidSeeds(int x, int z) {
+ this.mX = x;
+ this.mZ = z;
+ }
+ }
+
+ public WorldgenStone(StoneBuilder stone) {
+ super(stone.stoneName, GregTechAPI.sWorldgenList, stone.enabledByDefault);
+ mDimensionType = stone.dimension;
+ mBlock = stone.block;
+ mBlockMeta = Math.min(Math.max(stone.blockMeta, 0), 15);
+ mProbability = stone.probability;
+ mAmount = stone.amount;
+ mSize = stone.size;
+ mMinY = stone.minY;
+ mMaxY = stone.maxY;
+ mBiomeList = new ArrayList<>();
+ mAllowToGenerateinVoid = stone.allowToGenerateInVoid;
+ }
+
+ @Override
+ public boolean executeWorldgen(World aWorld, Random aRandom, String aBiome, int aDimensionType, int aChunkX,
+ int aChunkZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) {
+ XSTR stoneRNG = new XSTR();
+ ArrayList<ValidSeeds> stones = new ArrayList<>();
+
+ if (!isGenerationAllowed(aWorld, mDimensionType)) {
+ return false;
+ }
+ if (!(this.mBiomeList.isEmpty() || this.mBiomeList.contains(aBiome))) {
+ return false;
+ }
+ // I think the real size of the balls is mSize/8, but the original code was difficult to understand.
+ // Overall there will be less GT stones since they aren't spheres any more. /16 since this code uses it as a
+ // radius.
+ double realSize = mSize / 16;
+ int windowWidth = ((int) realSize) / 16 + 1; // Width of chunks to check for a potential stoneseed
+ // Check stone seeds to see if they have been added
+ for (int x = aChunkX / 16 - windowWidth; x < (aChunkX / 16 + windowWidth + 1); x++) {
+ for (int z = aChunkZ / 16 - windowWidth; z < (aChunkZ / 16 + windowWidth + 1); z++) {
+ long hash = (((aWorld.provider.dimensionId & 0xffL) << 56) | (((long) x & 0x000000000fffffffL) << 28)
+ | ((long) z & 0x000000000fffffffL));
+ if (!validStoneSeeds.containsKey(hash)) {
+ // Determine if RNG says to add stone at this chunk
+ stoneRNG.setSeed(
+ aWorld.getSeed() ^ hash + Math.abs(mBlockMeta)
+ + Math.abs(mSize)
+ + ((GregTechAPI.sBlockGranites == mBlock) ? (32768) : (0))); // Don't judge me.
+ // Want different
+ // values for
+ // different block
+ // types
+ if ((this.mProbability <= 1) || (stoneRNG.nextInt(this.mProbability) == 0)) {
+ // Add stone at this chunk
+ validStoneSeeds.put(hash, new StoneSeeds(true));
+ // Add to generation list
+ stones.add(new ValidSeeds(x, z));
+ if (debugStones) GTLog.out.println(
+ "New stoneseed=" + mWorldGenName + " x=" + x + " z=" + z + " realSize=" + realSize);
+ } else {
+ validStoneSeeds.put(hash, new StoneSeeds(false));
+ }
+ } else {
+ // This chunk has already been checked, check to see if a boulder exists here
+ if (validStoneSeeds.get(hash).mExists) {
+ // Add to generation list
+ stones.add(new ValidSeeds(x, z));
+ }
+ }
+ }
+ }
+
+ boolean result = stones.size() != 0;
+ // Now process each oreseed vs this requested chunk
+ for (; stones.size() != 0; stones.remove(0)) {
+ int x = stones.get(0).mX * 16;
+ int z = stones.get(0).mZ * 16;
+
+ stoneRNG.setSeed(
+ aWorld.getSeed()
+ ^ (((aWorld.provider.dimensionId & 0xffL) << 56) | (((long) x & 0x000000000fffffffL) << 28)
+ | ((long) z & 0x000000000fffffffL)) + Math.abs(mBlockMeta)
+ + Math.abs(mSize)
+ + ((GregTechAPI.sBlockGranites == mBlock) ? (32768) : (0))); // Don't judge me
+ for (int i = 0; i < this.mAmount; i++) { // Not sure why you would want more than one in a chunk! Left alone
+ // though.
+ // Locate the stoneseed XYZ. Original code would request an isAir at the seed location, causing a chunk
+ // generation request.
+ // To reduce potential worldgen cascade, we just always try to place a ball and use the check inside the
+ // for loop to prevent
+ // placement instead.
+ int tX = x + stoneRNG.nextInt(16);
+ int tY = mMinY + stoneRNG.nextInt(mMaxY - mMinY);
+ int tZ = z + stoneRNG.nextInt(16);
+
+ // Determine the XYZ sizes of the stoneseed
+ double xSize = sizeConversion[stoneRNG.nextInt(sizeConversion.length)];
+ double ySize = sizeConversion[stoneRNG.nextInt(sizeConversion.length) / 2]; // Skew the ySize towards
+ // the larger sizes, more
+ // long skinny pipes
+ double zSize = sizeConversion[stoneRNG.nextInt(sizeConversion.length)];
+
+ // Equation for an ellipsoid centered around 0,0,0
+ // Sx, Sy, and Sz are size controls (size = 1/S_)
+ // 1 = full size, 1.333 = 75%, 2 = 50%, 4 = 25%
+ // (x * Sx)^2 + (y * Sy)^2 + (z * sZ)^2 <= (mSize)^2
+
+ // So, we setup the intial boundaries to be the size of the boulder plus a block in each direction
+ int tMinX = tX - (int) (realSize / xSize - 1.0);
+ int tMaxX = tX + (int) (realSize / xSize + 2.0);
+ int tMinY = tY - (int) (realSize / ySize - 1.0);
+ int tMaxY = tY + (int) (realSize / ySize + 2.0);
+ int tMinZ = tZ - (int) (realSize / zSize - 1.0);
+ int tMaxZ = tZ + (int) (realSize / zSize + 2.0);
+
+ // If the (tY-ySize) of the stoneseed is air in the current chunk, mark the seed empty and move on.
+ if (aWorld.getBlock(aChunkX + 8, tMinY, aChunkZ + 8)
+ .isAir(aWorld, aChunkX + 8, tMinY, aChunkZ + 8)) {
+ if (debugStones) GTLog.out.println(
+ mWorldGenName + " tX="
+ + tX
+ + " tY="
+ + tY
+ + " tZ="
+ + tZ
+ + " realSize="
+ + realSize
+ + " xSize="
+ + realSize / xSize
+ + " ySize="
+ + realSize / ySize
+ + " zSize="
+ + realSize / zSize
+ + " tMinY="
+ + tMinY
+ + " tMaxY="
+ + tMaxY
+ + " - Skipped because first requesting chunk would not contain this stone");
+ long hash = (((aWorld.provider.dimensionId & 0xffL) << 56)
+ | (((long) x & 0x000000000fffffffL) << 28)
+ | ((long) z & 0x000000000fffffffL));
+ validStoneSeeds.remove(hash);
+ validStoneSeeds.put(hash, new StoneSeeds(false));
+ }
+
+ // Chop the boundaries by the parts that intersect with the current chunk
+ int wX = Math.max(tMinX, aChunkX + 8);
+ int eX = Math.min(tMaxX, aChunkX + 8 + 16);
+
+ int sZ = Math.max(tMinZ, aChunkZ + 8);
+ int nZ = Math.min(tMaxZ, aChunkZ + 8 + 16);
+
+ if (debugStones) GTLog.out.println(
+ mWorldGenName + " tX="
+ + tX
+ + " tY="
+ + tY
+ + " tZ="
+ + tZ
+ + " realSize="
+ + realSize
+ + " xSize="
+ + realSize / xSize
+ + " ySize="
+ + realSize / ySize
+ + " zSize="
+ + realSize / zSize
+ + " wX="
+ + wX
+ + " eX="
+ + eX
+ + " tMinY="
+ + tMinY
+ + " tMaxY="
+ + tMaxY
+ + " sZ="
+ + sZ
+ + " nZ="
+ + nZ);
+
+ double rightHandSide = realSize * realSize + 1; // Precalc the right hand side
+ for (int iY = tMinY; iY < tMaxY; iY++) { // Do placement from the bottom up layer up. Maybe better on
+ // cache usage?
+ double yCalc = ((double) (iY - tY) * ySize);
+ yCalc = yCalc * yCalc; // (y*Sy)^2
+ double leftHandSize = yCalc;
+ if (leftHandSize > rightHandSide) {
+ continue; // If Y alone is larger than the RHS, skip the rest of the loops
+ }
+ for (int iX = wX; iX < eX; iX++) {
+ double xCalc = ((double) (iX - tX) * xSize);
+ xCalc = xCalc * xCalc;
+ leftHandSize = yCalc + xCalc;
+ if (leftHandSize > rightHandSide) { // Again, if X and Y is larger than the RHS, skip to the
+ // next value
+ continue;
+ }
+ for (int iZ = sZ; iZ < nZ; iZ++) {
+ double zCalc = ((double) (iZ - tZ) * zSize);
+ zCalc = zCalc * zCalc;
+ leftHandSize = zCalc + xCalc + yCalc;
+ if (leftHandSize <= rightHandSide) {
+ // Yay! We can actually place a block now. (this part copied from original code)
+ Block tTargetedBlock = aWorld.getBlock(iX, iY, iZ);
+ if (tTargetedBlock instanceof BlockOresAbstract) {
+ TileEntity tTileEntity = aWorld.getTileEntity(iX, iY, iZ);
+ if ((tTileEntity instanceof TileEntityOres)) {
+ if (tTargetedBlock != GregTechAPI.sBlockOres1) {
+ ((TileEntityOres) tTileEntity).convertOreBlock(aWorld, iX, iY, iZ);
+ }
+ ((TileEntityOres) tTileEntity)
+ .overrideOreBlockMaterial(this.mBlock, (byte) this.mBlockMeta);
+ }
+ } else if (((this.mAllowToGenerateinVoid) && (aWorld.getBlock(iX, iY, iZ)
+ .isAir(aWorld, iX, iY, iZ)))
+ || ((tTargetedBlock != null) && ((tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.stone))
+ || (tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.stained_hardened_clay))
+ || (tTargetedBlock.isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.cobblestone))
+ || (tTargetedBlock.isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.end_stone))
+ || (tTargetedBlock.isReplaceableOreGen(aWorld, iX, iY, iZ, Blocks.netherrack))
+ || (tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, GregTechAPI.sBlockGranites))
+ || (tTargetedBlock
+ .isReplaceableOreGen(aWorld, iX, iY, iZ, GregTechAPI.sBlockStones))))) {
+ aWorld.setBlock(iX, iY, iZ, this.mBlock, this.mBlockMeta, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+}