.registerProvider(new SpawningSphereProvider())
.registerProvider(new BeaconProvider())
.registerProvider(new CustomBoxProvider())
+ .registerProvider(new BiomeBorderProvider())
.registerProvider(new CacheProvider(this::getCache));
KeyListener.init();
SpawningSphereProvider.clear();
BeaconProvider.clear();
CustomBoxProvider.clear();
+ BiomeBorderProvider.clear();
VillageColorCache.clear();
clearCaches();
}
registerRenderer(BoundingBoxMobSpawner.class, new MobSpawnerRenderer());
registerRenderer(BoundingBoxSpawningSphere.class, new SpawningSphereRenderer());
registerRenderer(BoundingBoxBeacon.class, new CuboidRenderer());
+ registerRenderer(BoundingBoxBiomeBorder.class, new BiomeBorderRenderer());
}
public <T extends AbstractBoundingBox> ClientRenderer registerProvider(IBoundingBoxProvider<T> provider) {
(id, x, y, width) -> new BoundingBoxTypeButton(id, x, y, width, "Spawn Sphere", BoundingBoxType.AFKSphere),
(id, x, y, width) -> new BoolSettingButton(id, x, y, width, "Spawnable Blocks", ConfigManager.renderAFKSpawnableBlocks),
(id, x, y, width) -> new IntSettingSlider(id, x, y, width, 1, 3, "Distance", ConfigManager.afkSpawnableBlocksRenderDistance)
+ .addDisplayValue(1, "Nearest")
+ .addDisplayValue(2, "Nearer")
+ .addDisplayValue(3, "Normal"),
+
+ (id, x, y, width) -> new BoundingBoxTypeButton(id, x, y, width, "Biome Borders", BoundingBoxType.BiomeBorder),
+ (id, x, y, width) -> new BoolSettingButton(id, x, y, width, "Only This Biome", ConfigManager.renderOnlyCurrentBiome),
+ (id, x, y, width) -> new IntSettingSlider(id, x, y, width, 1, 3, "Distance", ConfigManager.biomeBordersRenderDistance)
.addDisplayValue(1, "Nearest")
.addDisplayValue(2, "Nearer")
.addDisplayValue(3, "Normal"));
--- /dev/null
+package com.irtimaled.bbor.client.interop;
+
+import com.irtimaled.bbor.common.models.Coords;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.biome.Biome;
+
+public class BiomeBorderHelper {
+ public static int getBiomeId(Coords coords) {
+ return getBiomeId(coords.getX(), coords.getY(), coords.getZ());
+ }
+
+ public static int getBiomeId(int x, int y, int z) {
+ BlockPos pos = new BlockPos(x, y, z);
+ Biome biome = Minecraft.getInstance().world.getBiome(pos);
+ return Biome.getIdForBiome(biome);
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.client.providers;
+
+import com.irtimaled.bbor.client.PlayerCoords;
+import com.irtimaled.bbor.client.interop.BiomeBorderHelper;
+import com.irtimaled.bbor.common.BoundingBoxType;
+import com.irtimaled.bbor.common.MathHelper;
+import com.irtimaled.bbor.common.models.BoundingBoxBiomeBorder;
+import com.irtimaled.bbor.common.models.Coords;
+import com.irtimaled.bbor.config.ConfigManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class BiomeBorderProvider implements IBoundingBoxProvider<BoundingBoxBiomeBorder> {
+ private static Coords lastPlayerCoords = null;
+ private static Boolean lastRenderAllTransitions = null;
+ private static Integer lastRenderDistance = null;
+ private static Map<Coords, BoundingBoxBiomeBorder> lastBorders = new HashMap<>();
+
+ public Iterable<BoundingBoxBiomeBorder> get(int dimensionId) {
+ if (!BoundingBoxType.BiomeBorder.shouldRender())
+ return Iterators.empty();
+
+ Coords playerCoords = PlayerCoords.get();
+ Integer renderDistance = ConfigManager.biomeBordersRenderDistance.get();
+ Boolean renderAllTransitions = !ConfigManager.renderOnlyCurrentBiome.get();
+ if (!playerCoords.equals(lastPlayerCoords) || !renderDistance.equals(lastRenderDistance) || renderAllTransitions != lastRenderAllTransitions) {
+ lastPlayerCoords = playerCoords;
+ lastRenderDistance = renderDistance;
+ lastRenderAllTransitions = renderAllTransitions;
+ lastBorders = getBiomeBorders();
+ }
+ return lastBorders.values();
+ }
+
+ public static void clear() {
+ lastBorders = new HashMap<>();
+ lastPlayerCoords = null;
+ }
+
+ private Map<Coords, BoundingBoxBiomeBorder> getBiomeBorders() {
+ Integer renderDistance = lastRenderDistance;
+ Coords playerCoords = lastPlayerCoords;
+ boolean renderAllTransitions = lastRenderAllTransitions;
+
+ int width = MathHelper.floor(Math.pow(2, 3 + renderDistance));
+ int blockX = playerCoords.getX();
+ int minX = blockX - width;
+ int maxX = blockX + width;
+
+ int blockY = playerCoords.getY();
+
+ int blockZ = playerCoords.getZ();
+ int minZ = blockZ - width;
+ int maxZ = blockZ + width;
+
+ int size = (width * 2) + 1;
+ int[][] biomeIds = new int[size][size];
+ for (int x = minX; x <= maxX; x++) {
+ int matchX = (x - minX);
+ for (int z = minZ; z <= maxZ; z++) {
+ int matchZ = (z - minZ);
+ biomeIds[matchX][matchZ] = BiomeBorderHelper.getBiomeId(x, blockY, z);
+ }
+ }
+
+ int playerBiomeId = BiomeBorderHelper.getBiomeId(playerCoords);
+
+ Map<Coords, BoundingBoxBiomeBorder> borders = new HashMap<>();
+ for (int matchX = 1; matchX < size - 2; matchX++) {
+ for (int matchZ = 1; matchZ < size - 2; matchZ++) {
+ int x = matchX + minX;
+ int z = matchZ + minZ;
+ int biomeId = biomeIds[matchX][matchZ];
+ if (renderAllTransitions || biomeId == playerBiomeId) {
+ Coords coords = new Coords(x, blockY, z);
+ if (lastBorders.containsKey(coords)) {
+ borders.put(coords, lastBorders.get(coords));
+ } else {
+ boolean north = biomeIds[matchX][matchZ - 1] != biomeId;
+ boolean east = biomeIds[matchX + 1][matchZ] != biomeId;
+ boolean south = biomeIds[matchX][matchZ + 1] != biomeId;
+ boolean west = biomeIds[matchX - 1][matchZ] != biomeId;
+ if (north || east || south || west) {
+ borders.put(coords, BoundingBoxBiomeBorder.from(coords, north, east, south, west));
+ }
+ }
+ }
+ }
+ }
+ return borders;
+ }
+}
public abstract void render(T boundingBox);
void renderCuboid(OffsetBox bb, Color color) {
+ OffsetBox nudge = bb.nudge();
if (ConfigManager.fill.get()) {
- renderFilledCuboid(bb, color);
+ renderFilledFaces(nudge.getMin(), nudge.getMax(), color, 30);
}
- renderUnfilledCuboid(bb, color);
+ renderOutlinedCuboid(nudge, color);
}
- private void renderFilledCuboid(OffsetBox bb, Color color) {
- GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
- GL11.glEnable(GL11.GL_BLEND);
- renderCuboid(bb.nudge(), color, 30);
- GL11.glDisable(GL11.GL_BLEND);
- GL11.glEnable(GL11.GL_POLYGON_OFFSET_LINE);
- GL11.glPolygonOffset(-1.f, -1.f);
- }
-
- void renderUnfilledCuboid(OffsetBox bb, Color color) {
+ void renderOutlinedCuboid(OffsetBox bb, Color color) {
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
- renderCuboid(bb.nudge(), color, 255);
+ renderFaces(bb.getMin(), bb.getMax(), color, 255);
}
- private void renderCuboid(OffsetBox box, Color color, int alpha) {
- OffsetPoint min = box.getMin();
- OffsetPoint max = box.getMax();
-
+ private void renderFaces(OffsetPoint min, OffsetPoint max, Color color, int alpha) {
double minX = min.getX();
double minY = min.getY();
double minZ = min.getZ();
Renderer renderer = Renderer.startQuads()
.setColor(color)
- .setAlpha(alpha)
- .addPoint(minX, minY, minZ)
- .addPoint(maxX, minY, minZ)
- .addPoint(maxX, minY, maxZ)
- .addPoint(minX, minY, maxZ);
-
- if (minY != maxY) {
- renderer.addPoint(minX, maxY, minZ)
- .addPoint(maxX, maxY, minZ)
- .addPoint(maxX, maxY, maxZ)
- .addPoint(minX, maxY, maxZ)
+ .setAlpha(alpha);
- .addPoint(minX, minY, maxZ)
- .addPoint(minX, maxY, maxZ)
- .addPoint(maxX, maxY, maxZ)
+ if(minX != maxX && minZ != maxZ) {
+ renderer.addPoint(minX, minY, minZ)
+ .addPoint(maxX, minY, minZ)
.addPoint(maxX, minY, maxZ)
+ .addPoint(minX, minY, maxZ);
- .addPoint(minX, minY, minZ)
- .addPoint(minX, maxY, minZ)
- .addPoint(maxX, maxY, minZ)
- .addPoint(maxX, minY, minZ)
+ if (minY != maxY) {
+ renderer.addPoint(minX, maxY, minZ)
+ .addPoint(maxX, maxY, minZ)
+ .addPoint(maxX, maxY, maxZ)
+ .addPoint(minX, maxY, maxZ);
+ }
+ }
- .addPoint(minX, minY, minZ)
+ if(minX != maxX && minY != maxY) {
+ renderer.addPoint(minX, minY, maxZ)
+ .addPoint(minX, maxY, maxZ)
+ .addPoint(maxX, maxY, maxZ)
+ .addPoint(maxX, minY, maxZ);
+
+ if(minZ != maxZ) {
+ renderer.addPoint(minX, minY, minZ)
+ .addPoint(minX, maxY, minZ)
+ .addPoint(maxX, maxY, minZ)
+ .addPoint(maxX, minY, minZ);
+ }
+ }
+ if(minY != maxY && minZ != maxZ) {
+ renderer.addPoint(minX, minY, minZ)
.addPoint(minX, minY, maxZ)
.addPoint(minX, maxY, maxZ)
- .addPoint(minX, maxY, minZ)
+ .addPoint(minX, maxY, minZ);
- .addPoint(maxX, minY, minZ)
- .addPoint(maxX, minY, maxZ)
- .addPoint(maxX, maxY, maxZ)
- .addPoint(maxX, maxY, minZ);
+ if(minX != maxX) {
+ renderer.addPoint(maxX, minY, minZ)
+ .addPoint(maxX, minY, maxZ)
+ .addPoint(maxX, maxY, maxZ)
+ .addPoint(maxX, maxY, minZ);
+ }
}
renderer.render();
}
.render();
}
+ void renderFilledFaces(OffsetPoint min, OffsetPoint max, Color color, int alpha) {
+ GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
+ GL11.glEnable(GL11.GL_BLEND);
+ renderFaces(min, max, color, alpha);
+ GL11.glDisable(GL11.GL_BLEND);
+ GL11.glEnable(GL11.GL_POLYGON_OFFSET_LINE);
+ GL11.glPolygonOffset(-1.f, -1.f);
+ }
+
void renderText(OffsetPoint offsetPoint, String... texts) {
FontRenderer fontRenderer = Minecraft.getInstance().fontRenderer;
--- /dev/null
+package com.irtimaled.bbor.client.renderers;
+
+import com.irtimaled.bbor.common.models.BoundingBoxBiomeBorder;
+import com.irtimaled.bbor.common.models.Coords;
+import com.irtimaled.bbor.config.ConfigManager;
+
+import java.awt.*;
+
+public class BiomeBorderRenderer extends AbstractRenderer<BoundingBoxBiomeBorder> {
+ @Override
+ public void render(BoundingBoxBiomeBorder boundingBox) {
+ Coords coords = boundingBox.getCoords();
+ OffsetPoint northWest = new OffsetPoint(coords).offset(0, 0.001F, 0);
+ OffsetPoint northEast = northWest.offset(1, 0, 0);
+ OffsetPoint southWest = northWest.offset(0, 0, 1);
+
+ Color color = Color.GREEN;
+ if (boundingBox.renderNorth()) {
+ render(northWest, northEast, color);
+ }
+ if (boundingBox.renderWest()) {
+ render(northWest, southWest, color);
+ }
+ if(ConfigManager.renderOnlyCurrentBiome.get()) {
+ OffsetPoint southEast = southWest.offset(1, 0, 0);
+ if (boundingBox.renderSouth()) {
+ render(southWest, southEast, color);
+ }
+ if (boundingBox.renderEast()) {
+ render(northEast, southEast, color);
+ }
+ }
+ }
+
+ private void render(OffsetPoint topCorner1, OffsetPoint topCorner2, Color color) {
+ double xOffset = 0d;
+ double zOffset = 0d;
+ if(topCorner1.getX() == topCorner2.getX())
+ {
+ xOffset = getOffset(topCorner1.getX());
+ }
+ else
+ {
+ zOffset = getOffset(topCorner1.getZ());
+ }
+
+ topCorner1 = topCorner1.offset(xOffset, 0, zOffset);
+ topCorner2 = topCorner2.offset(xOffset, 0, zOffset);
+
+ renderLine(topCorner1, topCorner2, color);
+ OffsetPoint bottomCorner2 = topCorner2.offset(0, 1, 0);
+ renderFilledFaces(topCorner1, bottomCorner2, color, 30);
+ OffsetPoint bottomCorner1 = topCorner1.offset(0, 1, 0);
+ renderLine(bottomCorner1, bottomCorner2, color);
+ }
+
+ private double getOffset(double value) {
+ return value > 0 ? -0.001F : 0.001F;
+ }
+}
OffsetBox bb = new OffsetBox(offsetCenter, offsetCenter)
.grow(8, 3, 8);
- renderUnfilledCuboid(bb, boundingBox.getColor());
+ renderOutlinedCuboid(bb.nudge(), boundingBox.getColor());
}
private void renderVillageDoors(BoundingBoxVillage boundingBox) {
double y = PlayerCoords.getMaxY(ConfigManager.worldSpawnMaxY.get());
OffsetBox offsetBox = new OffsetBox(minCoords.getX(), y, minCoords.getZ(), maxCoords.getX(), y, maxCoords.getZ());
- renderUnfilledCuboid(offsetBox, color);
+ renderOutlinedCuboid(offsetBox.nudge(), color);
}
}
public final static BoundingBoxType Village = register(Colors.PURPLE, "Village", ConfigManager.drawVillages);
public final static BoundingBoxType VillageSpheres = register(null, "Village Sphere", ConfigManager.drawVillageSpheres);
public final static BoundingBoxType AFKSphere = register(Color.RED, "AFK Sphere", ConfigManager.drawAFKSpheres);
+ public final static BoundingBoxType BiomeBorder = register(Color.GREEN, "Biome Border", ConfigManager.drawBiomeBorders);
public final static BoundingBoxType Beacon = register(Color.WHITE, "Beacon", ConfigManager.drawBeacons);
public final static BoundingBoxType Custom = register(Color.WHITE, "Custom", ConfigManager.drawCustomBoxes);
--- /dev/null
+package com.irtimaled.bbor.common.models;
+
+import com.irtimaled.bbor.common.BoundingBoxType;
+
+public class BoundingBoxBiomeBorder extends AbstractBoundingBox {
+ private final Coords coords;
+ private final boolean north;
+ private final boolean east;
+ private final boolean south;
+ private final boolean west;
+
+ private BoundingBoxBiomeBorder(Coords coords, boolean north, boolean east, boolean south, boolean west) {
+ super(BoundingBoxType.Custom);
+ this.coords = coords;
+ this.north = north;
+ this.east = east;
+ this.south = south;
+ this.west = west;
+ }
+
+ public static BoundingBoxBiomeBorder from(Coords coords, boolean north, boolean east, boolean south, boolean west) {
+ return new BoundingBoxBiomeBorder(coords, north, east, south, west);
+ }
+
+ @Override
+ public Boolean intersectsBounds(int minX, int minZ, int maxX, int maxZ) {
+ return coords.getX() >= minX &&
+ coords.getZ() >= minZ &&
+ coords.getX() <= maxX &&
+ coords.getZ() <= maxZ;
+ }
+
+ public Coords getCoords() {
+ return coords;
+ }
+
+ public boolean renderNorth() {
+ return north;
+ }
+
+ public boolean renderEast() {
+ return east;
+ }
+
+ public boolean renderSouth() {
+ return south;
+ }
+
+ public boolean renderWest() {
+ return west;
+ }
+
+}
public static Setting<Integer> afkSpawnableBlocksRenderDistance;
public static Setting<Boolean> drawBeacons;
public static Setting<Boolean> drawCustomBoxes;
+ public static Setting<Boolean> drawBiomeBorders;
+ public static Setting<Boolean> renderOnlyCurrentBiome;
+ public static Setting<Integer> biomeBordersRenderDistance;
public static void loadConfig(File mcConfigDir) {
configDir = new File(mcConfigDir, "config");
keepCacheBetweenSessions = setup(config, "general", "keepCacheBetweenSessions", false, "If set to true bounding box caches will be kept between sessions.");
drawBeacons = setup(config, "general", "drawBeacons", true, "If set to true beacon bounding boxes will be drawn.");
drawCustomBoxes = setup(config, "general", "drawCustomBoxes", true, "If set to true custom bounding boxes will be drawn.");
+ drawBiomeBorders = setup(config, "biomeBorders", "drawBiomeBorders", true, "If set to true biome borders will be drawn.");
+ renderOnlyCurrentBiome = setup(config, "biomeBorders", "renderOnlyCurrentBiome", true, "If set to true only the biome border for the current biome will be drawn.");
+ biomeBordersRenderDistance = setup(config, "biomeBorders", "biomeBordersRenderDistance", 3, "The distance from the player where biome borders will be drawn.");
drawVillageSpheres = setup(config, "villages", "drawVillageSpheres", true, "If set to true village bounding spheres are drawn.");
drawIronGolemSpawnArea = setup(config, "villages", "drawIronGolemSpawnArea", true, "If set to true the iron golem spawn area of the village will be drawn. (default:true)");