Howto Move Furnace/Chest

Discussion in 'Plugin Development' started by zwarmapapa, Feb 17, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    zwarmapapa

    I am trying to make a drill, where I got 3 blocks: IronBlock (IB) - Chest (C) - Furnace (F).
    The IB has to move forward, the C then takes in the IB's place, then the F takes in the C's place. This is what is supposed to happen, but I get an error when I try to move the F to the C's place (moving the IB and the C goes ok).
    The error tells me that it can't cast a furnace to a chest... My code to 'move' the block is setTypeId() and setData(), so:
    Code:
    chest.setTypeId( furnace.getTypeId() );
    chest.setData( furnace.getData() );
    Why does it gives an error? How can I work around this to make this work?
     
  2. Offline

    Njol

    Please post more of your code, two lines aren't enough to help.
     
  3. Offline

    zwarmapapa

    Code:
        // move drill method >>
            public void moveDrill( Block justDrilledBlock, Block drill, Block chest, Block furnace  )
            {
                removeDrill( furnace );
           
                setBlock( justDrilledBlock, drill );
                setBlock( drill, chest );
                setBlock( chest.getState(), furnace.getState() );
                setBlock( furnace, null );
           
                saveDrill( chest.getWorld().getBlockAt(chest.getLocation()) ); // chest = new furnace
            }
        // move drill method <<
     
     
        // move block methods >>
            // these call >>
                public void setBlock( BlockState block, BlockState replaceBy )
                {
                    if( replaceBy != null )
                        setBlock( block.getWorld(), new Location(block.getWorld(), block.getX(), block.getY(), block.getZ()), replaceBy.getTypeId(), replaceBy.getRawData() );
                    else
                        setBlock( block.getWorld(), new Location(block.getWorld(), block.getX(), block.getY(), block.getZ()), 0, null );
                }
                public void setBlock( Block block, Block replaceBy )
                {
                    if( replaceBy != null )
                        setBlock( block.getWorld(), block.getLocation(), replaceBy.getTypeId(), replaceBy.getData() );
                    else
                        setBlock( block.getWorld(), block.getLocation(), 0, null );
                }
            // these call <<
       
            // these >>
                public void setBlock( World world, Location location, int BlockID, byte data )
                {
                    world.getBlockAt(location).setTypeId( BlockID );
                    world.getBlockAt(location).setData( data );
                }
                public void setBlock( World world, Location location, int BlockID, Object data )
                {
                    world.getBlockAt(location).setTypeId( BlockID );
                }
            // these <<
        // move block methods <<
    I get an error at "setBlock( chest.getState(), furnace.getState() );"
    PS: I also get the same error when I try "setBlock( chest, furnace );"

    This is the exact error I get:

    Code:
    14:01:26 [WARNING] Task of 'AutomaticDrillingMachines' generated an exception
    java.lang.ClassCastException: net.minecraft.server.TileEntityFurnace cannot be c
    ast to net.minecraft.server.TileEntityChest
            at net.minecraft.server.BlockChest.remove(SourceFile:225)
            at net.minecraft.server.Chunk.a(Chunk.java:386)
            at net.minecraft.server.World.setRawTypeId(World.java:371)
            at net.minecraft.server.World.setTypeId(World.java:438)
            at org.bukkit.craftbukkit.block.CraftBlock.setTypeId(CraftBlock.java:88)
     
            at zwarmapapa.AutomaticDrillingMachines.AutomaticDrillingMachines.setBlo
    ck(AutomaticDrillingMachines.java:987)
            at zwarmapapa.AutomaticDrillingMachines.AutomaticDrillingMachines.setBlo
    ck(AutomaticDrillingMachines.java:971)
            at zwarmapapa.AutomaticDrillingMachines.AutomaticDrillingMachines.moveDr
    ill(AutomaticDrillingMachines.java:958)
            at zwarmapapa.AutomaticDrillingMachines.AutomaticDrillingMachines.drillA
    ction(AutomaticDrillingMachines.java:923)
            at zwarmapapa.AutomaticDrillingMachines.AutomaticDrillingMachines$1.run(
    AutomaticDrillingMachines.java:824)
            at org.bukkit.craftbukkit.scheduler.CraftScheduler.mainThreadHeartbeat(C
    raftScheduler.java:137)
            at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:503)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:435)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:465)
    Here is a screenshot of the code in color with line numbers: http://dl.dropbox.com/u/7174774/dl/minecraft_AutomaticDrillingMachines/moveDrill_18-02-2012.png

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 24, 2016
  4. Offline

    ferrybig

    try setting the chest/furnace first to air (to clear the tile entity of it) and then to what you want
     
  5. Offline

    zwarmapapa

    ferrybig
    Damn, that worked :p
    Thanks!

    Ehm... I got 1 more problem....
    The moving goes ok, but when I move a chest, and put another block next to it, it will bug.
    It looks like it's a double chest, but it's not.
    After doing that, when I then destroy the block next to the chest, the client will crash. After logging back into the server (which won't crash or give any errors), the chest is normal again and the block next to the chest is gone.

    Any ideas why this is?


    More Info:
    1. This is what the code does:
    [ ] = empty
    [D] = drill (Iron Block or Diamond Block)
    [C] = chest
    [F] = furnace

    [ ] [D] [C] [F]
    [ ] [ ] [C] [F]
    [D] [ ] [C] [F]
    [D] [ ] [ ] [F]
    [D] [C] [ ] [F]
    [D] [C] [ ] [ ]
    [D] [C] [F] [ ]

    2. This bug also happens if I don't do the last 2 steps (so end up with [D] [C] [ ] [F]) and then place a block with the client next to the chest.

    3. Sometimes you don't see any black or strange stuff around the chest, but when you break the chest, you will still get a client crash.

    4. The code (chest gets f*cked up by the moveDrill method)
    Code:
        // move drill methods >>
            public Block moveDrill( Block justDrilledBlock, Block drill, Block chest, Block furnace )
            {
                removeDrill( furnace );
             
                Block newDrill        = replaceBlock( justDrilledBlock, drill );
                Block newChest        = replaceBlock( drill, chest );
                Block newFurnace    = replaceBlock( chest, furnace );
             
                saveDrill( newFurnace, false );
                return newFurnace;
            }
         
            public Block fallDrill( Block drill, Block chest, Block furnace )
            {
                removeDrill( furnace );
             
                Block newDrill=null, newChest=null, newFurnace=null;
                if( drill.getY() >= 1 )
                {
                    newDrill        = replaceBlock( getBlockBelow(drill), drill );
                    newChest        = replaceBlock( getBlockBelow(chest), chest );
                    newFurnace        = replaceBlock( getBlockBelow(furnace), furnace );
                }
                else
                {
                    replaceBlock( drill, null );
                    replaceBlock( chest, null );
                    replaceBlock( furnace, null );
                }
             
                if( drill.getY() >= 1 )
                {
                    saveDrill( newFurnace, false );
                }
                return newFurnace;
            }
        // move drill methods <<
     
     
        // set block methods >>
            // these call >>
                public Block replaceBlock( Block oldBlock, Block newBlock )
                {
                    clearBlock( oldBlock );
                 
                    if( newBlock == null )
                    {
                        newBlock = setBlock( oldBlock.getWorld(), oldBlock.getLocation(), 0, null );
                    }
                    else
                    {
                        ItemStack[] items = null;
                        short burnTime = 0;
                        if( newBlock.getTypeId() == BlockID.CHEST )
                        {
                            ((Chest) newBlock.getState()).update();
                            items = ((Chest) newBlock.getState()).getInventory().getContents();
                        }
                        if( (newBlock.getTypeId() == BlockID.FURNACE_OFF) || (newBlock.getTypeId() == BlockID.FURNACE_ON) )
                        {
                            ((Furnace) newBlock.getState()).update();
                            items = ((Furnace) newBlock.getState()).getInventory().getContents();
                            burnTime = ((Furnace) newBlock.getState()).getBurnTime();
                        }
                     
                        int typeId = newBlock.getTypeId();
                        byte data = newBlock.getData();
                        clearBlock( newBlock );
                        newBlock = setBlock( oldBlock.getWorld(), oldBlock.getLocation(), typeId, data );
                     
                        if( items != null )
                        {
                            if( newBlock.getTypeId() == BlockID.CHEST )
                            {
                                ((Chest) newBlock.getState()).getInventory().setContents( items );
                                ((Chest) newBlock.getState()).update();
                            }
                            if( (newBlock.getTypeId() == BlockID.FURNACE_OFF) || (newBlock.getTypeId() == BlockID.FURNACE_ON) )
                            {
                                ((Furnace) newBlock.getState()).getInventory().setContents( items );
                                ((Furnace) newBlock.getState()).setBurnTime( burnTime );
                                ((Furnace) newBlock.getState()).update();
                            }
                        }
                    }
                    return newBlock;
                }
            // these call <<
         
            // these >>
                public void clearBlock( Block block )
                {
                    if( block.getTypeId() == BlockID.CHEST )
                    {
                        ((Chest) block.getState()).getInventory().setContents( new ItemStack[ ((Chest) block.getState()).getInventory().getContents().length ] );
                        ((Chest) block.getState()).update();
                    }
                    if( (block.getTypeId() == BlockID.FURNACE_OFF) || (block.getTypeId() == BlockID.FURNACE_ON) )
                    {
                        ((Furnace) block.getState()).getInventory().setContents( new ItemStack[ ((Furnace) block.getState()).getInventory().getContents().length ] );
                        ((Furnace) block.getState()).update();
                    }
                    block.setTypeId( 0 );
                }
                public Block setBlock( World world, Location location, int BlockID, byte data )
                {
                    world.getBlockAt(location).setTypeId( 0 );
                    world.getBlockAt(location).setTypeId( BlockID );
                    world.getBlockAt(location).setData( data );
                    return world.getBlockAt( location );
                }
                public Block setBlock( World world, Location location, int BlockID, Object data )
                {
                    world.getBlockAt(location).setTypeId( 0 );
                    world.getBlockAt(location).setTypeId( BlockID );
                    return world.getBlockAt( location );
                }
            // these <<
        // set block methods <<
    Hmmm... I tested it some more, and it turned out it was this code causing it:
    Code:
    // change FURNACE_OFF to FURNACE_ON >>
        try
        {
            // this hacks into craftbukkit
            // it will automaticly turn back to OFF when out of fuel
            org.bukkit.craftbukkit.CraftWorld world = (org.bukkit.craftbukkit.CraftWorld) furnace.getWorld();
            net.minecraft.server.BlockFurnace.a( true, world.getHandle(), furnace.getX(), furnace.getY(), furnace.getZ() );
        }
        catch( Exception error )
        {
            // in case of a change in craftbukkit, this will probably cause errors
            // this code isn't important for this plugin, it's only for the burning furnace looks
        }
    // change FURNACE_OFF to FURNACE_ON <<
    Does anyone know how to properly change a furnace to a burning furnace?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 24, 2016
  6. Offline

    Njol

    Change it's type id to 62.
     
  7. Offline

    zwarmapapa

    Hm thanks, but then it resets the data and inventory.
    I guess I gotto work around that.
    To bad those other 2 lines caused crashes, it was easy to use, since it made the furnace turn back to a normal furnace when it no longer had burnTime anymore.

    Edit: turns out the setTypeId() also causes the furnace to put itself out when it's burnTime is over.

    Ow shit, I did that, it worked exactly like the 2 lines before, but now it still gives a crash when I destroy the furnace -.-
    Is this a craftbukkit bug?


    Current code:
    Code:
        // change FURNACE_OFF to FURNACE_ON >>
            ItemStack[] items = furnace.getInventory().getContents();
            short burnTime = furnace.getBurnTime();
     
            byte data = furnaceBlock.getData();
            clearBlock( furnaceBlock );
            Block furnaceOnBlock = setBlock( furnaceBlock.getWorld(), furnaceBlock.getLocation(), BlockID.FURNACE_ON, data );
     
            Furnace furnaceOn = (Furnace) furnaceOnBlock.getState();
            furnaceOn.setBurnTime( burnTime );
            furnaceOn.getInventory().setContents( items );
        // change FURNACE_OFF to FURNACE_ON <<

    clearBlock method:
    Code:
        public void clearBlock( Block block )
        {
            if( block.getTypeId() == BlockID.CHEST )
            {
                ((Chest) block.getState()).getInventory().setContents( new ItemStack[ ((Chest) block.getState()).getInventory().getContents().length ] );
                ((Chest) block.getState()).update();
            }
            if( (block.getTypeId() == BlockID.FURNACE_OFF) || (block.getTypeId() == BlockID.FURNACE_ON) )
            {
                ((Furnace) block.getState()).getInventory().setContents( new ItemStack[ ((Furnace) block.getState()).getInventory().getContents().length ] );
                ((Furnace) block.getState()).update();
            }
            block.setTypeId( 0 );
        }

    setBlock method:
    Code:
        public Block setBlock( World world, Location location, int BlockID, byte data )
        {
            world.getBlockAt(location).setTypeId( 0 );
            world.getBlockAt(location).setTypeId( BlockID );
            world.getBlockAt(location).setData( data );
            return world.getBlockAt( location );
        }


    Here is a link to the plugin (source included), so you can see the bug for yourself: http://dl.dropbox.com/u/7174774/dl/minecraft_AutomaticDrillingMachines/AutomaticDrillingMachines v1.0.0_furnace_bug.jar
    When you've added the plugin to your server, place 3 blocks next to eachother in this order: IronBlock-Chest-Furnace, then put redstone dust in the furnace (in the melt spot) and put some fuel into it (coal/planks/sticks/blaze-rod/lava/etc).
    When you then break the furnace (while the furnace is burning), it will crash the client.

    Can anyone test this too to see if their client also crashes?


    Edit 1: strangely enough, it doesn't happen when I use the SpoutCraft client, I'll try redownloading the MineCraft client...

    Edit 3: Nope, redownloading didn't work, it's probably a MineCraft client bug?

    Edit 3: The client crash still won't happen when using the SpoutCraft client.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 24, 2016
Thread Status:
Not open for further replies.

Share This Page