EntityChangeBlock Event not working correctly

Discussion in 'Spigot Plugin Development' started by Valetorev, Jun 5, 2017.

  1. I am attempting to create a plugin that will remove falling sand when it is a specific area to prevent stacking sand on a 1.8 worldborder with a cannon. I have made one that works when the sand starts in the area. However when the sand is shot in from somewhere else (a cannon) it doesn't work. I believe it is because it became an entity outside of the area. If I'm wrong please let me know and if you have a way to fix this please inform me. My code is below. :)

    Code (Text):
        @EventHandler
        public void onSandFall(EntityChangeBlockEvent e){
            Block b = e.getBlock();
            int wbMax = getConfig().getInt("Worldborder Max")-1;
            int wbMin = getConfig().getInt("Worldborder Min");
            if(b.getType() == Material.SAND || b.getType() == Material.GRAVEL || b.getType() == Material.ANVIL){
                if(b.getLocation().getX() >= wbMax || b.getLocation().getX() <= wbMin || b.getLocation().getZ() >= wbMax || b.getLocation().getZ() <= wbMin){
                    b.setType(Material.AIR);
                    e.getEntity().remove();
                }else{
                    return;
                }
            }else{
                return;
            }  
        }
     
  2. Why do you don't check the Y Coordinate?
     
  3. Because it doesn't matter where it hits on the worldborder.
     
  4. Which values are you reading out of the config?
     
  5. TomTheDeveloper

    Supporter

    I believe is something we do not accept in the programming world. Have you checked if you assumption is correct? If not, check it by looking at your coordinates you get from your config and comparing them to the coordinates you get from the block.

    Once you know 100% sure that your assumption is correct, you can move on the next step. So my question is, are you 100% sure you're assumption is correct?
     
  6. The minimum and maximum for the worldborder x and z values.
     
  7. Yes I am sure. The Event used fires when sand becomes an entity. What I don't understand though is why it wouldn't fire when it becomes a block again. I know for a 100% fact the coordinates are right, and that my assumption is correct.
     
  8. TomTheDeveloper

    Supporter

    Have you tried using the location from the entity instead of the block? Maybe that will solve the issue? It's worth a try.
     
  9. I did try using the entity location but it returns the location it became the entity not where it ends up. What I may need to do it check its location until it stopped moving. I not exactly sure how I would do that. Any ideas? I know it would have smithing to do with a repeating task and the entities velocity, but I'm not sure how I'd set it all up.
     
  10. So the EntityChangeBlockEvent gets called when the falling block gets to a solid one, however right after the event is called the location of the block isnt correct. So i simply made an scheduler and delayed it for half a second. You just have to try what period of time is the best in order to remove the block. Also you have to set the block to Material.AIR, removing the entity is pointless.

    Code (Text):
        @EventHandler
        public void PlayerInteract(EntityChangeBlockEvent e){
            Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Main.getMain(), new Runnable(){

                @Override
                public void run() {
                    e.getBlock().setType(Material.AIR);
                }
               
            }, 10L);
        }
    The time is in ticks, meaning 20L = 1 second
     
  11. Alright. I assume you've tested this, however I'll test it tomorrow when I'm on my PC to see if it works for what I'm doing :)
     
  12. It will "work", but for the wrong reasons.

    When a falling block has a -y collision it will spawn the appropriate block via EntityChangeBlockEvent, and then fire a BlockPhysicsEvent on the newly formed block (as it does with all new blocks). Thus, if it is floating sand the sand block will almost instantaneously despawn / skip spawn and a new falling block would be created (keep in mind the order of events here, you'd be saying a falling block lands but doesn't land).

    The event is fired when the sand is no longer meant to be an entity (in the context of falling blocks), as it is right before anything spawn related (for the block, the falling block will already be killed/despawned by this point).

    You're checking if Block#getType is returning SAND, but it will only return what the block is before the sand has landed. You need to check EntityChangeBlockEvent#getTo. This is why you're having problems, because the block hasn't changed yet. Additionally the event fires for more than falling blocks, it'd be good to restrict it:

    Code (Java):
    if (e.getEntity() instanceof FallingBlock && e.getTo() == Material.SAND && /* other conditions */) {
        //falling sand block!
    }

    block locations don't change, the only reason this works is because you're setting the value after the event has been fired (rather than cancelling the event).
     
    #12 1Rogue, Jun 9, 2017
    Last edited: Jun 9, 2017
    • Informative Informative x 1
  13. ok so based on what you said my code now looks like this:
    Code (Text):
        @EventHandler
        public void onEntityWorldBorderColide(EntityChangeBlockEvent e){
            Entity s = e.getEntity();
            int wbMax = getConfig().getInt("Worldborder Max")-1;
            int wbMin = getConfig().getInt("Worldborder Min");
            if(s instanceof FallingBlock || s instanceof TNTPrimed){
                if(e.getTo() == Material.SAND || e.getTo() == Material.GRAVEL || e.getTo() == Material.ANVIL || e.getEntityType() == EntityType.PRIMED_TNT){
                    if(s.getLocation().getX() >= wbMax || s.getLocation().getX() <= wbMin || s.getLocation().getZ() >= wbMax || s.getLocation().getZ() <= wbMin){
                        e.getBlock().setType(Material.AIR);
                    }else{
                        return;
                    }
                }else{
                    return;  
                }
            }else{
                return;
            }  
        }
    It still doesn't work as it is supposed to do. When i fire the cannon and it gets shot into the specified area and starts to fall it doesn't get removed, but when i place it in the specified area and it falls it works. It basically did nothing different from the code i had before.. Did i do it right or did i mess up again lol.
     
  14. You forgot to cancel the event. Outside of that you're fine.
     
  15. Lol I'm dumb some times. I'll test that tomorrow.