I have recently had the problem where I am unable to fill in the ancient city frame/portal. (1.21.1) The issue I have come across is that I have to place 2 blocks of reinforced deepslate or else it does not work at all. This can be seen more clearly below in this image:
However it will still not work to expectations as it will offset the frame filling by one block as seen below...
I will show my code below, sorry if I am making some silly mistake:
package poseidon.smp.customPortal;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.HashSet;
import java.util.Set;
public final class CustomPortal extends JavaPlugin implements Listener {
@Override
public void onEnable() {
Bukkit.getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onRightClick(PlayerInteractEvent event) {
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Block clickedBlock = event.getClickedBlock();
if (clickedBlock != null && clickedBlock.getType() == Material.REINFORCED_DEEPSLATE) {
Set<Block> frameBlocks = new HashSet<>();
findFrame(clickedBlock, frameBlocks);
fillFrameWithIce(frameBlocks);
}
}
}
private void findFrame(Block start, Set<Block> frameBlocks) {
findFrameRecursive(start, frameBlocks);
int minX = frameBlocks.stream().mapToInt(b -> b.getX()).min().orElse(0);
int maxX = frameBlocks.stream().mapToInt(b -> b.getX()).max().orElse(0);
int minY = frameBlocks.stream().mapToInt(b -> b.getY()).min().orElse(0);
int maxY = frameBlocks.stream().mapToInt(b -> b.getY()).max().orElse(0);
int minZ = frameBlocks.stream().mapToInt(b -> b.getZ()).min().orElse(0);
int maxZ = frameBlocks.stream().mapToInt(b -> b.getZ()).max().orElse(0);
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
frameBlocks.add(start.getWorld().getBlockAt(x, y, minZ));
frameBlocks.add(start.getWorld().getBlockAt(x, y, maxZ));
}
}
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
frameBlocks.add(start.getWorld().getBlockAt(minX, y, z));
frameBlocks.add(start.getWorld().getBlockAt(maxX, y, z));
}
}
}
private void findFrameRecursive(Block block, Set<Block> frameBlocks) {
if (block == null || frameBlocks.contains(block) || block.getType() != Material.REINFORCED_DEEPSLATE) {
return;
}
frameBlocks.add(block);
findFrameRecursive(block.getRelative(1, 0, 0), frameBlocks);
findFrameRecursive(block.getRelative(-1, 0, 0), frameBlocks);
findFrameRecursive(block.getRelative(0, 1, 0), frameBlocks);
findFrameRecursive(block.getRelative(0, -1, 0), frameBlocks);
findFrameRecursive(block.getRelative(0, 0, 1), frameBlocks);
findFrameRecursive(block.getRelative(0, 0, -1), frameBlocks);
}
private void fillFrameWithIce(Set<Block> frameBlocks) {
int minX = frameBlocks.stream().mapToInt(Block::getX).min().orElse(0);
int maxX = frameBlocks.stream().mapToInt(Block::getX).max().orElse(0);
int minY = frameBlocks.stream().mapToInt(Block::getY).min().orElse(0);
int maxY = frameBlocks.stream().mapToInt(Block::getY).max().orElse(0);
int minZ = frameBlocks.stream().mapToInt(Block::getZ).min().orElse(0);
int maxZ = frameBlocks.stream().mapToInt(Block::getZ).max().orElse(0);
for (int x = minX + 1; x < maxX; x++) {
for (int y = minY + 1; y < maxY; y++) {
for (int z = minZ + 1; z < maxZ; z++) {
Block block = frameBlocks.iterator().next().getWorld().getBlockAt(x, y, z);
if (!frameBlocks.contains(block)) {
block.setType(Material.STONE);
}
}
}
}
}
@Override
public void onDisable() {
}
}