]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/interop/SpawningSphereHelper.java
Change Sphere center to use Point not Coords and Offsets
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / interop / SpawningSphereHelper.java
1 package com.irtimaled.bbor.client.interop;
2
3 import com.irtimaled.bbor.client.models.BoundingBoxSpawningSphere;
4 import com.irtimaled.bbor.common.models.Coords;
5 import com.irtimaled.bbor.common.models.Point;
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;
17
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;
23
24         int blockZ = coords.getZ();
25         int minZ = blockZ - width;
26         int maxZ = blockZ + width;
27
28         int blockY = coords.getY();
29         int minY = blockY - height;
30
31         int centerY = (int) center.getY();
32         int centerYby2 = 2 * centerY;
33
34         WorldClient world = Minecraft.getInstance().world;
35         int processed = 0;
36         for (int x = minX; x < maxX; x++) {
37             for (int z = minZ; z < maxZ; z++) {
38                 if (!isWithinCircle(x, z, center)) continue;
39
40                 if (!isBiomeHostileSpawnable(world, new BlockPos(x, 1, z))) continue;
41
42                 int bottom = centerY;
43                 for (int y = minY; y < centerY; y++) {
44                     if (isWithinSpawnSphere(x, y, z, center)) {
45                         bottom = y;
46                         break;
47                     }
48                 }
49                 int top = (centerYby2 - bottom);
50                 if (top > 255) top = 255;
51                 if (bottom < 1) bottom = 1;
52
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)) {
60                         processed++;
61                     }
62                 }
63             }
64         }
65         return processed;
66     }
67
68     private static boolean isWithinSpawnSphere(int x, int y, int z, Point center) {
69         int x1 = x+1;
70         int z1 = z+1;
71         int y1 = y+1;
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);
77     }
78
79     private static boolean isWithinCircle(int x, int z, Point center) {
80         int x1 = x+1;
81         int z1 = z+1;
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;
86     }
87
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();
92     }
93
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);
106     }
107 }