Solved Mass change blocks

Discussion in 'Spigot Plugin Development' started by KingFaris10, Jun 27, 2016.

  1. Hi, I'm making a mini-game plugin and it sets the floor (64x64 blocks) to air, then after 5 seconds, it re-generates the floor as wool blocks (with different colours). My code works, but it's *VERY* laggy and nearly crashes the server (it does freeze the server). Is there a way I can do mass block updates with minimal lag? Currently I use block.setType() and block.setData(). I tried sendPacketChange or something, but that crashes the client.

    #1 KingFaris10, Jun 27, 2016
    Last edited: Jun 28, 2016
  2. Fairly sure this is because there is a lot of actions being called all at once on the same thread. I'm not experienced enough with performing actions on async threads to give you advice there. What you could try to do is, instead of trying to update all those blocks on the same server tick, setup a repeating task and update a small section of those blocks over many server ticks. It will take more game ticks to complete, but it should take less time in real life because the server won't hangup or freeze from being overloaded.
  3. @Hunky524 probably has one of the best solutions, add all the blocks you want to change to a list, and every tick change x at a time.
    • Optimistic Optimistic x 1
  4. I guess you could time every block place or divide the mass block placing.
  5. Thing is, the game works by having a floor, and most blocks disappear leaving only around 16-64 blocks left. After 5 seconds, all of these blocks are re-generated. Any players who fell through the floor (due to the blocks disappearing) lose, any players still on the left over blocks now are on the next round which causes the blocks to disappear again. If I did it on a scheduler, some blocks will show up and some blocks won't (for the players who are still alive). I think this is the best solution that I've found but it still doesn't meet my needs, thanks.
    #5 KingFaris10, Jun 27, 2016
    Last edited: Jun 28, 2016
  6. Hmm... yeah that's similar to the suggestion above, thanks anyway.
  7. Didn't see it cuz page refresh.. :)
    • Friendly Friendly x 1
  8. I would probably split the task into manageable parts and deal with each part asynchronously.
  9. You cant place blocks asynchronously.

    Do it without lighting updates, using NMS, if you need to place >100,000 blocks, and do it in sections, not all in one tick.
  10. Ah, I saw something by 'desht' about using NMS, no idea how to place blocks using NMS though, is it just like:
    Code (Text):

    int x = 0, y = 100, z = 0;
    int id = Material.WOOL.getId();
    byte data = 0;
    ((CraftWorld) world).getHandle().setTypeAndData(new BlockPosition(x, y, z), Block.getByCombinedId(id), (int) data);
    I'm guessing?
  11. As mentioned, not able to do that but thanks.
  12. Bump. I don't know how to use NMS to place a block without lighting updates. I've checked online and they're all for MC v1.7-
  13. This happens with all servers but, are you placing blocks over air? If you are that could be the cause of the problem. For some odd reason, whenever someone places a block over void or over air, it lags. Not sure why on earth it does this, but it just does. Therefore, when you are breaking all that wool, you are placing it back on open air correct?
  14. Yes. The issue is, the way I detect if a player loses is by checking in PlayerMoveEvent if the player's Y is below the floor's Y. If I set the floor to glass, the Y would be equal thus the players would never lose.
  15. Maybe it lags more because air blocks are transparent. Changing log to cobblestone is mostly switching the texture, no physics, light etc. have to be applied (just a wild guess).
  16. I'll test this theory.

    Edit: Worked well.
    #16 KingFaris10, Jun 28, 2016
    Last edited: Jun 28, 2016
  17. This should work for setting blocks using nms in 1.10
    Code (Java):

        public void setBlock(org.bukkit.block.Block block, int newBlock, byte data, boolean applyPhysics){
            net.minecraft.server.v1_10_R1.World world = ((CraftWorld) block.getWorld()).getHandle();
            net.minecraft.server.v1_10_R1.Chunk chunk = world.getChunkAt(block.getX() >> 4, block.getZ() >> 4);
            BlockPosition pos = new BlockPosition(block.getX(), block.getY(), block.getZ());
            int combined = newBlock + (data << 12);
            IBlockData ibd = Block.getByCombinedId(combined);
                world.setTypeAndData(pos, ibd, 3);
                world.setTypeAndData(pos, ibd, 2);
            chunk.a(pos, ibd);
    All the imports should be nms ones.
  18. You are VERY correct. In fact, I experienced 100ms lag at most when I changed from wool to planks and planks back to wool. Thanks, I now need to figure out a new mechanism for seeing if a player's not on the 'left over blocks'.
  19. I'll try this, thanks.

    Edit: Still not fast enough at all, freezes main thread, thanks anyway.
    #19 KingFaris10, Jun 28, 2016
    Last edited: Jun 28, 2016
  20. Actually @fujiboy4 made that observation, I just tried to explain it:rolleyes:

    Maybe instead of setting the blocks to air you can check the PlayerMoveEvent as well as the part where you used to set solid blocks to air. Instead of setting the blocks to air, you could change them to something else (like red wool). If a player is standing on such a block kill them, teleport them to a position that is below the platform so they fall of or anything similar cruel.
    Not sure if this leads to a better performance though. Especially with many players.
    • Friendly Friendly x 1