From fb30dd54841c940ad19181b688add8c520561d1c Mon Sep 17 00:00:00 2001 From: Irtimaled Date: Sun, 10 May 2020 02:28:19 -0700 Subject: [PATCH] Add support for spawnable blocks rendering --- .../irtimaled/bbor/client/ClientRenderer.java | 2 + .../client/config/BoundingBoxTypeHelper.java | 1 + .../bbor/client/config/ConfigManager.java | 7 ++ .../bbor/client/gui/SettingsScreen.java | 10 +++ .../client/interop/SpawnableBlocksHelper.java | 67 +++++++++++++++++++ .../models/BoundingBoxSpawnableBlocks.java | 25 +++++++ .../models/BoundingBoxSpawningSphere.java | 4 ++ .../providers/SpawnableBlocksProvider.java | 62 +++++++++++++++++ .../providers/SpawningSphereProvider.java | 10 ++- .../renderers/SpawnableBlocksRenderer.java | 16 +++++ .../bbor/common/BoundingBoxType.java | 1 + .../resources/assets/bbor/lang/en_us.json | 3 + 12 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/irtimaled/bbor/client/interop/SpawnableBlocksHelper.java create mode 100644 src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawnableBlocks.java create mode 100644 src/main/java/com/irtimaled/bbor/client/providers/SpawnableBlocksProvider.java create mode 100644 src/main/java/com/irtimaled/bbor/client/renderers/SpawnableBlocksRenderer.java diff --git a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java index 6672c69..6dedcf3 100644 --- a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java +++ b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java @@ -48,6 +48,7 @@ public class ClientRenderer { registerRenderer(BoundingBoxBeacon.class, new BeaconRenderer()); registerRenderer(BoundingBoxBiomeBorder.class, new BiomeBorderRenderer()); registerRenderer(BoundingBoxConduit.class, new ConduitRenderer()); + registerRenderer(BoundingBoxSpawnableBlocks.class, new SpawnableBlocksRenderer()); registerProvider(new SlimeChunkProvider()); registerProvider(new WorldSpawnProvider()); @@ -58,6 +59,7 @@ public class ClientRenderer { registerProvider(new BiomeBorderProvider()); registerProvider(new MobSpawnerProvider()); registerProvider(new ConduitProvider()); + registerProvider(new SpawnableBlocksProvider()); } public static void registerProvider(IBoundingBoxProvider provider) { diff --git a/src/main/java/com/irtimaled/bbor/client/config/BoundingBoxTypeHelper.java b/src/main/java/com/irtimaled/bbor/client/config/BoundingBoxTypeHelper.java index 084652f..212056f 100644 --- a/src/main/java/com/irtimaled/bbor/client/config/BoundingBoxTypeHelper.java +++ b/src/main/java/com/irtimaled/bbor/client/config/BoundingBoxTypeHelper.java @@ -22,6 +22,7 @@ public class BoundingBoxTypeHelper { registerType(BoundingBoxType.BiomeBorder, ConfigManager.drawBiomeBorders); registerType(BoundingBoxType.Beacon, ConfigManager.drawBeacons); registerType(BoundingBoxType.Conduit, ConfigManager.drawConduits); + registerType(BoundingBoxType.SpawnableBlocks, ConfigManager.drawSpawnableBlocks); registerType(BoundingBoxType.JungleTemple, ConfigManager.drawJungleTemples); registerType(BoundingBoxType.DesertTemple, ConfigManager.drawDesertTemples); diff --git a/src/main/java/com/irtimaled/bbor/client/config/ConfigManager.java b/src/main/java/com/irtimaled/bbor/client/config/ConfigManager.java index d6c301c..13773de 100644 --- a/src/main/java/com/irtimaled/bbor/client/config/ConfigManager.java +++ b/src/main/java/com/irtimaled/bbor/client/config/ConfigManager.java @@ -53,6 +53,9 @@ public class ConfigManager { public static Setting drawRuinedPortals; public static Setting drawConduits; public static Setting renderConduitMobHarmArea; + public static Setting drawSpawnableBlocks; + public static Setting spawnableBlocksRenderWidth; + public static Setting spawnableBlocksRenderHeight; public static void loadConfig() { configDir = new File(".", "config"); @@ -114,6 +117,10 @@ public class ConfigManager { renderAFKSpawnableBlocks = setup(config, "afkSpot", "renderAFKSpawnableBlocks", true, "If set to true boxes to show spawnable blocks within the AFK sphere will be drawn."); afkSpawnableBlocksRenderDistance = setup(config, "afkSpot", "afkSpawnableBlocksRenderDistance", 3, "The distance from the player where spawnable blocks within the AFK sphere will be drawn."); + drawSpawnableBlocks = setup(config, "spawnableBlocks", "drawSpawnableBlocks", false, "If set to true boxes to show spawnable blocks will be drawn."); + spawnableBlocksRenderWidth = setup(config, "spawnableBlocks", "spawnableBlocksRenderWidth", 2, "The distance from the player where spawnable blocks will be drawn in X and Z axis."); + spawnableBlocksRenderHeight = setup(config, "spawnableBlocks", "spawnableBlocksRenderHeight", 1, "The distance from the player where spawnable blocks will be drawn in Y axis."); + config.save(); } diff --git a/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java b/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java index 92da9ec..d336685 100644 --- a/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java +++ b/src/main/java/com/irtimaled/bbor/client/gui/SettingsScreen.java @@ -69,6 +69,16 @@ public class SettingsScreen extends ListScreen { (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.beacons"), BoundingBoxType.Beacon), (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.conduits"), BoundingBoxType.Conduit), (x, width) -> new BoolSettingButton(width, I18n.format("bbor.features.conduits.mobHarmArea"), ConfigManager.renderConduitMobHarmArea)) + .section(I18n.format("bbor.features.spawnableBlocks"), + (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawnableBlocks"), BoundingBoxType.SpawnableBlocks), + (x, width) -> new IntSettingSlider(width, 1, 3, "bbor.options.distance.y", ConfigManager.spawnableBlocksRenderHeight) + .addDisplayValue(1, "2") + .addDisplayValue(2, "4") + .addDisplayValue(3, "8"), + (x, width) -> new IntSettingSlider(width, 1, 3, "bbor.options.distance.xz", ConfigManager.spawnableBlocksRenderWidth) + .addDisplayValue(1, "8") + .addDisplayValue(2, "16") + .addDisplayValue(3, "32")) .section(I18n.format("bbor.features.spawningSpheres"), (x, width) -> new BoundingBoxTypeButton(width, I18n.format("bbor.features.spawningSpheres"), BoundingBoxType.AFKSphere), (x, width) -> new BoolSettingButton(width, I18n.format("bbor.features.spawningSpheres.spawnableBlocks"), ConfigManager.renderAFKSpawnableBlocks), diff --git a/src/main/java/com/irtimaled/bbor/client/interop/SpawnableBlocksHelper.java b/src/main/java/com/irtimaled/bbor/client/interop/SpawnableBlocksHelper.java new file mode 100644 index 0000000..f781a6c --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/interop/SpawnableBlocksHelper.java @@ -0,0 +1,67 @@ +package com.irtimaled.bbor.client.interop; + +import com.irtimaled.bbor.common.models.Coords; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.init.Blocks; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.EnumLightType; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; + +public class SpawnableBlocksHelper { + public static void findSpawnableBlocks(Coords coords, int width, int height, BlockProcessor blockProcessor) { + int blockX = coords.getX(); + int minX = blockX - width; + int maxX = blockX + width + 1; + + int blockZ = coords.getZ(); + int minZ = blockZ - width; + int maxZ = blockZ + width + 1; + + int blockY = coords.getY(); + int minY = Math.max(1, blockY - height); + int maxY = Math.min(255, blockY + height); + + World world = Minecraft.getInstance().world; + for (int x = minX; x < maxX; x++) { + for (int z = minZ; z < maxZ; z++) { + if (isBiomeHostileSpawnProof(world, new BlockPos(x, 1, z))) continue; + + IBlockState upperBlockState = world.getBlockState(new BlockPos(x, minY - 1, z)); + for (int y = Math.max(1, minY); y < maxY; y++) { + IBlockState spawnBlockState = upperBlockState; + BlockPos pos = new BlockPos(x, y, z); + upperBlockState = world.getBlockState(pos); + if (isSpawnable(world, pos, spawnBlockState, upperBlockState)) { + blockProcessor.process(x, y, z); + } + } + } + } + } + + static boolean isBiomeHostileSpawnProof(World world, BlockPos pos) { + Biome biome = world.getBiome(pos); + return biome.getSpawningChance() == 0 || + biome.getSpawns(EnumCreatureType.MONSTER).isEmpty(); + } + + static boolean isSpawnable(World world, BlockPos pos, IBlockState spawnBlockState, IBlockState upperBlockState) { + Block spawnBlock = spawnBlockState.getBlock(); + return spawnBlock != Blocks.AIR && + spawnBlock != Blocks.BEDROCK && + spawnBlock != Blocks.BARRIER && + spawnBlockState.isTopSolid() && + !upperBlockState.isBlockNormalCube() && + !upperBlockState.canProvidePower() && + !upperBlockState.isIn(BlockTags.RAILS) && + upperBlockState.getCollisionShape(world, pos).getEnd(EnumFacing.Axis.Y) <= 0 && + upperBlockState.getFluidState().isEmpty() && + (world.dimension.isNether() || world.getLightFor(EnumLightType.BLOCK, pos) <= 7); + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawnableBlocks.java b/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawnableBlocks.java new file mode 100644 index 0000000..8f3a4d5 --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawnableBlocks.java @@ -0,0 +1,25 @@ +package com.irtimaled.bbor.client.models; + +import com.irtimaled.bbor.common.BoundingBoxType; +import com.irtimaled.bbor.common.models.AbstractBoundingBox; +import com.irtimaled.bbor.common.models.Coords; + +import java.util.HashSet; +import java.util.Set; + +public class BoundingBoxSpawnableBlocks extends AbstractBoundingBox { + private final Set blocks = new HashSet<>(); + + public BoundingBoxSpawnableBlocks() { + super(BoundingBoxType.SpawnableBlocks); + } + + public Set getBlocks() { + return blocks; + } + + @Override + public Boolean intersectsBounds(int minX, int minZ, int maxX, int maxZ) { + return true; + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawningSphere.java b/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawningSphere.java index 8229e97..a7d5948 100644 --- a/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawningSphere.java +++ b/src/main/java/com/irtimaled/bbor/client/models/BoundingBoxSpawningSphere.java @@ -14,6 +14,10 @@ public class BoundingBoxSpawningSphere extends BoundingBoxSphere { super(point, SPAWN_RADIUS, BoundingBoxType.AFKSphere); } + public boolean isWithinSphere(Point point) { + return this.getPoint().getDistance(point) <= getRadius() + 0.5D; + } + public void setSpawnableCount(int count) { this.spawnableCount = count; } diff --git a/src/main/java/com/irtimaled/bbor/client/providers/SpawnableBlocksProvider.java b/src/main/java/com/irtimaled/bbor/client/providers/SpawnableBlocksProvider.java new file mode 100644 index 0000000..4f3704e --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/providers/SpawnableBlocksProvider.java @@ -0,0 +1,62 @@ +package com.irtimaled.bbor.client.providers; + +import com.irtimaled.bbor.client.Player; +import com.irtimaled.bbor.client.config.BoundingBoxTypeHelper; +import com.irtimaled.bbor.client.config.ConfigManager; +import com.irtimaled.bbor.client.interop.SpawnableBlocksHelper; +import com.irtimaled.bbor.client.models.BoundingBoxSpawnableBlocks; +import com.irtimaled.bbor.common.BoundingBoxType; +import com.irtimaled.bbor.common.MathHelper; +import com.irtimaled.bbor.common.models.Coords; +import net.minecraft.client.Minecraft; + +import java.util.HashSet; +import java.util.Set; + +public class SpawnableBlocksProvider implements IBoundingBoxProvider { + public static final Minecraft minecraft = Minecraft.getInstance(); + private static Long lastGameTime = null; + + private static Set lastBoundingBox = null; + + public static void clear() { + lastBoundingBox = null; + } + + private boolean isWithinActiveSpawningSphere() { + return BoundingBoxTypeHelper.shouldRender(BoundingBoxType.AFKSphere) && + ConfigManager.renderAFKSpawnableBlocks.get() && + SpawningSphereProvider.playerInsideSphere(); + } + + @Override + public boolean canProvide(int dimensionId) { + return BoundingBoxTypeHelper.shouldRender(BoundingBoxType.SpawnableBlocks) && + !isWithinActiveSpawningSphere(); + } + + @Override + public Iterable get(int dimensionId) { + long gameTime = minecraft.world.getGameTime(); + if (lastBoundingBox == null || (!((Long) gameTime).equals(lastGameTime) && gameTime % 2L == 0L)) { + lastGameTime = gameTime; + lastBoundingBox = getSpawnableBlocks(); + } + return lastBoundingBox; + } + + private Set getSpawnableBlocks() { + BoundingBoxSpawnableBlocks boundingBox = new BoundingBoxSpawnableBlocks(); + Set blocks = boundingBox.getBlocks(); + + int width = MathHelper.floor(Math.pow(2, 1 + ConfigManager.spawnableBlocksRenderWidth.get())); + int height = MathHelper.floor(Math.pow(2, ConfigManager.spawnableBlocksRenderHeight.get())); + + SpawnableBlocksHelper.findSpawnableBlocks(Player.getCoords(), width, height, + (x, y, z) -> blocks.add(new Coords(x, y, z))); + + Set boundingBoxes = new HashSet<>(); + boundingBoxes.add(boundingBox); + return boundingBoxes; + } +} diff --git a/src/main/java/com/irtimaled/bbor/client/providers/SpawningSphereProvider.java b/src/main/java/com/irtimaled/bbor/client/providers/SpawningSphereProvider.java index 1efd41e..00c2482 100644 --- a/src/main/java/com/irtimaled/bbor/client/providers/SpawningSphereProvider.java +++ b/src/main/java/com/irtimaled/bbor/client/providers/SpawningSphereProvider.java @@ -58,9 +58,17 @@ public class SpawningSphereProvider implements IBoundingBoxProvider true); } + static boolean playerInsideSphere() { + return spawningSphereInDimension(Player.getDimensionId()) && spawningSphere.isWithinSphere(Player.getPoint()); + } + + private static boolean spawningSphereInDimension(int dimensionId) { + return spawningSphere != null && SpawningSphereProvider.dimensionId == dimensionId; + } + @Override public boolean canProvide(int dimensionId) { - return spawningSphere != null && SpawningSphereProvider.dimensionId == dimensionId && BoundingBoxTypeHelper.shouldRender(BoundingBoxType.AFKSphere); + return spawningSphereInDimension(dimensionId) && BoundingBoxTypeHelper.shouldRender(BoundingBoxType.AFKSphere); } @Override diff --git a/src/main/java/com/irtimaled/bbor/client/renderers/SpawnableBlocksRenderer.java b/src/main/java/com/irtimaled/bbor/client/renderers/SpawnableBlocksRenderer.java new file mode 100644 index 0000000..504ce3f --- /dev/null +++ b/src/main/java/com/irtimaled/bbor/client/renderers/SpawnableBlocksRenderer.java @@ -0,0 +1,16 @@ +package com.irtimaled.bbor.client.renderers; + +import com.irtimaled.bbor.client.models.BoundingBoxSpawnableBlocks; + +public class SpawnableBlocksRenderer extends AbstractRenderer { + @Override + public void render(BoundingBoxSpawnableBlocks boundingBox) { + boundingBox.getBlocks().forEach(c -> { + int x = c.getX(); + int y = c.getY(); + int z = c.getZ(); + OffsetBox offsetBox = new OffsetBox(x, y, z, x + 1, y, z + 1); + renderCuboid(offsetBox, boundingBox.getColor()); + }); + } +} diff --git a/src/main/java/com/irtimaled/bbor/common/BoundingBoxType.java b/src/main/java/com/irtimaled/bbor/common/BoundingBoxType.java index ecb1287..51fe9b6 100644 --- a/src/main/java/com/irtimaled/bbor/common/BoundingBoxType.java +++ b/src/main/java/com/irtimaled/bbor/common/BoundingBoxType.java @@ -19,6 +19,7 @@ public class BoundingBoxType { public static final BoundingBoxType Custom = register(Color.WHITE, "Custom"); public static final BoundingBoxType Beacon = register(Color.WHITE, "Beacon"); public static final BoundingBoxType Conduit = register(Color.CYAN, "Conduit"); + public static final BoundingBoxType SpawnableBlocks = register(Color.RED, "Spawnable Blocks"); public static final BoundingBoxType JungleTemple = register(Colors.DARK_GREEN, "Jungle_Pyramid"); public static final BoundingBoxType DesertTemple = register(Color.ORANGE, "Desert_Pyramid"); diff --git a/src/main/resources/assets/bbor/lang/en_us.json b/src/main/resources/assets/bbor/lang/en_us.json index dea0e63..56dcbda 100644 --- a/src/main/resources/assets/bbor/lang/en_us.json +++ b/src/main/resources/assets/bbor/lang/en_us.json @@ -17,6 +17,8 @@ "bbor.options.distance.nearest": "Nearest", "bbor.options.distance.nearer": "Nearer", "bbor.options.distance.normal": "Normal", + "bbor.options.distance.y": "Distance (Y): %s", + "bbor.options.distance.xz": "Distance (X/Z): %s", "bbor.features.spawnChunks": "Spawn Chunks", "bbor.features.lazyChunks": "Lazy Chunks", @@ -26,6 +28,7 @@ "bbor.features.mobSpawners.activationLines": "Activation Lines", "bbor.features.spawningSpheres": "Spawning Spheres", "bbor.features.spawningSpheres.spawnableBlocks": "Spawnable Blocks", + "bbor.features.spawnableBlocks": "Spawnable Blocks", "bbor.features.biomeBorders": "Biome Borders", "bbor.sections.beaconsAndConduits": "Beacons & Conduits", -- 2.44.0