BlockPopulator sometimes fails to work

Discussion in 'Plugin Development' started by Plague, Nov 19, 2011.

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

    Plague

    I wanted to get rid of those "sand spots" anywhere (mostly underwater) except for the desert biome.

    I created a BlockPopulator and applied it and it works. BUT it sometimes fails and some chunks are not rid of the sand. Is there a problem with my code?
    main class (open)

    Code:
    public class PlgNoSand extends JavaPlugin {
    
        public void onEnable() {
            // register events
            WorldListener initListener = new WorldListener() {
                public void onWorldInit(WorldInitEvent event) {
                    for (World world : getServer().getWorlds())
                        world.getPopulators().add(new PlgNoSandRemover());
                }
            };
            getServer().getPluginManager().registerEvent(Event.Type.WORLD_INIT, initListener, Event.Priority.Normal, this);
            // version info
            PluginDescriptionFile pdfFile = this.getDescription();
            System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!");
        }
    
        public void onDisable() {
            PluginDescriptionFile pdfFile = this.getDescription();
            System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " stopping...");
        }
    
        public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
            String cmd = command.getName();
            if (cmd.equalsIgnoreCase("plg_removesand")) {
                if (!sender.isOp()) {
                    sender.sendMessage(ChatColor.RED + "You have to be OP!");
                    return true;
                }
                if (!(sender instanceof Player)) {
                    sender.sendMessage(ChatColor.RED + "You have to be a player!");
                    return true;
                }
                Player player = (Player)sender;
                Chunk chunk = player.getLocation().getBlock().getChunk();
                PlgNoSandRemover.removeSand(chunk);
                return true;
            }
            return false;
        }
    
    }

    block populator (open)

    Code:
    public class PlgNoSandRemover extends BlockPopulator {
    
        private static int airId = Material.AIR.getId();
        private static int sandId = Material.SAND.getId();
        private static int sandstoneId = Material.SANDSTONE.getId();
    
        public void populate(World world, Random random, Chunk source) {
            removeSand(source);
        }
    
        public static void removeSand(Chunk chunk) {
            for (int x = 0; x < 16; ++x) {
                for (int z = 0; z < 16; ++z) {
                    if (chunk.getBlock(x, 0, z).getBiome() == Biome.DESERT) continue;
                    for (int y = 0; y < 128; ++y) {
                        Block block = chunk.getBlock(x, y, z);
                        int id = block.getTypeId();
                        if (id == sandId || id == sandstoneId) {
                            if (block.getRelative(BlockFace.UP).getTypeId() == airId)
                                block.setType(Material.GRASS);
                            else
                                block.setType(Material.DIRT);
                        }
                    }
                }
            }
        }
    
    }


    Here's a map of the generated level (disregard black pixels), you can see the bug in the upper right corner. You can also see that it worked in the center (there's a swamp with clay spots).
    map (open)

    [​IMG]


    Update: I used the CHUNK_POPULATED event instead of Block Populator (even if the docs say you should do it the other way around). It has the same problem, just not that often (but maybe I'm imagining the "often" part).
    -----------
     
  2. Offline

    DDoS

    When you're listening for world initialization, shouldn't you apply the populator to the word that's initializing only, instead of all worlds? Else wouldn't some worlds have the populator apply more than once?
     
  3. Offline

    bleachisback

    maybe the desert biome just happens to start at that spot, and extends into the ocean?
     
  4. What @bleachisback said.
    It might also be the case that your on an older part of your map and biomes got shifted again.
     
  5. Offline

    Plague

    Even if, the populator removes all sand, so why would applying it twice bring it back?
    Desert biome would not have that shallow water, clay in it and mostly the sand would be connected
    This is a newly generated map.
     
  6. Perhaps it is called before the sand making blockGenerator sometimes?
     
  7. Offline

    Plague

    Well I tested if there are any other blockpopulators, and the list is empty (the list I add to). Maybe it's the vanilla one, but that sure is called before mine because Villages are there.

    I tested on 1.0 unstable bukkit now and the problem stays
     
  8. Offline

    ZNickq

    @Plague
    The code is perfect :confused:
    The only thing i could think of is that the map generates with somehow falling sand, which is an entity, not a block...maybe add a delay to removeSand?

    Also, that area might be the spawn point (it probably is, since the player spawns on sand)!
    Populators don't work in the spawn point!
     
  9. Offline

    Plague

    That I didn't know, so I maybe have to do this some day, but the areas you can see is shallow water in swamps (at least in this particular map) so I don't think falling sand is the case here :(
    Unfrtunately no, the spawn point is somewhere near the centre. Actually It does work for me (because of the world init thing I think) and around the spawn point, i.e. the blocks generated right after the start of server with no map, it always works. It's the areas generated on the fly that sometimes fail.
     
  10. Offline

    DDoS

    Well, still wouldn't it be better to only apply one populator, for performance purposes? Also, when exactly does a world initialize? Isn't it when the server boots up, and you get the loading messages (with the percentages of completion)? Because if that is the case, and you only register the populators in onEnable, all the worlds have already initialized at that time (unless you load a new one with a multiword plugin).
     
  11. Offline

    Plague

    that's what load:startup is for in plugin.yml

    I mean really, you are not trying to solve my problem... it WORKS for the spawn location which is generate on world init, what does NOT work is the part that is generated when I am flying over the world and generating the map. And it works on some chunks and others not.
     
  12. Offline

    DDoS

    I am trying to help you, I just need more info... Could you apply your sand removing method to chunks on load up (using a chunk listener)?
     
  13. Offline

    Plague

    I apply the method by hand using a command so I can achieve my goal at this moment, which works as it should.
    And as I said it does work for most of the time, only sometimes it fails like this.

    I even tried applying it to all 4 chunks around the "source" one, but to no avail.

    Oh and I use this for the world populator setting now (which of course didn't help at all):
    Code:
    event.getWorld().getPopulators().add(new PlgNoSandRemover());
     
  14. Offline

    DDoS

    Maybe you should try populating a chunk when a chunk populate event is called for it. This should hopefully apply to all new chunks. Although this is maybe not the best way to do it, it could work, and I think it's worth a try.
     
  15. Offline

    ledaal10

    [tnt]were Is 1.0.0 Bukkit[creeper]
     
  16. Offline

    Plague

    Well the docs say I should use the populator instead. I actually started coding with the vent but then chaned it :)
    But you're right, I should test that, BRB.
     
  17. Offline

    DDoS

    I saw that too. But since the block populator don't seem to work well enough, I see no harm in trying out this method.
     
  18. Offline

    Plague

    Well, from the looks of it (few mites of testing) it WORKS! Thanks! I really totally forgot about the event, ven though I coded it at first, silly me.
    Its a workaround but I'm glad for it anyway.
     
  19. Offline

    DDoS


    Well, happy to see I could help :D.
     
  20. Offline

    Plague

    Well actually it happened again :) So nope, even this fails SOMETIMES (which is the worst part here I think).
     
  21. Offline

    DDoS

    Well, this is either a problem with Bukkit, or your populator has an problem. Why not try to remove the desert biome check? I guess you should try to decompose it, to see what could be the problem.
     
  22. Offline

    Plague

    Trust me I know how to debug my code. I removed that a while ago to test, that's not the problem. It looks like concurrency or CPU load problem maybe. But that would mean there's a bug somewhere when ticks go off or something, but that's something only @Dinnerbone would know how to find in this.

    Looks like I have to wait for the bugtracker to come up again...
     
  23. Offline

    DDoS


    Well, good luck with this. I have offered everything I could, I'm off!
     
  24. Offline

    Plague

    Thanks anyway, at least it fails less now :)
     
  25. Offline

    codename_B

    @Plague I believe it's to do with how the populator is called, some chunks don't get populated. There was a pull a while back to change the mechanics of population but like so many great pulls it got forgotten.
     
  26. Offline

    Plague

    Damn. Thanks for the info. Will have to report on leaky when it's up then.
     
  27. Offline

    The_Coder

    Plague
    I have a question I am making a plugin with BlockPopulators. My plugin will based in the nether. So my BlockPopulator will remove and add glowstone based on a value in a config. My question is how do I regenerate the glowstone.
     
  28. Offline

    Plague

    What do you mean exactly? I go over all blocks and when I find sand under water I turn it into dirt. Don't know what you mean by regeneration.
     
  29. Offline

    mossyblog

    So after a 2days of testing I've finally concluded that this is a bug and screw anyone who says differently hehehehe (kidding). The bug has been logged but I do have a work-around for those of you who are still suffering the pain.
    What I have found is that the BlockPopulator works for about 60-70% of the time but for the rest there seems to be a post-populate event of some kind lingering which then generates Ores. That being said I've found if you place a Glowstone at (0,0,0) within the chunk (which it has no natural business being there) this can act as a marker for you to do regenerate the chunk on ChunkPopulate. In that code just remove the marker and that should get you back to a "as per design" solution. It also reduces a lot of unnecessary ScheduledTasks etc.
     
  30. Offline

    xTrollxDudex

    mossyblog
    ..............
    This thread is 2 years old. OP, has not been active since last year.

    Y U NECROBUMP
     
    Garris0n likes this.
Thread Status:
Not open for further replies.

Share This Page