]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/providers/BedrockCeilingProvider.java
a35d5d6896609bdf4fa54d64ca3e55844819be7e
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / providers / BedrockCeilingProvider.java
1 /*
2 package com.irtimaled.bbor.client.providers;
3
4 import com.irtimaled.bbor.client.Player;
5 import com.irtimaled.bbor.client.config.BoundingBoxTypeHelper;
6 import com.irtimaled.bbor.client.interop.BedrockCeilingHelper;
7 import com.irtimaled.bbor.client.interop.ClientInterop;
8 import com.irtimaled.bbor.client.models.BoundingBoxBedrockCeiling;
9 import com.irtimaled.bbor.common.BoundingBoxType;
10 import com.irtimaled.bbor.common.MathHelper;
11 import com.irtimaled.bbor.common.models.Coords;
12 import com.irtimaled.bbor.common.models.DimensionId;
13
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Map;
18 import java.util.Random;
19 import java.util.Set;
20
21 public class BedrockCeilingProvider implements IBoundingBoxProvider<BoundingBoxBedrockCeiling>, ICachingProvider {
22     private static final double CHUNK_SIZE = 16d;
23     private static Long lastGameTime = null;
24     private static final Map<String, BedrockChunk> chunks = new HashMap<>();
25
26     private static class BedrockChunk {
27         private final Set<BoundingBoxBedrockCeiling> boxes = new HashSet<>();
28
29         public BedrockChunk(int chunkX, int chunkZ) {
30             int chunkStartX = chunkX << 4;
31             int chunkStartZ = chunkZ << 4;
32
33             if (BedrockCeilingHelper.chunkLoaded(chunkX, chunkZ)) findBoxesFromBlockState(chunkStartX, chunkStartZ);
34             else findBoxesFromRNG(chunkX, chunkZ, chunkStartX, chunkStartZ);
35         }
36
37         private void findBoxesFromBlockState(int chunkStartX, int chunkStartZ) {
38             for (int x = 0; x < 16; x++) {
39                 for (int z = 0; z < 16; z++) {
40                     Coords coords = getCoordsFromBlockState(chunkStartX + x, chunkStartZ + z);
41                     if (coords != null) {
42                         boxes.add(new BoundingBoxBedrockCeiling(coords));
43                     }
44                 }
45             }
46         }
47
48         private Coords getCoordsFromBlockState(int x, int z) {
49             Coords coords = null;
50             for (int y = 127; y >= 123; y--) {
51                 if (BedrockCeilingHelper.isBedrock(x, y, z)) {
52                     if (coords == null) {
53                         coords = new Coords(x, y, z);
54                     } else {
55                         return null;
56                     }
57                 }
58             }
59             return coords;
60         }
61
62         private void findBoxesFromRNG(int chunkX, int chunkZ, int chunkStartX, int chunkStartZ) {
63             Random random = BedrockCeilingHelper.getRandomForChunk(chunkX, chunkZ);
64
65             // preseed 16x16x3 calls to nextDouble
66             for (int dummy = 0; dummy < 768; dummy++) {
67                 random.nextDouble();
68             }
69             for (int z = 0; z < 16; z++) {
70                 for (int x = 0; x < 16; x++) {
71                     Coords coords = getBlocksFromRNG(random, chunkStartX + x, chunkStartZ + z);
72
73                     if (coords != null) {
74                         boxes.add(new BoundingBoxBedrockCeiling(coords));
75                     }
76                 }
77             }
78         }
79
80         private Coords getBlocksFromRNG(Random random, int x, int z) {
81             int count = 0;
82             for (int y = 127; y >= 123; y--) {
83                 if (y >= 127 - random.nextInt(5)) {
84                     count++;
85                 }
86             }
87             for (int y = 4; y >= 0; y--) {
88                 random.nextInt(5);
89             }
90             return count == 1 ? new Coords(x, 127, z) : null;
91         }
92
93         public Collection<? extends BoundingBoxBedrockCeiling> getBlocks() {
94             return boxes;
95         }
96
97         public void clear() {
98             boxes.clear();
99         }
100     }
101
102     public void clearCache() {
103         chunks.values().forEach(BedrockChunk::clear);
104         chunks.clear();
105     }
106
107     @Override
108     public Iterable<BoundingBoxBedrockCeiling> get(DimensionId dimensionId) {
109         boolean shouldRecalculate = shouldRecalculate();
110
111         int renderDistanceChunks = ClientInterop.getRenderDistanceChunks() / 2;
112         int playerChunkX = MathHelper.floor(Player.getX() / CHUNK_SIZE);
113         int playerChunkZ = MathHelper.floor(Player.getZ() / CHUNK_SIZE);
114
115         Set<BoundingBoxBedrockCeiling> boxes = new HashSet<>();
116
117         for (int chunkX = playerChunkX - renderDistanceChunks; chunkX <= playerChunkX + renderDistanceChunks; chunkX++) {
118             for (int chunkZ = playerChunkZ - renderDistanceChunks; chunkZ <= playerChunkZ + renderDistanceChunks; chunkZ++) {
119                 String key = String.format("%d,%d", chunkX, chunkZ);
120                 if (shouldRecalculate || !chunks.containsKey(key)) {
121                     chunks.put(key, new BedrockChunk(chunkX, chunkZ));
122                 }
123                 BedrockChunk chunk = chunks.get(key);
124                 boxes.addAll(chunk.getBlocks());
125             }
126         }
127         return boxes;
128     }
129
130     public boolean shouldRecalculate() {
131         long gameTime = ClientInterop.getGameTime();
132         if (!((Long) gameTime).equals(lastGameTime) && gameTime % 2L == 0L) {
133             lastGameTime = gameTime;
134             return true;
135         }
136         return false;
137     }
138
139     @Override
140     public boolean canProvide(DimensionId dimensionId) {
141         return dimensionId == DimensionId.NETHER && BoundingBoxTypeHelper.shouldRender(BoundingBoxType.BedrockCeiling) && Player.getY() > 110;
142     }
143 }
144  */