1 package com.irtimaled.bbor.client.interop;
3 import com.irtimaled.bbor.client.models.Point;
4 import com.irtimaled.bbor.common.models.BoundingBoxSpawningSphere;
5 import com.irtimaled.bbor.common.models.Coords;
6 import net.minecraft.block.Block;
7 import net.minecraft.block.state.IBlockState;
8 import net.minecraft.client.Minecraft;
9 import net.minecraft.client.multiplayer.WorldClient;
10 import net.minecraft.entity.EnumCreatureType;
11 import net.minecraft.init.Blocks;
12 import net.minecraft.tags.BlockTags;
13 import net.minecraft.util.EnumFacing;
14 import net.minecraft.util.math.BlockPos;
15 import net.minecraft.world.EnumLightType;
16 import net.minecraft.world.biome.Biome;
18 public class SpawningSphereHelper {
19 public static int findSpawnableSpaces(Point center, Coords coords, int width, int height, BlockProcessor blockProcessor) {
20 int blockX = coords.getX();
21 int minX = blockX - width;
22 int maxX = blockX + width;
24 int blockZ = coords.getZ();
25 int minZ = blockZ - width;
26 int maxZ = blockZ + width;
28 int blockY = coords.getY();
29 int minY = blockY - height;
31 int centerY = (int) center.getY();
32 int centerYby2 = 2 * centerY;
34 WorldClient world = Minecraft.getInstance().world;
36 for (int x = minX; x < maxX; x++) {
37 for (int z = minZ; z < maxZ; z++) {
38 if (!isWithinCircle(x, z, center)) continue;
40 if (!isBiomeHostileSpawnable(world, new BlockPos(x, 1, z))) continue;
43 for (int y = minY; y < centerY; y++) {
44 if (isWithinSpawnSphere(x, y, z, center)) {
49 int top = (centerYby2 - bottom);
50 if (top > 255) top = 255;
51 if (bottom < 1) bottom = 1;
53 IBlockState upperBlockState = world.getBlockState(new BlockPos(x, bottom - 1, z));
54 for (int y = Math.max(1, bottom); y < top; y++) {
55 IBlockState spawnBlockState = upperBlockState;
56 BlockPos pos = new BlockPos(x, y, z);
57 upperBlockState = world.getBlockState(pos);
58 if (isSpawnable(world, pos, spawnBlockState, upperBlockState) &&
59 blockProcessor.process(x, y, z)) {
68 private static boolean isWithinSpawnSphere(int x, int y, int z, Point center) {
72 int closestX = Math.abs(center.getX()-x) < Math.abs(center.getX()-x1) ? x : x1;
73 int closestY = Math.abs(center.getY()-y) < Math.abs(center.getY()-y1) ? y : y1;
74 int closestZ = Math.abs(center.getZ()-z) < Math.abs(center.getZ()-z1) ? z : z1;
75 double distance = center.getDistance(new Point(closestX, closestY, closestZ));
76 return distance <= BoundingBoxSpawningSphere.SPAWN_RADIUS && distance >= (BoundingBoxSpawningSphere.SAFE_RADIUS-1);
79 private static boolean isWithinCircle(int x, int z, Point center) {
82 int closestX = Math.abs(center.getX()-x) < Math.abs(center.getX()-x1) ? x : x1;
83 int closestZ = Math.abs(center.getZ()-z) < Math.abs(center.getZ()-z1) ? z : z1;
84 double distance = center.getDistance(new Point(closestX, center.getY(), closestZ));
85 return distance <= BoundingBoxSpawningSphere.SPAWN_RADIUS;
88 private static boolean isBiomeHostileSpawnable(WorldClient world, BlockPos pos) {
89 Biome biome = world.getBiome(pos);
90 return biome.getSpawningChance() > 0 &&
91 !biome.getSpawns(EnumCreatureType.MONSTER).isEmpty();
94 private static boolean isSpawnable(WorldClient world, BlockPos pos, IBlockState spawnBlockState, IBlockState upperBlockState) {
95 Block spawnBlock = spawnBlockState.getBlock();
96 return spawnBlock != Blocks.AIR &&
97 spawnBlock != Blocks.BEDROCK &&
98 spawnBlock != Blocks.BARRIER &&
99 spawnBlockState.isTopSolid() &&
100 !upperBlockState.isBlockNormalCube() &&
101 !upperBlockState.canProvidePower() &&
102 !upperBlockState.isIn(BlockTags.RAILS) &&
103 upperBlockState.getCollisionShape(world, pos).getEnd(EnumFacing.Axis.Y) <= 0 &&
104 upperBlockState.getFluidState().isEmpty() &&
105 (world.dimension.isNether() || world.getLightFor(EnumLightType.BLOCK, pos) <= 7);