.registerProvider(new SlimeChunkProvider())
.registerProvider(new WorldSpawnProvider())
.registerProvider(new SpawningSphereProvider())
- .registerProvider(new BeaconProvider());
+ .registerProvider(new BeaconProvider())
+ .registerProvider(new CustomBoxProvider());
KeyListener.init();
}
WorldSpawnProvider.clear();
SpawningSphereProvider.clear();
BeaconProvider.clear();
+ CustomBoxProvider.clear();
VillageColorCache.clear();
clearCaches();
}
--- /dev/null
+package com.irtimaled.bbor.client.commands;
+
+import com.irtimaled.bbor.client.providers.CustomBoxProvider;
+import com.irtimaled.bbor.common.models.Coords;
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import net.minecraft.command.Commands;
+import net.minecraft.command.ISuggestionProvider;
+import net.minecraft.command.arguments.BlockPosArgument;
+import net.minecraft.util.math.BlockPos;
+
+import java.util.function.BiConsumer;
+
+public class BoxCommand {
+ public static void register(CommandDispatcher<ISuggestionProvider> commandDispatcher) {
+ LiteralArgumentBuilder command = Commands.literal("bbor:box")
+ .then(Commands.literal("add")
+ .then(Commands.argument("from", BlockPosArgument.blockPos())
+ .then(Commands.argument("to", BlockPosArgument.blockPos())
+ .executes((context) -> {
+ CoordsFromContext(context, CustomBoxProvider::add);
+ return 0;
+ }))))
+ .then(Commands.literal("clear")
+ .executes((context) -> {
+ CustomBoxProvider.clear();
+ return 0;
+ })
+ .then(Commands.argument("from", BlockPosArgument.blockPos())
+ .then(Commands.argument("to", BlockPosArgument.blockPos())
+ .executes((context) -> {
+ CoordsFromContext(context, CustomBoxProvider::remove);
+ return 0;
+ }))));
+ commandDispatcher.register(command);
+ }
+
+ private static void CoordsFromContext(CommandContext context, BiConsumer<Coords, Coords> consumer) throws CommandSyntaxException {
+ BlockPos from = BlockPosArgument.getBlockPos(context, "from");
+ BlockPos to = BlockPosArgument.getBlockPos(context, "to");
+ Coords minCoords = new Coords(Math.min(from.getX(), to.getX()), Math.min(from.getY(), to.getY()), Math.min(from.getZ(), to.getZ()));
+ Coords maxCoords = new Coords(Math.max(from.getX(), to.getX()), Math.max(from.getY(), to.getY()), Math.max(from.getZ(), to.getZ()));
+ consumer.accept(minCoords, maxCoords);
+ }
+}
import com.irtimaled.bbor.client.PlayerCoords;
import com.irtimaled.bbor.client.commands.BeaconCommand;
+import com.irtimaled.bbor.client.commands.BoxCommand;
import com.irtimaled.bbor.client.commands.SeedCommand;
import com.irtimaled.bbor.client.commands.SpawningSphereCommand;
import com.irtimaled.bbor.client.events.DisconnectedFromRemoteServer;
SeedCommand.register(commandDispatcher);
SpawningSphereCommand.register(commandDispatcher);
BeaconCommand.register(commandDispatcher);
+ BoxCommand.register(commandDispatcher);
}
}
--- /dev/null
+package com.irtimaled.bbor.client.providers;
+
+import com.irtimaled.bbor.client.PlayerCoords;
+import com.irtimaled.bbor.common.BoundingBoxType;
+import com.irtimaled.bbor.common.Dimensions;
+import com.irtimaled.bbor.common.models.BoundingBoxCuboid;
+import com.irtimaled.bbor.common.models.Coords;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class CustomBoxProvider implements IBoundingBoxProvider<BoundingBoxCuboid> {
+ private static Map<Integer, Map<Integer, BoundingBoxCuboid>> dimensionCache = buildDimensionCache();
+
+ private static Map<Integer, Map<Integer, BoundingBoxCuboid>> buildDimensionCache() {
+ Map<Integer, Map<Integer, BoundingBoxCuboid>> 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 int getHashKey(Coords minCoords, Coords maxCoords) {
+ return (31 + minCoords.hashCode()) * 31 + maxCoords.hashCode();
+ }
+
+ private static Map<Integer, BoundingBoxCuboid> getCache(int dimensionId) {
+ return dimensionCache.computeIfAbsent(dimensionId, i -> new ConcurrentHashMap<>());
+ }
+
+ public static void add(Coords minCoords, Coords maxCoords) {
+ int dimensionId = PlayerCoords.getDimensionId();
+ int cacheKey = getHashKey(minCoords, maxCoords);
+ BoundingBoxCuboid cuboid = BoundingBoxCuboid.from(minCoords, maxCoords, BoundingBoxType.Custom);
+ getCache(dimensionId).put(cacheKey, cuboid);
+ }
+
+ public static void remove(Coords minCoords, Coords maxCoords) {
+ int dimensionId = PlayerCoords.getDimensionId();
+ int cacheKey = getHashKey(minCoords, maxCoords);
+ getCache(dimensionId).remove(cacheKey);
+ }
+
+ public static void clear() {
+ dimensionCache.values().forEach(Map::clear);
+ }
+
+ public Iterable<BoundingBoxCuboid> get(int dimensionId) {
+ return getCache(dimensionId).values();
+ }
+}
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);
+ public final static BoundingBoxType Custom = register(Color.WHITE, "Custom", ConfigManager.drawCustomBoxes);
private static BoundingBoxType register(Color color, String name, Setting<Boolean> shouldRenderSetting) {
return structureTypeMap.computeIfAbsent(name.hashCode(), k -> new BoundingBoxType(color, name, shouldRenderSetting));
public static Setting<Boolean> renderAFKSpawnableBlocks;
public static Setting<Integer> afkSpawnableBlocksRenderDistance;
public static Setting<Boolean> drawBeacons;
+ public static Setting<Boolean> drawCustomBoxes;
public static void loadConfig(File mcConfigDir) {
configDir = new File(mcConfigDir, "config");
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.");
+ drawCustomBoxes = setup(config, "general", "drawCustomBoxes", true, "If set to true custom 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)");