1 package com.irtimaled.bbor.client;
3 import com.irtimaled.bbor.client.interop.ClientInterop;
4 import com.irtimaled.bbor.client.models.BoundingBoxBeacon;
5 import com.irtimaled.bbor.client.models.BoundingBoxBedrockCeiling;
6 import com.irtimaled.bbor.client.models.BoundingBoxBiomeBorder;
7 import com.irtimaled.bbor.client.models.BoundingBoxConduit;
8 import com.irtimaled.bbor.client.models.BoundingBoxFlowerForest;
9 import com.irtimaled.bbor.client.models.BoundingBoxLine;
10 import com.irtimaled.bbor.client.models.BoundingBoxMobSpawner;
11 import com.irtimaled.bbor.client.models.BoundingBoxSlimeChunk;
12 import com.irtimaled.bbor.client.models.BoundingBoxSpawnableBlocks;
13 import com.irtimaled.bbor.client.models.BoundingBoxSpawningSphere;
14 import com.irtimaled.bbor.client.models.BoundingBoxSphere;
15 import com.irtimaled.bbor.client.models.BoundingBoxWorldSpawn;
16 import com.irtimaled.bbor.client.models.Point;
17 import com.irtimaled.bbor.client.providers.BeaconProvider;
18 import com.irtimaled.bbor.client.providers.BedrockCeilingProvider;
19 import com.irtimaled.bbor.client.providers.BiomeBorderProvider;
20 import com.irtimaled.bbor.client.providers.ConduitProvider;
21 import com.irtimaled.bbor.client.providers.CustomBeaconProvider;
22 import com.irtimaled.bbor.client.providers.CustomBoxProvider;
23 import com.irtimaled.bbor.client.providers.CustomLineProvider;
24 import com.irtimaled.bbor.client.providers.CustomSphereProvider;
25 import com.irtimaled.bbor.client.providers.FlowerForestProvider;
26 import com.irtimaled.bbor.client.providers.IBoundingBoxProvider;
27 import com.irtimaled.bbor.client.providers.ICachingProvider;
28 import com.irtimaled.bbor.client.providers.MobSpawnerProvider;
29 import com.irtimaled.bbor.client.providers.SlimeChunkProvider;
30 import com.irtimaled.bbor.client.providers.SpawnableBlocksProvider;
31 import com.irtimaled.bbor.client.providers.SpawningSphereProvider;
32 import com.irtimaled.bbor.client.providers.WorldSpawnProvider;
33 import com.irtimaled.bbor.client.renderers.AbstractRenderer;
34 import com.irtimaled.bbor.client.renderers.BeaconRenderer;
35 import com.irtimaled.bbor.client.renderers.BiomeBorderRenderer;
36 import com.irtimaled.bbor.client.renderers.ConduitRenderer;
37 import com.irtimaled.bbor.client.renderers.CuboidRenderer;
38 import com.irtimaled.bbor.client.renderers.FlowerForestRenderer;
39 import com.irtimaled.bbor.client.renderers.LineRenderer;
40 import com.irtimaled.bbor.client.renderers.MobSpawnerRenderer;
41 import com.irtimaled.bbor.client.renderers.RenderHelper;
42 import com.irtimaled.bbor.client.renderers.RenderQueue;
43 import com.irtimaled.bbor.client.renderers.SlimeChunkRenderer;
44 import com.irtimaled.bbor.client.renderers.SpawnableBlocksRenderer;
45 import com.irtimaled.bbor.client.renderers.SpawningSphereRenderer;
46 import com.irtimaled.bbor.client.renderers.SphereRenderer;
47 import com.irtimaled.bbor.client.renderers.WorldSpawnRenderer;
48 import com.irtimaled.bbor.common.MathHelper;
49 import com.irtimaled.bbor.common.TypeHelper;
50 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
51 import com.irtimaled.bbor.common.models.BoundingBoxCuboid;
52 import com.irtimaled.bbor.common.models.DimensionId;
53 import net.minecraft.client.util.math.MatrixStack;
55 import java.util.Comparator;
56 import java.util.HashMap;
57 import java.util.HashSet;
60 import java.util.stream.Stream;
62 public class ClientRenderer {
63 private static final int CHUNK_SIZE = 16;
64 private static final Map<Class<? extends AbstractBoundingBox>, AbstractRenderer> boundingBoxRendererMap = new HashMap<>();
66 private static boolean active;
67 private static final Set<IBoundingBoxProvider> providers = new HashSet<>();
69 public static boolean getActive() {
73 public static void toggleActive() {
80 static void deactivate() {
85 registerRenderer(BoundingBoxSlimeChunk.class, new SlimeChunkRenderer());
86 registerRenderer(BoundingBoxWorldSpawn.class, new WorldSpawnRenderer());
87 registerRenderer(BoundingBoxCuboid.class, new CuboidRenderer());
88 registerRenderer(BoundingBoxMobSpawner.class, new MobSpawnerRenderer());
89 registerRenderer(BoundingBoxSpawningSphere.class, new SpawningSphereRenderer());
90 registerRenderer(BoundingBoxBeacon.class, new BeaconRenderer());
91 registerRenderer(BoundingBoxBiomeBorder.class, new BiomeBorderRenderer());
92 registerRenderer(BoundingBoxConduit.class, new ConduitRenderer());
93 registerRenderer(BoundingBoxSpawnableBlocks.class, new SpawnableBlocksRenderer());
94 registerRenderer(BoundingBoxLine.class, new LineRenderer());
95 registerRenderer(BoundingBoxSphere.class, new SphereRenderer());
96 registerRenderer(BoundingBoxFlowerForest.class, new FlowerForestRenderer());
97 registerRenderer(BoundingBoxBedrockCeiling.class, new CuboidRenderer());
99 registerProvider(new SlimeChunkProvider());
100 registerProvider(new WorldSpawnProvider());
101 registerProvider(new SpawningSphereProvider());
102 registerProvider(new BeaconProvider());
103 registerProvider(new CustomBoxProvider());
104 registerProvider(new CustomBeaconProvider());
105 registerProvider(new BiomeBorderProvider());
106 registerProvider(new MobSpawnerProvider());
107 registerProvider(new ConduitProvider());
108 registerProvider(new SpawnableBlocksProvider());
109 registerProvider(new CustomLineProvider());
110 registerProvider(new CustomSphereProvider());
111 registerProvider(new FlowerForestProvider());
112 registerProvider(new BedrockCeilingProvider());
115 public static <T extends AbstractBoundingBox> void registerProvider(IBoundingBoxProvider<T> provider) {
116 providers.add(provider);
119 public static <T extends AbstractBoundingBox> void registerRenderer(Class<? extends T> type, AbstractRenderer<T> renderer) {
120 boundingBoxRendererMap.put(type, renderer);
123 private static boolean isWithinRenderDistance(AbstractBoundingBox boundingBox) {
124 int renderDistanceBlocks = ClientInterop.getRenderDistanceChunks() * CHUNK_SIZE;
125 int minX = MathHelper.floor(Player.getX() - renderDistanceBlocks);
126 int maxX = MathHelper.floor(Player.getX() + renderDistanceBlocks);
127 int minZ = MathHelper.floor(Player.getZ() - renderDistanceBlocks);
128 int maxZ = MathHelper.floor(Player.getZ() + renderDistanceBlocks);
130 return boundingBox.intersectsBounds(minX, minZ, maxX, maxZ);
133 public static void render(MatrixStack matrixStack, DimensionId dimensionId) {
137 RenderHelper.beforeRender();
139 getBoundingBoxes(dimensionId).forEach(key -> {
140 AbstractRenderer renderer = boundingBoxRendererMap.get(key.getClass());
141 if (renderer != null) renderer.render(matrixStack, key);
144 RenderHelper.afterRender();
148 public static void renderDeferred() {
149 RenderHelper.beforeRender();
150 RenderHelper.polygonModeFill();
151 RenderHelper.enableBlend();
152 RenderQueue.renderDeferred();
153 RenderHelper.disableBlend();
154 RenderHelper.enablePolygonOffsetLine();
155 RenderHelper.polygonOffsetMinusOne();
156 RenderHelper.afterRender();
159 public static Stream<AbstractBoundingBox> getBoundingBoxes(DimensionId dimensionId) {
160 Stream.Builder<AbstractBoundingBox> boundingBoxes = Stream.builder();
161 for (IBoundingBoxProvider<?> provider : providers) {
162 if (provider.canProvide(dimensionId)) {
163 for (AbstractBoundingBox boundingBox : provider.get(dimensionId)) {
164 if (isWithinRenderDistance(boundingBox)) {
165 boundingBoxes.accept(boundingBox);
171 Point point = Player.getPoint();
172 return boundingBoxes.build()
174 .comparingDouble((AbstractBoundingBox boundingBox) -> boundingBox.getDistance(point.getX(), point.getY(), point.getZ())).reversed());
177 public static void clear() {
178 for(IBoundingBoxProvider<?> provider : providers) {
179 TypeHelper.doIfType(provider, ICachingProvider.class, ICachingProvider::clearCache);