|
| 1 | +package github.kasuminova.stellarcore.mixin.draconicevolution; |
| 2 | + |
| 3 | +import com.brandon3055.brandonscore.lib.PairXZ; |
| 4 | +import com.brandon3055.brandonscore.registry.ModFeatureParser; |
| 5 | +import com.brandon3055.brandonscore.utils.SimplexNoise; |
| 6 | +import com.brandon3055.brandonscore.utils.Utils; |
| 7 | +import com.brandon3055.draconicevolution.DEConfig; |
| 8 | +import com.brandon3055.draconicevolution.DEFeatures; |
| 9 | +import com.brandon3055.draconicevolution.blocks.tileentity.TileChaosCrystal; |
| 10 | +import com.brandon3055.draconicevolution.world.ChaosWorldGenHandler; |
| 11 | +import net.minecraft.block.Block; |
| 12 | +import net.minecraft.init.Blocks; |
| 13 | +import net.minecraft.util.math.BlockPos; |
| 14 | +import net.minecraft.world.World; |
| 15 | +import org.spongepowered.asm.mixin.Mixin; |
| 16 | +import org.spongepowered.asm.mixin.Overwrite; |
| 17 | + |
| 18 | +import java.util.Random; |
| 19 | + |
| 20 | +import static com.brandon3055.draconicevolution.world.ChaosWorldGenHandler.getClosestChaosSpawn; |
| 21 | + |
| 22 | +@Mixin(ChaosWorldGenHandler.class) |
| 23 | +public class MixinChaosWorldGenHandler { |
| 24 | + |
| 25 | + /** |
| 26 | + * @author sddsd2332 |
| 27 | + * @reason 区块生成 与高版本一致 |
| 28 | + */ |
| 29 | + @Overwrite(remap = false) |
| 30 | + public static void generateChunk(World world, int chunkX, int chunkZ, PairXZ<Integer, Integer> islandCenter, Random random) { |
| 31 | + PairXZ<Integer, Integer> closestSpawn = islandCenter == null ? getClosestChaosSpawn(chunkX, chunkZ) : islandCenter; |
| 32 | + if (closestSpawn.x == 0 && closestSpawn.z == 0) { |
| 33 | + return; |
| 34 | + } |
| 35 | + int posX = chunkX * 16; |
| 36 | + int posZ = chunkZ * 16; |
| 37 | + int copyStartDistance = 180; |
| 38 | + if (Math.abs(posX - closestSpawn.x) > copyStartDistance || Math.abs(posZ - closestSpawn.z) > copyStartDistance) { |
| 39 | + return; |
| 40 | + } |
| 41 | + |
| 42 | + |
| 43 | + if (closestSpawn.x > posX && closestSpawn.x <= posX + 16 && closestSpawn.z > posZ && closestSpawn.z <= posZ + 16) { |
| 44 | + generateStructures(world, closestSpawn, random); |
| 45 | + } |
| 46 | + |
| 47 | + if (!DEConfig.chaosIslandVoidMode) { |
| 48 | + for (int trueX = posX; trueX < posX + 16; trueX++) { |
| 49 | + for (int y = 0; y < 255; y++) { |
| 50 | + for (int trueZ = posZ; trueZ < posZ + 16; trueZ++) { |
| 51 | + int x = trueX - closestSpawn.x; |
| 52 | + int z = trueZ - closestSpawn.z; |
| 53 | + int size = 80; |
| 54 | + double dist = Math.sqrt(x * x + (y - 16) * (y - 16) + z * z); |
| 55 | + double xd, yd, zd; |
| 56 | + double density, centerFalloff, plateauFalloff, heightMapFalloff; |
| 57 | + |
| 58 | + xd = (double) x / size; |
| 59 | + yd = (double) y / (32); |
| 60 | + zd = (double) z / size; |
| 61 | + |
| 62 | + //Calculate Center Falloff |
| 63 | + centerFalloff = 1D / (dist * 0.05D); |
| 64 | + if (centerFalloff < 0) centerFalloff = 0; |
| 65 | + |
| 66 | + //Calculate Plateau Falloff |
| 67 | + if (yd < 0.4D) { |
| 68 | + plateauFalloff = yd * 2.5D; |
| 69 | + } else if (yd <= 0.6D) { |
| 70 | + plateauFalloff = 1D; |
| 71 | + } else if (yd > 0.6D && yd < 1D) { |
| 72 | + plateauFalloff = 1D - (yd - 0.6D) * 2.5D; |
| 73 | + } else { |
| 74 | + plateauFalloff = 0; |
| 75 | + } |
| 76 | + |
| 77 | + //Trim Further calculations |
| 78 | + if (plateauFalloff == 0 || centerFalloff == 0) { |
| 79 | + continue; |
| 80 | + } |
| 81 | + |
| 82 | + //Calculate heightMapFalloff |
| 83 | + heightMapFalloff = 0; |
| 84 | + for (int octave = 1; octave < 5; octave++) { |
| 85 | + heightMapFalloff += ((SimplexNoise.noise(xd * octave + closestSpawn.x, zd * octave + closestSpawn.z) + 1) * 0.5D) * 0.01D * (octave * 10D * 1 - (dist * 0.001D)); |
| 86 | + } |
| 87 | + if (heightMapFalloff <= 0) { |
| 88 | + heightMapFalloff = 0; |
| 89 | + } |
| 90 | + heightMapFalloff += ((0.5D - Math.abs(yd - 0.5D)) * 0.15D); |
| 91 | + if (heightMapFalloff == 0) { |
| 92 | + continue; |
| 93 | + } |
| 94 | + |
| 95 | + density = centerFalloff * plateauFalloff * heightMapFalloff; |
| 96 | + |
| 97 | + BlockPos pos = new BlockPos(x + closestSpawn.x, y + 64 + DEConfig.chaosIslandYOffset, z + closestSpawn.z); |
| 98 | + if (density > 0.1 && (world.isAirBlock(pos) && world.getBlockState(pos).getBlock() != DEFeatures.chaosShardAtmos)) { |
| 99 | + world.setBlockState(pos, (dist > 60 || dist > random.nextInt(60)) ? Blocks.END_STONE.getDefaultState() : Blocks.OBSIDIAN.getDefaultState()); |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + /** |
| 108 | + * @author sddsd2332 |
| 109 | + * @reason 生成核心部分 |
| 110 | + */ |
| 111 | + @Overwrite(remap = false) |
| 112 | + public static void generateStructures(World world, PairXZ<Integer, Integer> islandCenter, Random random) { |
| 113 | + int outerRadius = 330; |
| 114 | + |
| 115 | + //Gen Chaos Cavern |
| 116 | + int shardY = 80 + DEConfig.chaosIslandYOffset; |
| 117 | + int coreHeight = 10; |
| 118 | + int coreWidth = 20; |
| 119 | + for (int y = shardY - coreHeight; y <= shardY + coreHeight; y++) { |
| 120 | + int h = Math.abs(y - shardY); |
| 121 | + int inRadius = h - 3; |
| 122 | + double yp = (coreHeight - h) / (double) coreHeight; |
| 123 | + int outRadius = (int) (yp * coreWidth); |
| 124 | + outRadius -= (outRadius * outRadius) / 100; |
| 125 | + |
| 126 | + genCoreSlice(world, islandCenter.x, y, islandCenter.z, inRadius, shardY, coreWidth, true, random); |
| 127 | + genCoreSlice(world, islandCenter.x, y, islandCenter.z, outRadius, shardY, coreWidth, false, random); |
| 128 | + } |
| 129 | + BlockPos center = new BlockPos(islandCenter.x, shardY, islandCenter.z); |
| 130 | + |
| 131 | + if (ModFeatureParser.isEnabled(DEFeatures.chaosCrystal)) { |
| 132 | + world.setBlockState(center, DEFeatures.chaosCrystal.getDefaultState()); |
| 133 | + TileChaosCrystal tileChaosShard = (TileChaosCrystal) world.getTileEntity(center); |
| 134 | + tileChaosShard.setLockPos(); |
| 135 | + } |
| 136 | + |
| 137 | + } |
| 138 | + |
| 139 | + /** |
| 140 | + * @author sddsd2332 |
| 141 | + * @reason 生成核心外部黑曜石 |
| 142 | + */ |
| 143 | + @Overwrite(remap = false) |
| 144 | + public static void genCoreSlice(World world, int xi, int yi, int zi, int ringRadius, int yc, int coreRadious, boolean fillIn, Random rand) { |
| 145 | + if (DEConfig.chaosIslandVoidMode) return; |
| 146 | + for (int x = xi - coreRadious; x <= xi + coreRadious; x++) { |
| 147 | + for (int z = zi - coreRadious; z <= zi + coreRadious; z++) { |
| 148 | + double dist = Utils.getDistanceAtoB(x, yi, z, xi, yc, zi); |
| 149 | + double oRad = coreRadious - (Math.abs(yc - yi) * Math.abs(yc - yi)) / 10; |
| 150 | + if (dist > oRad - 3D && rand.nextDouble() * 3D < dist - (oRad - 3D)) { |
| 151 | + continue; |
| 152 | + } |
| 153 | + if (fillIn && (int) (Utils.getDistanceAtoB(x, z, xi, zi)) <= ringRadius) { |
| 154 | + if ((int) dist < 9) |
| 155 | + world.setBlockState(new BlockPos(x, yi, z), DEFeatures.infusedObsidian.getDefaultState()); |
| 156 | + else world.setBlockState(new BlockPos(x, yi, z), Blocks.OBSIDIAN.getDefaultState()); |
| 157 | + } else if (!fillIn && (int) (Utils.getDistanceAtoB(x, z, xi, zi)) >= ringRadius) { |
| 158 | + world.setBlockState(new BlockPos(x, yi, z), Blocks.OBSIDIAN.getDefaultState()); |
| 159 | + } else if (!fillIn && (int) Utils.getDistanceAtoB(x, z, xi, zi) <= ringRadius) { |
| 160 | + Block b = world.getBlockState(new BlockPos(x, yi, z)).getBlock(); |
| 161 | + if (b == Blocks.AIR || b == Blocks.END_STONE || b == Blocks.OBSIDIAN) |
| 162 | + world.setBlockState(new BlockPos(x, yi, z), DEFeatures.chaosShardAtmos.getDefaultState()); |
| 163 | + } |
| 164 | + |
| 165 | + } |
| 166 | + } |
| 167 | + } |
| 168 | +} |
0 commit comments