diff options
author | NotAPenguin <michiel.vandeginste@gmail.com> | 2024-09-02 23:17:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-02 23:17:17 +0200 |
commit | 1b820de08a05070909a267e17f033fcf58ac8710 (patch) | |
tree | 02831a025986a06b20f87e5bcc69d1e0c639a342 /src/main/java/gregtech/common/WorldgenStone.java | |
parent | afd3fd92b6a6ab9ab0d0dc3214e6bc8ff7a86c9b (diff) | |
download | GT5-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.java | 297 |
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; + } +} |