Make Furnace Light When Certain Blocks are Around It

stronwood

New member
May 7, 2023
1
0
1
I'm trying to create a plugin that will make a furnace remain lit and not require additional fuel when lava is placed on four surrounding sides. To do this, I want to detect when a lava source block is touching the 3 horizontal sides that are not the furnace face as well as the top of the furnace. To do this, I'm currently trying to use an InventoryClickEvent to detect when a certain item is placed in the fuel space then call a method that checks if the furnace is surrounded by lava. If both of these are true, the furnace should become lit and remain that way. For the life of me I can't seem to get this to work.

Current code is here -


Event Method:

Java:
public void furnaceFuelEvent(InventoryClickEvent event) {
        Inventory inv = event.getClickedInventory();
        if (inv.getType().getDefaultTitle() == "Furnace") {
            InventoryHolder invholder = inv.getHolder();
            Block c = (Block) invholder;
            Material m = c.getType();
            Lightable lightable = (Lightable) c.getBlockData();
            boolean fplace = new FurnacePlace().onFurnPlace(c);
            int x = c.getLocation().getBlockX();
            int y = c.getLocation().getBlockY();
            int z = c.getLocation().getBlockZ();
            Furnace furnace = (Furnace) c;
            BlockData furnData = m.createBlockData("lit=true");
            BlastFurnace bfurnace = (BlastFurnace) furnace;
            InventoryType.SlotType type = event.getSlotType();
            ItemStack istack = event.getCurrentItem();
            Material fuel = istack.getType();
            short burntime = 32000;
            if (fuel == Material.CONDUIT) {
                if (type == InventoryType.SlotType.FUEL) {
                    if (fplace == true) {
                        furnace.setBurnTime(burntime);
                        lightable.setLit(true);
                        furnace.update();

                    }
                }
            }
        } else {
            return;
        }
    }
}

Adjacent Block Check:

Java:
class FurnacePlace {
    public boolean onFurnPlace(Block b) {
        Material m = b.getType();
        BlockData mData = m.createBlockData();
        int x = b.getLocation().getBlockX();
        int y = b.getLocation().getBlockY();
        int z = b.getLocation().getBlockZ();
        Block east = b.getRelative(BlockFace.EAST, 1);
        Block west = b.getRelative(BlockFace.WEST, 1);
        Block north = b.getRelative(BlockFace.NORTH, 1);
        Block south = b.getRelative(BlockFace.SOUTH, 1);
        Block up = b.getRelative(BlockFace.UP, 1);
        Furnace f = (Furnace) b;
        Directional furn = (Directional) b;
        BlockFace facing = furn.getFacing();
        if (facing == BlockFace.WEST && (m == Material.FURNACE || m== Material.BLAST_FURNACE)) {
            if (east.getType() == Material.LAVA && north.getType() == Material.LAVA && south.getType() == Material.LAVA && up.getType() == Material.LAVA) {
                return true;
            }
        } else if (facing == BlockFace.NORTH && (m == Material.FURNACE || m== Material.BLAST_FURNACE)) {
            if (east.getType() == Material.LAVA && west.getType() == Material.LAVA && south.getType() == Material.LAVA && up.getType() == Material.LAVA) {
                return true;
            }
        } else if (facing == BlockFace.SOUTH && (m == Material.FURNACE || m== Material.BLAST_FURNACE)) {
            if (east.getType() == Material.LAVA && north.getType() == Material.LAVA && west.getType() == Material.LAVA && up.getType() == Material.LAVA) {
                return true;
            }
        } else if (facing == BlockFace.EAST && (m == Material.FURNACE || m== Material.BLAST_FURNACE)) {
            if (west.getType() == Material.LAVA && north.getType() == Material.LAVA && south.getType() == Material.LAVA && up.getType() == Material.LAVA) {
                return true;
            }
        } else {
            return false;
        }
        return false;
    }
}
 

RimeOrReason

New member
May 9, 2023
2
0
1
Simplified it and fixed, works like you said you wanted it to. Here's the whole class:

Java:
public class FurnaceListener implements Listener {
    private static final ArrayList<BlockFace> faces = new ArrayList<>();
    private static final short burntime = Short.MAX_VALUE;
    static {
        faces.add(BlockFace.NORTH);
        faces.add(BlockFace.EAST);
        faces.add(BlockFace.SOUTH);
        faces.add(BlockFace.WEST);
        faces.add(BlockFace.UP);
    }

    @EventHandler //This annotation processor is what makes this method an event handler, otherwise it won't do anything when the event is fired unless you have an event object and call this method with it as the argument
    public void furnaceFuelEvent(InventoryClickEvent event) {
        Inventory inv = event.getClickedInventory();
        if (!(inv instanceof FurnaceInventory)) return;
        if (event.getSlotType() != InventoryType.SlotType.FUEL) return;
        ItemStack istack = event.getCursor(); //event#getCurrentItem returns the item in the slot, not the item being added and since conduits can't be placed in the fuel slot, this is the only way to get the item being added
        if (istack == null || istack.getType() != Material.CONDUIT) return;
        InventoryHolder invholder = inv.getHolder();
        Furnace furnace = (Furnace) invholder;
        Lightable lightable = (Lightable) furnace.getBlockData();

        if (isValidFurnace(furnace.getBlock())) {
            furnace.setBurnTime(burntime);
            lightable.setLit(true);
            furnace.update();
            istack.setAmount(istack.getAmount() - 1);
        }
    }

    public boolean isValidFurnace(Block b) {
        Material m = b.getType();
        Directional furn = (Directional) b.getBlockData(); //Block and BlockData are separate things, can't cast Block to Directional
        BlockFace facing = furn.getFacing();
        if (m != Material.FURNACE && m != Material.BLAST_FURNACE) return false; //probably unnecessary since there's a FurnaceInventory check above
        int lavaCount = 0;
        for (BlockFace face : faces) {
            if (face == facing) continue;
            if (b.getRelative(face).getType() == Material.LAVA) lavaCount++;
        }
        return lavaCount >= 4;
    }
}

The if (!condition) return; blocks allow you to check conditions without too much indentation, would recommend using them when you can unless you're checking only 1 condition in total, in that case doing it the normal way would be easier to read. Plus, you can put them on the beginning of the method to skip unnecessary method calls, starting with the more general things and ending with the most specific thing. This helps a lot when there are lots of event calls happening, but there's nothing stopping you from using it on situations with low number of event calls as well.

Also opted for a for loop to check the relative blocks on each side with a static ArrayList of all possible block faces and counted lava blocks in total (while not counting the lava on the front side of the furnace). This way, it's easier to read and make adjustments to.

Edit: This won't make the furnace stay lit forever, I don't know any efficient way of making that happen (lightable#setLit might be doing this as well, I have no clue.) The only thing that comes to mind is a BukkitRunnable with runTaskTimer of 32767 and setting burntime of the furnace back to 32767 (assuming it's based on seconds and not ticks, it'd probably be an int or long if it was ticks though but idk) and running the task again when plugin is enabled.
 
Last edited: