package dev.loki.lomines.block; import dev.loki.lomines.LoMinesPlugin; import dev.loki.lomines.data.config.block.BlockKey; import dev.loki.lomines.util.location.Cuboid; import dev.lolib.scheduler.Scheduler; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.data.BlockData; import java.util.List; import java.util.Map; import java.util.function.IntConsumer; /** * BlockSetter implementation for vanilla Minecraft blocks. * Uses Bukkit API to set blocks with optimal performance settings. * Updated for BlockKey type-safe configuration. */ public final class BukkitBlockSetter extends BlockSetter { private final Map weights; private final LoMinesPlugin plugin; public BukkitBlockSetter(Map weights, LoMinesPlugin plugin) { this.weights = weights; this.plugin = plugin; } @Override public void fill(Cuboid region, IntConsumer callback) { Scheduler.get(plugin).runAsync(() -> { int count = fillSync(region); Scheduler.get(plugin).run(() -> { callback.accept(count); }); }); } @Override public void fillAtLocations(List locations, IntConsumer callback) { if (locations == null || locations.isEmpty()) { Scheduler.get(plugin).run(() -> callback.accept(0)); return; } Scheduler.get(plugin).runAsync(() -> { int count = fillAtLocationsSync(locations); Scheduler.get(plugin).run(() -> callback.accept(count)); }); } private int fillSync(Cuboid region) { int count = 0; World world = region.getWorld(); for (int x = region.getMinX(); x <= region.getMaxX(); x++) { for (int y = region.getMinY(); y <= region.getMaxY(); y++) { for (int z = region.getMinZ(); z <= region.getMaxZ(); z++) { BlockData data = sampleBlockData(); world.getBlockAt(x, y, z).setBlockData(data, false); count++; } } } return count; } private int fillAtLocationsSync(List locations) { int count = 0; for (Location loc : locations) { if (loc.getWorld() == null) { continue; } BlockData data = sampleBlockData(); loc.getBlock().setBlockData(data, false); count++; } return count; } private BlockData sampleBlockData() { // Simple weighted random selection double random = Math.random(); double currentWeight = 0; for (Map.Entry entry : weights.entrySet()) { currentWeight += entry.getValue(); if (random <= currentWeight) { // BlockKey is already validated to be a block if (entry.getKey() instanceof BlockKey.Vanilla vanilla) { return Bukkit.createBlockData(vanilla.material()); } // Fallback for non-vanilla keys in vanilla setter (shouldn't happen) return Bukkit.createBlockData(Material.STONE); } } // Fallback to first entry BlockKey firstKey = weights.keySet().iterator().next(); if (firstKey instanceof BlockKey.Vanilla vanilla) { return Bukkit.createBlockData(vanilla.material()); } return Bukkit.createBlockData(Material.STONE); } }