Solved Why is the chunk getting updated?

Discussion in 'Spigot Plugin Development' started by Hello1231, Mar 28, 2020.

  1. So I'm using this code:
    Code (Java):
    private static HashMap<String, Integer> time = new HashMap<>();
    private static HashMap<String, Integer> taskID = new HashMap<>();
    Plugin plugin = Main.getPlugin(Main.class);

    @EventHandler
        public void newChunkEvent(ChunkPopulateEvent e) {
            if (plugin.getConfig().getBoolean("Enabled")) {
                int x = 16*e.getChunk().getX();
                int z = 16*e.getChunk().getZ();
                Bukkit.broadcastMessage("New chunk loaded at"+x+" "+z+"!");
                startTimer("Kelp Ore", x, z, e.getWorld(), plugin.getConfig().getInt("Ores.Kelp Ore.Amount"));
                startTimer("Petrified Wood", x, z, e.getWorld(), plugin.getConfig().getInt("Ores.Petrified Wood.Amount"));
                }}

    public static void stopTimer(String bl) {
            Bukkit.getScheduler().cancelTask(taskID.get(bl));
            time.remove(bl);
        }
     
        public static Main getInstance() {return Main.instance;}
     
        public void startTimer(String name, int x, int z, World world, int t) {
            BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
            String bl = world.getName()+x+z+name;
            time.put(bl, t);
            taskID.put(bl, scheduler.scheduleSyncRepeatingTask(plugin, () -> {
                    if (time.get(bl) == 0 || plugin.getConfig().getBoolean("Ores." + name + ".Enabled") == false) {
                        stopTimer(bl);
                        return;
                    }
                    else {
                        Random rand = new Random();
                        int rand1 = rand.nextInt(16);
                        int rand2 = rand.nextInt(16);
                        int randy = plugin.getConfig().getInt("Ores." + name + ".MinY") + rand.nextInt(plugin.getConfig().getInt("Ores." + name + ".MaxY") - plugin.getConfig().getInt("Ores." + name + ".MinY"));
                        int randx = rand1 + x;
                        int randz = rand2 + z;
                        Block blo = world.getBlockAt(randx, randy, randz);
                        if (blo.getType() == Material.STONE || blo.getType() == Material.DIORITE || blo.getType() == Material.ANDESITE || blo.getType() == Material.GRANITE) {
                            ListenerClass.setHead(blo, name);
                            time.put(bl, time.get(bl) - 1);
                        }
                    }
            }, 0L, 2L));}

    private static String getHeadText(String name) {
            for (Heads head : Heads.values()) {
                if (head.getName().equalsIgnoreCase(name)) {
                    return head.getTexture();
                }
            }
            return null;
        }

    public static void setHead(Block b, String name) {
                b.setType(Material.PLAYER_HEAD, false);
                BlockState headData = b.getState();
                GameProfile profile = new GameProfile(UUID.randomUUID(), null);
             
                profile.getProperties().put("textures", new Property("textures", getHeadText(name)));
                 try
                    {
                        Field profileField = headData.getClass().getDeclaredField("profile");
                        profileField.setAccessible(true);
                        profileField.set(headData, profile);
                    }
                    catch (IllegalArgumentException|NoSuchFieldException|SecurityException | IllegalAccessException error)
                    {
                        error.printStackTrace();
                    }
                 headData.update(false, false);
        }
    When ever I run this, it updates the chunk, causing more chunks to load around it. What could be causing it to update?
     
  2. Instead of letting us search through your code for any potential errors, what exactly are you trying to do? : )
     
    • Like Like x 2
  3. I'm trying to set a custom player head in a random spot on each chunk.
     
  4. thats why its getting updated. if you modify a block on the edge of a chunk, it updates the block next to it in the next chunk for the correct lighting values, which causes that chunk to load and update.
     
    • Agree Agree x 2
    • Like Like x 1
  5. I used b.setType(Material.PLAYER_HEAD, false); and headData.update(false, false); So I don't know why it would still be updating
     
  6. those prevent physics updates last i checked. it still does lighting checks which the chunks need to be loaded for. you MIGHT be able to remediate the issue by simply setting to 1-14 instead of 0-15 on each chunk
     
    • Like Like x 1
    • Informative Informative x 1
  7. You're not getting it. As @Warren1001 said, if the block your refer to as `b` is updated and is on the edge of the chunk, the chunk next to the current one will be updated. This is intended behavior. Think about the issues that would be present if this wasn't the case, for example: redstone signals on the edge of a chunk wouldn't continue into the one next to it.
     
    • Like Like x 1
  8. Is there any way I could prevent this or do I just have to avoid the edges of each chunk?
     
  9. Not to my knowledge, I would simply avoid chunk edges. This behavior is drilled into the game and is vital to block behavior.
     
    • Like Like x 1
  10. as far as i know, avoid the edges of the chunk. i think a minor design flaw of bukkit with setting blocks is regardless of where its done, going through bukkit will always update nearby chunks when it needs to (as that is what the system is designed for). you may be able to skirt this with a chunk generator (or simply adding your own chunk populator to the native chunk generators). there are guides for this that are around and should still work for recent minecraft versions. there are probably some nms methods that will not update other chunks, but you run the risk of running into undesired effects by doing that (lighting issues, water flow problems) unless you properly update it yourself afterwards.
     
    • Like Like x 1
  11. I made it so they can't be on the edges, like this:
    Code (Java):
    public void startTimer(String name, int x, int z, World world, int t) {
            BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
            String bl = world.getName()+x+z+name;
            time.put(bl, t);
            tries.put(bl, t*3);
            taskID.put(bl, scheduler.scheduleSyncRepeatingTask(plugin, () -> {
                    if (tries.get(bl) == 0 || time.get(bl) == 0 || plugin.getConfig().getBoolean("Ores." + name + ".Enabled") == false) {
                        stopTimer(bl);
                        return;
                    }
                    else {
                        Random rand = new Random();
                        int rand1 = rand.nextInt(14);
                        int rand2 = rand.nextInt(14);
                        int randy = plugin.getConfig().getInt("Ores." + name + ".MinY") + rand.nextInt(1 + plugin.getConfig().getInt("Ores." + name + ".MaxY") - plugin.getConfig().getInt("Ores." + name + ".MinY"));
                        int randx = 1+rand1+x;
                        int randz = 1+rand2+z;
                        Block blo = world.getBlockAt(randx, randy, randz);
                        if (blo.getType() == Material.STONE || blo.getType() == Material.DIORITE || blo.getType() == Material.ANDESITE || blo.getType() == Material.GRANITE) {
                            ListenerClass.setHead(blo, name);
                            time.put(bl, time.get(bl) - 1);
                        }
                        tries.put(bl, tries.get(bl) - 1);
                    }
            }, 0L, 2L));}
    It's definitely not spawning any heads on the edge, but the problem still persists. I tried changing it from ListenerClass.setHead(blo, name); to blo.setType(Material.ACACIA_STAIRS, false) and the problem stopped even when I let it go on the edge of the chunk again, so it must be a problem with ListenerClass.setHead();
    Code (Java):
        public static void setHead(Block b, String name) {
                b.setType(Material.PLAYER_HEAD, false);
                BlockState headData = b.getState();
                GameProfile profile = new GameProfile(UUID.randomUUID(), null);
             
                profile.getProperties().put("textures", new Property("textures", getHeadText(name)));
                 try
                    {
                        Field profileField = headData.getClass().getDeclaredField("profile");
                        profileField.setAccessible(true);
                        profileField.set(headData, profile);
                    }
                    catch (IllegalArgumentException|NoSuchFieldException|SecurityException | IllegalAccessException error)
                    {
                        error.printStackTrace();
                    }
                 headData.update(false, false);
        }

    EDIT: headData.update(false, false);
    in the above method is the problem. I'm not sure how to fix it though, that line is essential.

    EDIT 2: I found a solution! I made a simplified thread and posted it there:
    https://www.spigotmc.org/threads/blockstate-update-updates-chunk.426237/
     
    #11 Hello1231, Mar 29, 2020
    Last edited: Mar 30, 2020