Getting sponges to work?

Discussion in 'Plugin Development' started by Jnorr44, Jul 4, 2012.

  1. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I know this may look like I am doing too much work or something, but this same method is set up to be added to for other blocks, so don't worry about that. What I am trying to do is make sponges work, by checking the config for the variable configRadius, and setting a radius around that from water to air (only water is being changed). Why isn't it working?
    Code:
    package com.github.JamesNorris.Flow;
     
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockPlaceEvent;
     
    public class PlacedBlockEvents implements Listener {
        private Flow plugin;
        public PlacedBlockEvents(final Flow instance) {
            plugin = instance;
        }
        @EventHandler(priority = EventPriority.HIGHEST)
        public void BPE(BlockPlaceEvent event){
            if(!event.isCancelled()){
                Block placed = event.getBlock();
                int configFace = plugin.getConfig().getInt("spongeRadius");
                if (placed.getType() == Material.SPONGE){//SPONGES
                    final Block block = new Location(placed.getWorld(), placed.getLocation().getX(), placed.getLocation().getY(), placed.getLocation().getZ()).getBlock();
                    final World world = block.getWorld();
                    final int x = block.getX();
                    final int y = block.getY();
                    final int z = block.getZ();
                    final int minX = x - configFace;
                    final int minY = y - configFace;
                    final int minZ = z - configFace;
                    final int maxX = x + configFace;
                    final int maxY = y + configFace;
                    final int maxZ = z + configFace;
                    for (int counterX = minX; counterX <= maxX; counterX++) {
                        for (int counterY = minY; counterY <= maxY; counterY++) {
                            for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
                                final Block face = world.getBlockAt(counterX, counterY, counterZ);
                                if (face.getType() != Material.WATER){
                                    break;
                                }
                                if (face.getType() == Material.WATER || face.getType() == Material.STATIONARY_WATER) { 
                                    face.setType(Material.AIR);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    This post has been edited 1 time. It was last edited by Jnorr44 Jul 4, 2012.
  2. Offline

    andf54

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I have few comments:
    Code:
    if (face.getType() != Material.WATER){
       break;
    }
    
    Is useless, because you make the same check right after it.

    You loop trough all x, y but not z. Remove the "break" see if it improves.

    You are changing only one cube face to air which may be imminently fixed back to water.
  3. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    got it... fixed thanks!
  4. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    now what would I put if I want to cancel that event on block break?
    EDIT: I tried setCancelled, but the water doesnt form streams back into the hole left by the sponge...

    This post has been edited 1 time. It was last edited by Jnorr44 Jul 4, 2012.
  5. Offline

    andf54

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Not sure what you mean. If I understand you correctly, you want to make the water flow towards the spondge and not fix itself.

    Try modifying BlockFormToEvent. You need to cancel all events where WATER forms to STATIONARY_WATER.
  6. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    No, I want it so when you place a sponge, the water is removed (done that), then when the sponge is removed, the blocks that were water before, are changed back into water. (ignoring air and other blocks in the area)
  7. Offline

    andf54

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    There is no certain way to do it, unless you want to save all block locations, that have been changed, to the disk.

    You could just set every block in the radius that got drained back to water.

    The special cases make it very messy though. If the player doesn't submerge the sponge deep enough, then it will result in a fountain effect.

    Those problems may be avoided if you set radius to 1. Just replace the sponge with water when you remove it. Hopefully that additional water block will fix the water around the sponge.
  8. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    wait... is there a way to just remove the water around the sponge, instead of turning the water to air?
  9. Offline

    andf54

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Nop, removing and setting to air are basically synonyms.
  10. Offline

    EnvisionRed

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Maybe save locations and a List in a hashmap, where the location is the location of the sponge and the List contains locations of where water was previously?
    For an BlockBreakEvent it would be simple enough to call that hashmap and restore water.
  11. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Hmm, but what about the edges of the water (at the outside of the sponges' affect). Could those be turned into streams?

    EDIT: EnvisionRed great idea! trying now!

    This post has been edited 1 time. It was last edited by Jnorr44 Jul 4, 2012.
  12. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    How would I define the list changed in this?
    Code:
    package com.github.JamesNorris.Flow;
     
    import java.awt.List;
    import java.util.HashMap;
    import java.util.Map;
     
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockPlaceEvent;
     
    public class PlacedBlockEvents implements Listener {
        private Flow plugin;
        public PlacedBlockEvents(final Flow instance) {
            plugin = instance;
        }
        public Map<Location, List>
        blocks = new HashMap<Location, List>();
        @EventHandler(priority = EventPriority.HIGHEST)
        public void BPE(BlockPlaceEvent event){
            if (!event.isCancelled()) {
                Block placed = event.getBlock();
                int configFace = plugin.getConfig().getInt("spongeRadius");
                if (placed.getType() == Material.SPONGE){//SPONGES
                    final Block block = new Location(placed.getWorld(), placed.getLocation().getX(), placed.getLocation().getY(), placed.getLocation().getZ()).getBlock();
                    final World world = block.getWorld();
                    final int x = block.getX();
                    final int y = block.getY();
                    final int z = block.getZ();
                    final int minX = x - configFace;
                    final int minY = y - configFace;
                    final int minZ = z - configFace;
                    final int maxX = x + configFace;
                    final int maxY = y + configFace;
                    final int maxZ = z + configFace;
                    for (int counterX = minX; counterX <= maxX; counterX++) {
                        for (int counterY = minY; counterY <= maxY; counterY++) {
                            for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
                                final Block face = world.getBlockAt(counterX, counterY, counterZ);
                                if (face.getType() == Material.WATER || face.getType() == Material.STATIONARY_WATER) {
                                    blocks.put(placed.getLocation(), changed.getLocation());
                                    face.setType(Material.AIR);
                                    if (placed.getType() == Material.AIR){
                                        event.setCancelled(true);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    So that its a list of all the blocks that were within the "configFace" (radius), and that were water?
  13. Offline

    andf54

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    You will also need to save that hashmap, because you don't want to loose the functionality when you /reload or reboot.
  14. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    This is working, but only partially. If you destroy 1 sponge, all of thier water returns to normal. How would I fix this?
    Code:
    package com.github.JamesNorris.Flow;
     
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
     
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.block.BlockState;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.event.block.BlockPlaceEvent;
     
    public class PlacedBlockEvents implements Listener {
        private Flow plugin;
        public PlacedBlockEvents(final Flow instance) {
            plugin = instance;
        }
        public HashSet<BlockState>
        blocks = new HashSet<BlockState>();
        public Map<Location, HashSet<BlockState>>
        area = new HashMap<Location, HashSet<BlockState>>();
        @EventHandler(priority = EventPriority.HIGHEST)
        public void BPE(BlockPlaceEvent event){
            if (!event.isCancelled()) {
                Block placed = event.getBlock();
                Location placedloc = event.getBlock().getLocation();
                int configFace = plugin.getConfig().getInt("spongeRadius");
                if (placed.getType() == Material.SPONGE){
                    final Block block = new Location(placed.getWorld(), placed.getLocation().getX(), placed.getLocation().getY(), placed.getLocation().getZ()).getBlock();
                    final World world = block.getWorld();
                    final int x = block.getX();
                    final int y = block.getY();
                    final int z = block.getZ();
                    final int minX = x - configFace;
                    final int minY = y - configFace;
                    final int minZ = z - configFace;
                    final int maxX = x + configFace;
                    final int maxY = y + configFace;
                    final int maxZ = z + configFace;
                    for (int counterX = minX; counterX <= maxX; counterX++) {
                        for (int counterY = minY; counterY <= maxY; counterY++) {
                            for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
                                final Block face = world.getBlockAt(counterX, counterY, counterZ);
                                if (face.getType() == Material.WATER || face.getType() == Material.STATIONARY_WATER) {
                                    blockChange(face, placed, placedloc);
                                }
                            }
                        }
                    }
                }
            }
        }
        public void blockChange(Block face, Block placed, Location placedloc){
            Location loc = placed.getLocation();
            BlockState blockstate = face.getState();
            blocks.add(blockstate);
            area.put(loc, blocks);
            face.setType(Material.AIR);
        }
       
        public void checkIfBroken(Location loc) {
            for (BlockState state : area.get(loc)) {
                state.update(true);
            }
        }
        @EventHandler(priority = EventPriority.HIGHEST)
        public void BBE(BlockBreakEvent event){
            Block destroyed = event.getBlock();
            if (destroyed.getType() == Material.SPONGE){
                checkIfBroken(destroyed.getLocation());
            }
        }
    }
  15. Offline

    EnvisionRed

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I was hoping that was implied.
  16. Offline

    ZachBora

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I think you need to listen to onBlockFromTo and verify if a sponge is near. It's the event I used to make water unable to spread outside a zone.
  17. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I thought that to, but now it works without it, saving time...
    NEW PROBLEMS!
    • If a half bubble is formed above water, it does not get filled in, although I have fixed this problem for below water.
    Code:
    package com.github.JamesNorris.Flow;
     
    import java.util.HashMap;
    import java.util.HashSet;
     
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.World;
    import org.bukkit.block.Block;
    import org.bukkit.block.BlockState;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.EventPriority;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.BlockBreakEvent;
    import org.bukkit.event.block.BlockFromToEvent;
    import org.bukkit.event.block.BlockPlaceEvent;
     
    public class SpongeEvents implements Listener {
        private final Flow plugin;
     
        public SpongeEvents(final Flow instance) {
            plugin = instance;
        }
     
        public HashSet<BlockState> blocks = new HashSet<BlockState>();
        public HashMap<Location, HashSet<BlockState>> area = new HashMap<Location, HashSet<BlockState>>();
     
        @EventHandler(priority = EventPriority.HIGHEST) public void BPE(final BlockPlaceEvent event) {
            if (!event.isCancelled()) {
                final Block placed = event.getBlock();
                final int configFace = plugin.getConfig().getInt("spongeRadius");
                if (placed.getType() == Material.SPONGE) {
                    final Block block = new Location(placed.getWorld(), placed.getLocation().getX(), placed.getLocation().getY(), placed.getLocation().getZ()).getBlock();
                    final World world = block.getWorld();
                    final int x = block.getX();
                    final int y = block.getY();
                    final int z = block.getZ();
                    final int minX = x - configFace;
                    final int minY = y - configFace;
                    final int minZ = z - configFace;
                    final int maxX = x + configFace;
                    final int maxY = y + configFace;
                    final int maxZ = z + configFace;
                    for (int counterX = minX; counterX <= maxX; counterX++) {
                        for (int counterY = minY; counterY <= maxY; counterY++) {
                            for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
                                final Block face = world.getBlockAt(counterX, counterY, counterZ);
                                if (face.getType() == Material.WATER || face.getType() == Material.STATIONARY_WATER && plugin.getConfig().getBoolean("enableWater") == true) {
                                    blockChange(face, placed);
                                }
                                if (face.getType() == Material.LAVA || face.getType() == Material.STATIONARY_LAVA && plugin.getConfig().getBoolean("enableLava") == true) {
                                    blockChange(face, placed);
                                }
                            }
                        }
                    }
                }
            }
        }
     
        public void blockChange(final Block face, final Block placed) {
            final Location loc = placed.getLocation();
            final BlockState blockstate = face.getState();
            blocks.add(blockstate);
            area.put(loc, blocks);
            face.setType(Material.AIR);
        }
     
        public void checkIfBroken(Location loc, Block destroyed) {
            if (area.containsKey(loc)) {
                if (area.get(destroyed) == blocks){
                    for (final BlockState state : area.get(loc)) {
                        state.update(true);
                    }
                }
            }
        }
     
        @EventHandler(priority = EventPriority.HIGHEST) public void BBE(final BlockBreakEvent event) {
            final Block destroyed = event.getBlock();
            if (plugin.getConfig().getBoolean("enableSponges") == true) {
                if (destroyed.getType() == Material.SPONGE) {
                    if (plugin.getConfig().getBoolean("liquidReplacement") == true) {
                        final Location loc = destroyed.getLocation();
                        checkIfBroken(loc, destroyed);
                    } else {
                        final int configFace = plugin.getConfig().getInt("spongeRadius");
                        final Block block = new Location(destroyed.getWorld(), destroyed.getLocation().getX(), destroyed.getLocation().getY(), destroyed.getLocation().getZ()).getBlock();
                        final World world = block.getWorld();
                        final int x = block.getX();
                        final int y = block.getY();
                        final int z = block.getZ();
                        final int minX = x - configFace - 1;
                        final int minY = y - configFace - 1;
                        final int minZ = z - configFace - 1;
                        final int maxX = x + configFace + 1;
                        final int maxY = y + configFace + 1;
                        final int maxZ = z + configFace + 1;
                        for (int counterX = minX; counterX <= maxX; counterX++) {
                            for (int counterY = minY; counterY <= maxY; counterY++) {
                                for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
                                    final Block face = world.getBlockAt(counterX, counterY, counterZ);
                                    if (face.getData() == 0x8) {
                                        if (face.getType() != Material.CACTUS || face.getType() != Material.SUGAR_CANE_BLOCK || face.getType() != Material.SNOW_BLOCK) {
                                            if (face.getType() != Material.SOIL || face.getType() != Material.CROPS || face.getType() != Material.WOOL || face.getType() != Material.RAILS) {
                                                if (face.getType() != Material.WOOD_DOOR || face.getType() != Material.IRON_DOOR || face.getType() != Material.SIGN_POST) {
                                                    if (face.getType() != Material.BED_BLOCK || face.getType() != Material.REDSTONE_WIRE || face.getType() != Material.PISTON_BASE) {
                                                        if (face.getType() != Material.PISTON_STICKY_BASE || face.getType() != Material.PISTON_EXTENSION || face.getType() != Material.RED_MUSHROOM) {
                                                            if (face.getType() != Material.HUGE_MUSHROOM_1 || face.getType() != Material.HUGE_MUSHROOM_2 || face.getType() != Material.VINE) {
                                                                if (plugin.getConfig().getBoolean("enableWater") == true) {
                                                                    face.setType(Material.STATIONARY_WATER);
                                                                    face.setData((byte) 0x3);
                                                                }
                                                                if (plugin.getConfig().getBoolean("enableLava") == true) {
                                                                    face.setType(Material.STATIONARY_LAVA);
                                                                    face.setData((byte) 0x2);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if (face.getType() == Material.WATER || face.getType() == Material.STATIONARY_WATER && plugin.getConfig().getBoolean("enableWater") == true) {
                                        face.setType(Material.STATIONARY_WATER);
                                        face.setData((byte) 0x3);   
                                    }
                                    if (face.getType() == Material.LAVA || face.getType() == Material.STATIONARY_LAVA && plugin.getConfig().getBoolean("enableLava") == true) {
                                        face.setType(Material.STATIONARY_LAVA);
                                        face.setData((byte) 0x2);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        @EventHandler(priority = EventPriority.HIGHEST)
        public void BFTE(BlockFromToEvent event){
            if (!event.isCancelled()) {
                if (plugin.getConfig().getBoolean("enableSponges") == true){
                    Block changed = event.getBlock();
                    int configFace = plugin.getConfig().getInt("spongeRadius");
                    if (changed.getType() == Material.WATER || changed.getType() == Material.STATIONARY_WATER){
                        Block block = event.getToBlock();
                        World world = block.getWorld();
                        int x = block.getX();
                        int y = block.getY();
                        int z = block.getZ();
                        int minX = x - configFace;
                        int minY = y - configFace;
                        int minZ = z - configFace;
                        int maxX = x + configFace;
                        int maxY = y + configFace;
                        int maxZ = z + configFace;
                        for (int counterX = minX; counterX <= maxX; counterX++) {
                            for (int counterY = minY; counterY <= maxY; counterY++) {
                                for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
                                    final Block face = world.getBlockAt(counterX, counterY, counterZ);
                                    if (face.getType() == Material.SPONGE) {
                                        event.setCancelled(true);
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    If you can fix any or all of these, please post it below!

    This post has been edited 5 times. It was last edited by Jnorr44 Jul 5, 2012.
  18. Offline

    ferrybig

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    instead of saving al the blocks that are inside the area of the sponge (and have risk of runnin gout of memory)
    why not do this on runtime, just ad this listener methode:
    Code:java
    1.  
    2. @EventHandler(priority = EventPriority.HIGHEST)
    3. public void BPE(BlockFromToEvent event){
    4. if (!event.isCancelled()) {
    5. Block placed = getBlock();
    6. int configFace = plugin.getConfig().getInt("spongeRadius");
    7. if ( placed.getType() == Material.WATER || placed.getType() == Material.STATIONARY_WATER)){
    8. final Block block = event.getToBlock();
    9. final World world = block.getWorld();
    10.  
    11. final int x = block.getX();
    12. final int y = block.getY();
    13. final int z = block.getZ();
    14.  
    15. final int minX = x - configFace;
    16. final int minY = y - configFace;
    17. final int minZ = z - configFace;
    18.  
    19. int maxX = x + configFace;
    20. int maxY = y + configFace;
    21. int maxZ = z + configFace;
    22.  
    23. for (int counterX = minX; counterX <= maxX; counterX++) {
    24. for (int counterY = minY; counterY <= maxY; counterY++) {
    25. for (int counterZ = minZ; counterZ <= maxZ; counterZ++) {
    26. final Block face = world.getBlockAt(counterX, counterY, counterZ);
    27. if (face.getType() == Material.SPONGE) {
    28. event.setCancelled(true);return;
    29. }
    30. }
    31. }
    32. }
    33. }
    34. }
    35. }
  19. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @ferrybig
    After I add this should I remove the HashSet and HashMap?
    EDIT: and if I set a max radius of 10, how much memory could this take up?
    EDITEDIT: Changed the code that I just posted...
    EDITEDITEDIT: Added another problem, that I will eventually have to fix..

    This post has been edited 3 times. It was last edited by Jnorr44 Jul 5, 2012.
  20. Offline

    BranicYeti

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Great plugin. Keep try Jnorr44, you'll get there. :)
  21. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Still in need of help....
  22. Offline

    ZachBora

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    May I suggest you look at WorldGuard source which does a fine job of simulating sponge?

    This post has been edited 1 time. It was last edited by ZachBora Jul 5, 2012.
  23. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    it fixes 2 of the 3 problems, and requires much more code, and the source is scattered, and I want to learn from this, not just copy some code and put a licence on it.
  24. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @ferrybig
    Jeez, i tried what you said and it fixed a problem! Thanks!
    EDIT: 2 of 3 down, 1 more to go, and its the same problem I get with worldguard sponges.

    This post has been edited 1 time. It was last edited by Jnorr44 Jul 5, 2012.
  25. Offline

    BranicYeti

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    What is the third problem with sponges that you are trying to solve?
  26. Offline

    ZachBora

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I've never had a problem with worldguard sponges... what is it? Whatever it is, it's a feature.
  27. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    When you remove a sponge from the surface, a water "crater" is left. For me this tries to fix itself, but it doesnt work completely. Thats all I have to do to finish sponges.
  28. Offline

    ferrybig

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    I think the water crator was also there in the classic game, so the sponges just work, but you do want to add it as feacture?
  29. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    @ferrybig
    Yeah, if players don't want it, they can remove it from the config.

    This post has been edited 1 time. It was last edited by Jnorr44 Jul 5, 2012.
  30. Offline

    Jnorr44

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    again, still in need of help...

Share This Page