EntityExplodeEvent and blocklist

Discussion in 'Plugin Development' started by Michael Bain, Feb 22, 2011.

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

    Michael Bain

    I have been digging around with EntityExplodeEvent working on a creeper effect mod and have found that blocklist doesn't seem to be affecting anything if updates are made. If you dig through the CraftBukkit source you will find that the blocklist from onEntityExplode is never used for anything more than an informational model. If you remove or make changes to these blocks does NOT affect the original explosion.

    blocklist is created from an array list of ChunkPosition that is an attribute of Explosion (from Explosion.java, line 184):

    Code:
    ArrayList arraylist = new ArrayList();
    
    arraylist.addAll(this.g);
    
    this list of ChunkPosition is then propagated into blocklist (from Explosion.java, line 194):

    Code:
    List<org.bukkit.block.Block> blocklist = new ArrayList<org.bukkit.block.Block>();
    for (int j = arraylist.size() - 1; j >= 0; j--) {
        ChunkPosition cpos = (ChunkPosition) arraylist.get(j);
        org.bukkit.block.Block blox = world.getBlockAt(cpos.a, cpos.b, cpos.c);
        if (!blox.getType().equals(org.bukkit.Material.AIR)) {
            blocklist.add(blox);
        }
    }
    

    However, when the damage determination from the explosion occurs, the code goes back to using arraylist (from Explosion.java, line 213):

    Code:
    for (int i = arraylist.size() - 1; i >= 0; --i) {
        ChunkPosition chunkposition = (ChunkPosition) arraylist.get(i);
    
    So, regardless of what you do with blocklist, it is still processing the original position list. I have compared this with the ExplosionPrimedEvent, and find that the attributes in this event seem to be passed along as they should be (from EntityCreeper.java, line 90):

    Code:
    ExplosionPrimedEvent event = new ExplosionPrimedEvent(eventType, CraftEntity.getEntity(server, this), 3.0F, false);
    server.getPluginManager().callEvent(event);
    if(!event.isCancelled()) {
        this.world.a(this, this.locX, this.locY, this.locZ, event.getRadius(), event.getFire());
        this.q();
    
    Thoughts? I saw similar threads questioning the ExplosionPrimedEvent changes, but from what I can see in the code those appear to be properly passed. I didn't want to add this thread to that discussion for fear of confusing the issue. Is there another way of excluding blocks from the explosion that I am missing?


    Basically what I was trying to do is keep the explosion animation but direct what it can affect (i.e. player damage and block damage). I can cancel the explosion overall to ensure blocks aren't destroyed but that also cancels the explosion animation and effects. Blocking the player damage for the most part was straight forward enough (aside from a 1/2 heart that I am trying to track down that I think is some sort of concussive damage not coming directly from the creeper).
     
  2. Offline

    TnT

    Moved thread to plugin development forum.
     
  3. Offline

    Edward Hand

    What can I say? You are correct. As it is now, if you want to stop the explosion damaging blocks, you'll have to just replace the blocks after the fact.
     
  4. Offline

    Nohup

  5. Offline

    DHowett

    I saw the same issue in trying to remove blocks from an explosion, so I modified Explosion.java to take the (possibly modified) blocklist and convert it back into an array of ChunkPositions.
    This works fine, but you also have to deal with the client-side explosion prediction. Any blocks you remove from the list will disappear to the client and then pop back into existence once the client gets an update from the server. It's a little jarring and it causes movement glitches (like, if you were to walk into a now-"unoccupied" space, you'd jerk around for a bit and then be ejected from the area when the block popped back in.)
     
Thread Status:
Not open for further replies.

Share This Page