Solved Restore Blocks to original after broken

Discussion in 'Plugin Development' started by The__Master_Coder, May 28, 2015.

Thread Status:
Not open for further replies.
  1. I made a splegg plugin for my server, and everything is working except I can't seem to figure out how to restore block to their original state after the last person dies.

    Here is my HashMap:

    Code:
    private HashMap<Block, Location> bl = new HashMap<Block, Location>();
    Here is where I am trying to restore blocks:

    Code:
    @SuppressWarnings("deprecation")
        @EventHandler
        public void onHit(ProjectileHitEvent e){
            final BlockIterator iterator = new BlockIterator(e.getEntity().getWorld(),
                    e.getEntity().getLocation().toVector(),
                    e.getEntity().getVelocity().normalize(), 0.0D, 4);
           
            Block hitBlock = null;
           
            while (iterator.hasNext()) {
                hitBlock = iterator.next();
                
                if (hitBlock.getType() != Material.AIR) {
                break;
                }
            }
            final Location hitblockloc = hitBlock.getLocation();
                
            if (hitBlock.getType() == Material.WOOL) {
                bl.put(hitBlock, hitblockloc);
                hitBlock.getWorld().playEffect(hitBlock.getLocation(), Effect.STEP_SOUND, hitBlock.getTypeId());
                hitBlock.setType(Material.AIR);
            }
            BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
            scheduler.scheduleSyncRepeatingTask(this, new Runnable() {
                @Override
                public void run(){
                    if (spleggstart.size() == 0 && spleggstarting.size() == 0 && splegglobby.size() == 0){
                        String s = String.valueOf(bl.get(hitblockloc));
                        hitblockloc.getBlock().setType(Material.getMaterial(s));
                    }
                }
            }, 20L, 10L);
        }
    Can't seem to figure out what is wrong. Any help?
     
  2. Offline

    567legodude

    @The__Master_Coder The Block object has a getLocation method, so you dont need to store the location with the block.
    Also, I think it would be better to store HashMap<Location, Material> then just iterate through the map and set each location to the right material.
     
  3. @567legodude Thanks! That worked, except the only problem is that the blocks that get changed are changed to white wool, when I am using colored wool. Is there anyway I can store that too?
     
  4. @The__Master_Coder That's the data i think you will need to store Block for that to work.
     
  5. @bwfcwalshy That's what I tried originally (see code in first post) but the only problem was that the block wasn't even getting replaced with anything :/ Did I do something wrong in the above code?
     
  6. @The__Master_Coder You can still use material to replace if you can get it to work, all you need to do is check for data and apply the data
     
  7. @bwfcwalshy How would I check for data and somehow include that data into the HashMap without getting rid of Location and Material?
     
  8. @The__Master_Coder You can try replacing Material with block and using the block material and the block data is stored in Block.
     
  9. @bwfcwalshy I understand that a block stores the material and data, but when I use block in the hashmap, then the block still isnt placed. Do I need to change how I am setting the blocks from the HashMap? I can't seem to figure this out :/
     
  10. Make the HashMap's value of type BlockState and store stuff in it using Block#getState(), then you can load the block state and all you have to do is call BlockState#update()
     
  11. Do you mean like this?

    @megamichiel

    Code:
    private HashMap<Location, BlockState> bl = new HashMap<Location, BlockState>();
    Code:
    @SuppressWarnings("deprecation")
        @EventHandler
        public void onHit(ProjectileHitEvent e){
            final BlockIterator iterator = new BlockIterator(e.getEntity().getWorld(),
                    e.getEntity().getLocation().toVector(),
                    e.getEntity().getVelocity().normalize(), 0.0D, 4);
        
            Block hitBlock = null;
        
            while (iterator.hasNext()) {
                hitBlock = iterator.next();
             
                if (hitBlock.getType() != Material.AIR) {
                break;
                }
            }
            final Location hitblockloc = hitBlock.getLocation();
             
            if (hitBlock.getType() == Material.WOOL) {
                bl.put(hitblockloc, hitBlock.getState());
                hitBlock.getWorld().playEffect(hitBlock.getLocation(), Effect.STEP_SOUND, hitBlock.getTypeId());
                hitBlock.setType(Material.AIR);
            }
            BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
            scheduler.scheduleSyncRepeatingTask(this, new Runnable() {
                @Override
                public void run(){
                    if (spleggstart.size() == 0 && spleggstarting.size() == 0 && splegglobby.size() == 0){
                        String s = String.valueOf(bl.get(hitblockloc));
                        hitblockloc.getBlock().getState().update();
                    }
                }
            }, 20L, 10L);
        }
    Because this code doesn't replace a block. Should I update the blocks in a different way?

    Any ideas anyone?

    I have tried everything I could possibly think of! But I just can't seem to figure this one out... if anyone has any suggestions or solutions, it would be much appreciated

    FINALLY figured it out... I ended up creating a HashMap for each wool color I had in my map, and in each HashMap it took a <Location, Material> and when I was placing the blocks back into the world, i first checked if one of the HashMaps contained the block I was about to place, and if it did, then it would place the colored wool based on the hashmap. I placed colored wool with the

    Code:
    hitblockloc.getBlock().setTypeIdAndData(35, (byte) 0x1, true)
    Thanks everyone for the help :)

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

    567legodude

    @The__Master_Coder Does that mean that you have 16 hashmaps? Because you could easily store the color data in a single hashmap.
    HashMap<Location, Map.Entry<Material, Byte>>
    Then you can store the Material and the color data with each Location.
     
  13. Sorry to bring up an old thread, but I am trying to make my plugin more efficient, and I know that using 17 different hashmaps for each type of wool color is not efficient at all. Using that HashMap @567legodude how would I use the (hashmapname).put(blahblah); I've been struggling with trying to store block data and location for a while so I was wondering, how would I store blocks, and how would I update them so they are restored. Thanks
     
  14. Offline

    mythbusterma

    @The__Master_Coder

    Use one Set of BlockStates. You don't need to store the Location, as the BlockState already stores that information. Simply create a Set and then iterate over all the values in the Set, performing BlockState#update().

    To get the BlockState invoke #getState() on whatever Block you need the state of.
     
  15. Thanks for the quick reply @mythbusterma but the block isnt being replaced with the original. The debug message DOES send in the bukkit runnable, so the code is not stopping before then. Am I doing something wrong?

    Code:
    private ArrayList<BlockState> blockstore = new ArrayList<BlockState>();
    Code:
    public void onProjectileHit(ProjectileHitEvent e){
            BlockIterator iterator = new BlockIterator(e.getEntity().getWorld(),
                    e.getEntity().getLocation().toVector(),
                    e.getEntity().getVelocity().normalize(), 0.0D, 4);
     
           Block hitBlock = null;
     
            while (iterator.hasNext()) {
                hitBlock = iterator.next();
           
                if (hitBlock.getType() != Material.AIR) {
                break;
                }
            }
            final Block newblock = hitBlock;
          
            blockstore.add(newblock.getState());
          
            Random r = new Random();
         
            int randomcolor = r.nextInt(10) + 1;
         
            DyeColor color = getDye(randomcolor);
         
            Byte b = color.getData();
         
            newblock.setTypeIdAndData(35, b, true);
         
            Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new BukkitRunnable(){
                public void run(){
                    for (BlockState bs : blockstore){
                        Bukkit.getServer().getLogger().info("updating changed blocks."
                                + "");
                        bs.update();
                        blockstore.remove(newblock.getState());
                    }
                }
            }, 80);
        }
     
    Last edited: Jul 4, 2015
  16. Offline

    mythbusterma

    @The__Master_Coder

    Are you sure you're not generating a stack trace in your console? That code looks like it would generate one.
     
  17. @mythbusterma

    The only thing that is coming up in console is "updating changed blocks"
     
  18. Offline

    mythbusterma

  19. I figure that I need to save the BlockState and update it in the runnable, but that is not working, it is just staying as a wool color. :/

    EDIT: Found something rather odd: if the block that is changed to colored wool is already a type of wool (colored or not) it is restored to its original state. Though for no other blocks does it work.

    *Solved* finnaly figured it out.

    Code:
    final BlockState bl = hitBlock.getState();
            Random r = new Random();
    
            int randomcolor = r.nextInt(10) + 1;
    
            DyeColor color = getDye(randomcolor);
    
            Byte b = Byte.valueOf(color.getData());
            hitBlock.setType(Material.WOOL);
            hitBlock.setData(b);
            Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
                public void run(){
                    bl.getLocation().getBlock().setTypeIdAndData(bl.getTypeId(), bl.getRawData(), true);
                    bl.update();
                }
            }, 20*5);
    UPDATED CODE ABOVE. The main part that I added to make it work was the line above bl.update();

    I don't know why I had to set TypeIdAndData, but I did and it worked. Thanks to all who helped.

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

Share This Page