1.12.2 How to set blocks one by one?

Discussion in 'Spigot Plugin Development' started by Sean0402, Jan 25, 2020.

  1. Hey all, I have a region manager where you do stuff similar to worldedit in the sense of settigs blocks.

    I currently store 2 locations and grab all the blocks inside that location in a List<Block>.

    I was wondering how do I go about pasting the blocks "1 by 1"? I heard you can do it with block states or something along those lines, but how would I go about doing this?

    I basically want it to place blocks one by one when they type /set <block>.
     
  2. If this is merely for a visual effect (and not for speeding things up) just use a repeating or a delayed task
     
  3. It's just to stop people from setting loads of blocks at once with a delay on the blocks.
     
  4. Not quite sure what you're trying to achieve (probably me just being dumb) If you're trying to do it so the server isn't being overloaded I'd do it in several broken up async tasks so the main thread isn't hindered, and split up in however many parts based on the amount of blocks being edited
     
  5. it's for a visual effect as you said. Merely to look good.
     
  6. Oh okay then I would go about it like I said before; use a delayed task like so:
    Make a list of "to-do" blocks -> add all of the blocks to this.
    Then, make a task that runs (however long you want)
    - While to-do isn't empty, run the delayed task which will get the next block from the "to-do" list, change it, and remove it.

    Alternatively this can be done with a repeating task too
     
  7. So this is how I currently get my locations,
    Code (Text):
    public static List<Block> blocksFromTwoPoints(Location loc1, Location loc2) {
            List<Block> blocks = new ArrayList<>();
            int topBlockX = (Math.max(loc1.getBlockX(), loc2.getBlockX()));
            int bottomBlockX = (Math.min(loc1.getBlockX(), loc2.getBlockX()));

            int topBlockY = (Math.max(loc1.getBlockY(), loc2.getBlockY()));
            int bottomBlockY = (Math.min(loc1.getBlockY(), loc2.getBlockY()));

            int topBlockZ = (Math.max(loc1.getBlockZ(), loc2.getBlockZ()));
            int bottomBlockZ = (Math.min(loc1.getBlockZ(), loc2.getBlockZ()));

            for (int x = bottomBlockX; x <= topBlockX; x++) {
                for (int z = bottomBlockZ; z <= topBlockZ; z++) {
                    for (int y = bottomBlockY; y <= topBlockY; y++) {
                        // Grab all blocks in the middle
                        Block block = loc1.getWorld().getBlockAt(x, y, z);
                        blocks.add(block);
                    }
                }
            }
            return blocks;
        }
    then I grab it from here
    Code (Text):
                                        List<Block> blocks = LocationMethod.blocksFromTwoPoints(FactionWorldedit.selectedLocations.get(p).get(0), FactionWorldedit.selectedLocations.get(p).get(1));
     
    I thought this would work but is your way the only way for it really to work?
    Code (Text):
    Bukkit.getScheduler().scheduleSyncRepeatingTask(FactionWorldedit.getInstance(), () -> {
                                                    b.getState().update(true, false);
                                                    b.getLocation().getWorld().spawnParticle(Particle.CLOUD, b.getLocation(), 6);
                                                }, 0L, 20L);
     
  8. drives_a_ford

    Moderator

    You don't really need to store all your blocks in a list. All you need to know is the min and max for x, y and z. You've already calculated those.
    Then what you can do is create a new Runnable that has member fields for x, y and z that start from the minimum. In the run method that runnable gets the block at the location and does whatever it needs and then increments x. If x is bigger than its max, set it to its min and increment z. If z is bigger than its max set it to its min and increment y. The order of the coordinates does not matter.

    But bare in mind that if you only ever do 1 block in a tick, you're going to have a horrible time changing large regions. You see, a 10x10x10 block region is 1000 blocks and would take 50 seconds to change. Whereas a 100x10x100 would take more than an hour. You'd be better off doing a number of different changes in a single tick.
     
    • Like Like x 1
    • Agree Agree x 1