renderer = new ClientRenderer(this::getCache)
.registerProvider(new SlimeChunkProvider())
.registerProvider(new WorldSpawnProvider())
- .registerProvider(new SpawningSphereProvider());
+ .registerProvider(new SpawningSphereProvider())
+ .registerProvider(new BeaconProvider());
KeyListener.init();
}
SlimeChunkProvider.clear();
WorldSpawnProvider.clear();
SpawningSphereProvider.clear();
+ BeaconProvider.clear();
VillageColorCache.clear();
clearCaches();
}
registerRenderer(BoundingBoxCuboid.class, new CuboidRenderer());
registerRenderer(BoundingBoxMobSpawner.class, new MobSpawnerRenderer());
registerRenderer(BoundingBoxSpawningSphere.class, new SpawningSphereRenderer());
+ registerRenderer(BoundingBoxBeacon.class, new CuboidRenderer());
}
public <T extends AbstractBoundingBox> ClientRenderer registerProvider(IBoundingBoxProvider<T> provider) {
--- /dev/null
+package com.irtimaled.bbor.client.commands;
+
+import com.irtimaled.bbor.client.providers.BeaconProvider;
+import com.irtimaled.bbor.common.TypeHelper;
+import com.irtimaled.bbor.common.models.Coords;
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import net.minecraft.client.Minecraft;
+import net.minecraft.command.Commands;
+import net.minecraft.command.ISuggestionProvider;
+import net.minecraft.command.arguments.BlockPosArgument;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.tileentity.TileEntityBeacon;
+import net.minecraft.util.math.BlockPos;
+
+public class BeaconCommand {
+ public static void register(CommandDispatcher<ISuggestionProvider> commandDispatcher) {
+ LiteralArgumentBuilder command = Commands.literal("bbor:beacon")
+ .then(Commands.literal("add")
+ .then(Commands.argument("pos", BlockPosArgument.blockPos())
+ .executes((context) -> {
+ BlockPos pos = BlockPosArgument.getBlockPos(context, "pos");
+ TileEntity tileEntity = Minecraft.getInstance().world.getTileEntity(pos);
+ TypeHelper.doIfType(tileEntity, TileEntityBeacon.class, beacon -> {
+ BeaconProvider.add(new Coords(pos), beacon.getLevels());
+ });
+ return 0;
+ })))
+ .then(Commands.literal("clear")
+ .executes((context) -> {
+ BeaconProvider.clear();
+ return 0;
+ })
+ .then(Commands.argument("pos", BlockPosArgument.blockPos())
+ .executes((context) -> {
+ BlockPos pos = BlockPosArgument.getBlockPos(context, "pos");
+ BeaconProvider.remove(new Coords(pos));
+ return 0;
+ })));
+ commandDispatcher.register(command);
+ }
+}
package com.irtimaled.bbor.client.interop;
import com.irtimaled.bbor.client.PlayerCoords;
+import com.irtimaled.bbor.client.commands.BeaconCommand;
import com.irtimaled.bbor.client.commands.SeedCommand;
import com.irtimaled.bbor.client.commands.SpawningSphereCommand;
import com.irtimaled.bbor.client.events.DisconnectedFromRemoteServer;
public static void registerClientCommands(CommandDispatcher<ISuggestionProvider> commandDispatcher) {
SeedCommand.register(commandDispatcher);
SpawningSphereCommand.register(commandDispatcher);
+ BeaconCommand.register(commandDispatcher);
}
}
--- /dev/null
+package com.irtimaled.bbor.client.providers;
+
+import com.irtimaled.bbor.client.PlayerCoords;
+import com.irtimaled.bbor.common.Dimensions;
+import com.irtimaled.bbor.common.models.BoundingBoxBeacon;
+import com.irtimaled.bbor.common.models.Coords;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class BeaconProvider implements IBoundingBoxProvider<BoundingBoxBeacon> {
+ private static Map<Integer, Map<Coords, BoundingBoxBeacon>> dimensionsCache = buildBeaconsCache();
+
+ private static Map<Integer, Map<Coords, BoundingBoxBeacon>> buildBeaconsCache() {
+ Map<Integer, Map<Coords, BoundingBoxBeacon>> map = new HashMap<>();
+ map.put(Dimensions.OVERWORLD, new ConcurrentHashMap<>());
+ map.put(Dimensions.NETHER, new ConcurrentHashMap<>());
+ map.put(Dimensions.THE_END, new ConcurrentHashMap<>());
+ return map;
+ }
+
+ private static Map<Coords, BoundingBoxBeacon> getCache(int dimensionId) {
+ return dimensionsCache.computeIfAbsent(dimensionId, i -> new ConcurrentHashMap<>());
+ }
+
+ public static void add(Coords coords, int level) {
+ int dimensionId = PlayerCoords.getDimensionId();
+ BoundingBoxBeacon beacon = BoundingBoxBeacon.from(coords, level);
+ getCache(dimensionId).put(coords, beacon);
+ }
+
+ public static void remove(Coords coords) {
+ int dimensionId = PlayerCoords.getDimensionId();
+ getCache(dimensionId).remove(coords);
+ }
+
+ public static void clear() {
+ dimensionsCache.values().forEach(Map::clear);
+ }
+
+ public Iterable<BoundingBoxBeacon> get(int dimensionId) {
+ return getCache(dimensionId).values();
+ }
+}
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 Beacon = register(Color.WHITE, "Beacon", ConfigManager.drawBeacons);
private static BoundingBoxType register(Color color, String name, Setting<Boolean> shouldRenderSetting) {
return structureTypeMap.computeIfAbsent(name.hashCode(), k -> new BoundingBoxType(color, name, shouldRenderSetting));
--- /dev/null
+package com.irtimaled.bbor.common.models;
+
+import com.irtimaled.bbor.common.BoundingBoxType;
+
+public class BoundingBoxBeacon extends BoundingBoxCuboid {
+ private final Coords coords;
+
+ private BoundingBoxBeacon(Coords coords, Coords minCoords, Coords maxCoords) {
+ super(minCoords, maxCoords, BoundingBoxType.Beacon);
+ this.coords = coords;
+ }
+
+ public static BoundingBoxBeacon from(Coords coords, int level) {
+ int range = 10 + (10 * level);
+ Coords minCoords = new Coords(coords.getX() - range, coords.getY() - range, coords.getZ() - range);
+ Coords maxCoords = new Coords(coords.getX() + range, 324 + range, coords.getZ() + range);
+ return new BoundingBoxBeacon(coords, minCoords, maxCoords);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + coords.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BoundingBoxBeacon other = (BoundingBoxBeacon) obj;
+ return coords.equals(other.coords);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + coords.toString() + ")";
+ }
+
+ public Coords getCoords() {
+ return coords;
+ }
+}
public static Setting<Boolean> drawAFKSpheres;
public static Setting<Boolean> renderAFKSpawnableBlocks;
public static Setting<Integer> afkSpawnableBlocksRenderDistance;
+ public static Setting<Boolean> drawBeacons;
public static void loadConfig(File mcConfigDir) {
configDir = new File(mcConfigDir, "config");
outerBoxesOnly = setup(config, "general", "outerBoxesOnly", false, "If set to true only the outer bounding boxes are rendered.");
alwaysVisible = setup(config, "general", "alwaysVisible", false, "If set to true boxes will be visible even through other blocks.");
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.");
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)");