]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/ClientRenderer.java
Fix Z-ordering of boxes
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / ClientRenderer.java
1 package com.irtimaled.bbor.client;
2
3 import com.irtimaled.bbor.client.config.ConfigManager;
4 import com.irtimaled.bbor.client.interop.ClientInterop;
5 import com.irtimaled.bbor.client.models.*;
6 import com.irtimaled.bbor.client.providers.*;
7 import com.irtimaled.bbor.client.renderers.*;
8 import com.irtimaled.bbor.common.MathHelper;
9 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
10 import com.irtimaled.bbor.common.models.BoundingBoxCuboid;
11 import com.irtimaled.bbor.common.models.DimensionId;
12 import org.lwjgl.opengl.GL11;
13
14 import java.util.*;
15 import java.util.stream.Stream;
16
17 public class ClientRenderer {
18     private static final int CHUNK_SIZE = 16;
19     private static final Map<Class<? extends AbstractBoundingBox>, AbstractRenderer> boundingBoxRendererMap = new HashMap<>();
20
21     private static boolean active;
22     private static final Set<IBoundingBoxProvider> providers = new HashSet<>();
23
24     public static boolean getActive() {
25         return active;
26     }
27
28     public static void toggleActive() {
29         active = !active;
30         if (!active) return;
31
32         Player.setActiveY();
33     }
34
35     static void deactivate() {
36         active = false;
37     }
38
39     static {
40         registerRenderer(BoundingBoxSlimeChunk.class, new SlimeChunkRenderer());
41         registerRenderer(BoundingBoxWorldSpawn.class, new WorldSpawnRenderer());
42         registerRenderer(BoundingBoxCuboid.class, new CuboidRenderer());
43         registerRenderer(BoundingBoxMobSpawner.class, new MobSpawnerRenderer());
44         registerRenderer(BoundingBoxSpawningSphere.class, new SpawningSphereRenderer());
45         registerRenderer(BoundingBoxBeacon.class, new BeaconRenderer());
46         registerRenderer(BoundingBoxBiomeBorder.class, new BiomeBorderRenderer());
47         registerRenderer(BoundingBoxConduit.class, new ConduitRenderer());
48         registerRenderer(BoundingBoxSpawnableBlocks.class, new SpawnableBlocksRenderer());
49         registerRenderer(BoundingBoxLine.class, new LineRenderer());
50         registerRenderer(BoundingBoxSphere.class, new SphereRenderer());
51
52         registerProvider(new SlimeChunkProvider());
53         registerProvider(new WorldSpawnProvider());
54         registerProvider(new SpawningSphereProvider());
55         registerProvider(new BeaconProvider());
56         registerProvider(new CustomBoxProvider());
57         registerProvider(new CustomBeaconProvider());
58         registerProvider(new BiomeBorderProvider());
59         registerProvider(new MobSpawnerProvider());
60         registerProvider(new ConduitProvider());
61         registerProvider(new SpawnableBlocksProvider());
62         registerProvider(new CustomLineProvider());
63         registerProvider(new CustomSphereProvider());
64     }
65
66     public static <T extends AbstractBoundingBox> void registerProvider(IBoundingBoxProvider<T> provider) {
67         providers.add(provider);
68     }
69
70     public static <T extends AbstractBoundingBox> void registerRenderer(Class<? extends T> type, AbstractRenderer<T> renderer) {
71         boundingBoxRendererMap.put(type, renderer);
72     }
73
74     private static boolean isWithinRenderDistance(AbstractBoundingBox boundingBox) {
75         int renderDistanceBlocks = ClientInterop.getRenderDistanceChunks() * CHUNK_SIZE;
76         int minX = MathHelper.floor(Player.getX() - renderDistanceBlocks);
77         int maxX = MathHelper.floor(Player.getX() + renderDistanceBlocks);
78         int minZ = MathHelper.floor(Player.getZ() - renderDistanceBlocks);
79         int maxZ = MathHelper.floor(Player.getZ() + renderDistanceBlocks);
80
81         return boundingBox.intersectsBounds(minX, minZ, maxX, maxZ);
82     }
83
84     public static void render(DimensionId dimensionId) {
85         if (!active) return;
86
87         GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
88         GL11.glLineWidth(2.0f);
89         GL11.glDisable(GL11.GL_TEXTURE_2D);
90         GL11.glDisable(GL11.GL_CULL_FACE);
91         GL11.glEnable(GL11.GL_DEPTH_TEST);
92
93         if (ConfigManager.alwaysVisible.get()) {
94             GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
95         }
96
97         getBoundingBoxes(dimensionId).forEach(key -> {
98             AbstractRenderer renderer = boundingBoxRendererMap.get(key.getClass());
99             if (renderer != null) renderer.render(key);
100         });
101
102         GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
103         GL11.glEnable(GL11.GL_CULL_FACE);
104         GL11.glEnable(GL11.GL_TEXTURE_2D);
105     }
106
107     public static Stream<AbstractBoundingBox> getBoundingBoxes(DimensionId dimensionId) {
108         Stream.Builder<AbstractBoundingBox> boundingBoxes = Stream.builder();
109         for (IBoundingBoxProvider<?> provider : providers) {
110             if (provider.canProvide(dimensionId)) {
111                 for (AbstractBoundingBox boundingBox : provider.get(dimensionId)) {
112                     if (isWithinRenderDistance(boundingBox)) {
113                         boundingBoxes.accept(boundingBox);
114                     }
115                 }
116             }
117         }
118
119         Point point = Player.getPoint();
120         return boundingBoxes.build()
121                 .sorted(Comparator
122                         .comparingDouble((AbstractBoundingBox boundingBox) -> boundingBox.getDistance(point.getX(), point.getY(), point.getZ())).reversed());
123     }
124
125 }