Replace a lot of blocks cause server lag

Discussion in 'Plugin Development' started by Kentakis, Sep 10, 2015.

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

    Kentakis

    Hello.

    I want to replace a lot of blocks (about 1000) it is not hard for world edit, but for my plugin it is.


    First, in hashmap as key I keep blocks which I operate.
    Seconds as HashMap loop (using iterator) I change these blocks to Material.AIR

    Code:
            for(Iterator<Map.Entry <Block,ItemStack>> it = blocks.entrySet().iterator();it.hasNext();){
               Map.Entry <Block,ItemStack> entry = it.next();
    e.getKey().setType(Material.AIR); 
    }
    
    And this cause the most lag (about 2 seconds)
     
  2. Offline

    Hiztree

    How are you selecting those "1000" blocks and saving them?
     
  3. Offline

    mythbusterma

    @Kentakis

    Don't save references to Blocks. Use BlockStates instead.
     
  4. Offline

    Kentakis

    @mythbusterma
    I change it to BlockState but now blockState.setType(Material.AIR) dont change blocks.

    @edit
    Ohh.. I forget to update block ... My fault.

    Best Regards

    ///
    I tested it, but it still cause lag. (for example scoreboard freeze for 2 seconds)
     
    Last edited: Sep 11, 2015
  5. Offline

    teej107

    @Kentakis Are you sure it causes lag for the server or just your client? Either way, you can just span your block replacing out over several ticks.
     
  6. Offline

    Kentakis

    @teej107 I'm replacing ~4,5k blocks

    It cause lag for server because console of server is lagged too
     
  7. Offline

    teej107

    @Kentakis
     
  8. Offline

    Kentakis

    @teej107

    U mean something like 'sleep' in this loop ?
     
  9. Offline

    teej107

    @Kentakis No. That will make it lag even more. It involves using a scheduler.
     
  10. Offline

    Kentakis

    @teej107

    So I have to runTaskLater(20L) - and replace 50% blocks

    And runTaskLater(30L) - to replace rest of blocks ?
     
  11. Offline

    teej107

  12. Offline

    Kentakis

  13. Offline

    teej107

    1. @Kentakis
    2. Create a repeating task
    3. In the task, use a loop (I assume you are using one to replace blocks)
    4. Check to see if X milliseconds have passed in the loop, if so, end the method early
    5. Also in the loop, replace the blocks.
    6. After the for loop, cancel the task.
     
  14. Offline

    Kentakis

    I think that the best way to solve problem is to use NMS.

    I try with:
    Code:
      net.minecraft.server.v1_7_R4.World w = ((CraftWorld) world).getHandle();
      w.setTypeAndData(b.getX(),b.getY(),b.getZ(),net.minecraft.server.v1_7_R4.Block.getById(typeId),typeId,data);
    
    2.
    Code:
    public void setBlockFast(Block b, int typeId, byte data) {
      net.minecraft.server.v1_7_R4.Chunk chunk = w.getChunkAt(b.getX() >> 4, b.getZ() >> 4);
      chunk.a( b.getX() & 0x0f, b.getY(), b.getZ() & 0x0f,net.minecraft.server.v1_7_R4.Block.getById(typeId), data);
       
      w.notify(b.getX(),b.getY(),b.getZ());
    }
    
    But it still lags main thread ... I try to use @teej107 idea, but this is too slow.


    If I change blocks to AIR, there is NO LAG, but If I change blocks to "NOT AIR" IT CAUSE BIG LAG

    I read something about light but I dont know how to use this knowledge
     
  15. Offline

    teej107

    That's your client.
     
  16. Offline

    mythbusterma

    @Kentakis

    Do what Teej said and spread out the changes over multiple ticks, this helps the server deal with the load.


    @teej107

    The server does do light calculations.
     
  17. Offline

    Kentakis

    @teej107 For sure this is not Client side.

    @mythbusterma Yes It is light calculations !

    Please tell me how to 'turn it off'
     
  18. Offline

    mythbusterma

    @Kentakis

    "Turning it off" is very difficult as it turns out.

    There's some code to do it in dhutils (if that's still being maintained) that works pretty well.

    EDIT: and you really shouldn't be working with the server internals (NMS) if you can't figure out how to spread the changes over multiple ticks.
     
  19. Offline

    Kentakis

    @mythbusterma
    I know how to do it in multiple ticks I exactly do it, but I said this is slow.

    Hmm this function was taken from dhutils

    Code:
    public void setBlockFast(Block b, int typeId, byte data) {
      net.minecraft.server.v1_7_R4.Chunk chunk = w.getChunkAt(b.getX() >> 4, b.getZ() >> 4);
      chunk.a( b.getX() & 0x0f, b.getY(), b.getZ() & 0x0f,net.minecraft.server.v1_7_R4.Block.getById(typeId), data);
      
      w.notify(b.getX(),b.getY(),b.getZ());
    }
    But it update light too
    //
    Hmm I think, I know, this is 'a' function fault
     
  20. Offline

    mythbusterma

    @Kentakis

    If you look in dhutils, there's a way to defer lighting calculations.
     
  21. Offline

    teej107

    Dealing with that many blocks, I still think part of the "lag" is due to the client, but I'm not denying that there isn't any on the server. Don't mess with NMS and attempt what I suggested.
     
  22. Offline

    Kentakis

    @teej107 @mythbusterma

    In the runTaskTimer I change 'blockFast' 100 per 6 ticks.
    Server is no laggy (I think) but now I dont know why, my minecraft LAG very well. (I mean that screen is freezed)


    So how to load these blocks like 'worldedit' do it
     
  23. Offline

    teej107

  24. Offline

    Kentakis

    @teej107
    Yes I do, I dont know how to load blocks without NMS and Light Calulations
     
  25. Offline

    mythbusterma

  26. Offline

    PatoTheBest

    I use this, its something
    Code:
    public boolean QuickChangeBlockAt(final World world, final int x, final int y, final int z, final int blockId, final int data) {
            net.minecraft.server.v1_7_R4.World w = ((CraftWorld) world).getHandle();
            Chunk chunk = w.getChunkAt(x >> 4, z >> 4);
            return a(chunk, x & 0x0f, y, z & 0x0f, net.minecraft.server.v1_7_R4.Block.getById(blockId), data);
        }
    
        private boolean a(Chunk that, int i, int j, int k, net.minecraft.server.v1_7_R4.Block block, int l) {
            int i1 = k << 4 | i;
    
            if (j >= that.b[i1] - 1) {
                that.b[i1] = -999;
            }
    
            int j1 = that.heightMap[i1];
            net.minecraft.server.v1_7_R4.Block block1 = that.getType(i, j, k);
            int k1 = that.getData(i, j, k);
    
            if (block1 == block && k1 == l) {
                return false;
            } else {
                boolean flag = false;
                ChunkSection chunksection = that.getSections()[j >> 4];
    
                if (chunksection == null) {
                    if (block == Blocks.AIR) { return false; }
    
                    chunksection = that.getSections()[j >> 4] = new ChunkSection(j >> 4 << 4, !that.world.worldProvider.g);
                    flag = j >= j1;
                }
    
                int l1 = that.locX * 16 + i;
                int i2 = that.locZ * 16 + k;
    
                if (!that.world.isStatic) {
                    block1.f(that.world, l1, j, i2, k1);
                }
    
                // CraftBukkit start - Delay removing containers until after they're
                // cleaned up
                if (!(block1 instanceof IContainer)) {
                    chunksection.setTypeId(i, j & 15, k, block);
                }
                // CraftBukkit end
    
                if (!that.world.isStatic) {
                    block1.remove(that.world, l1, j, i2, block1, k1);
                } else if (block1 instanceof IContainer && block1 != block) {
                    that.world.p(l1, j, i2);
                }
    
                // CraftBukkit start - Remove containers now after cleanup
                if (block1 instanceof IContainer) {
                    chunksection.setTypeId(i, j & 15, k, block);
                }
                // CraftBukkit end
    
                if (chunksection.getTypeId(i, j & 15, k) != block) {
                    return false;
                } else {
                    chunksection.setData(i, j & 15, k, l);
                    if (flag) {
                        that.initLighting();
                    }
                    TileEntity tileentity;
    
                    if (block1 instanceof IContainer) {
                        tileentity = that.e(i, j, k);
                        if (tileentity != null) {
                            tileentity.u();
                        }
                    }
    
                    // CraftBukkit - Don't place while processing the
                    // BlockPlaceEvent, unless it's a BlockContainer
                    if (!that.world.isStatic && (!that.world.captureBlockStates || (block instanceof BlockContainer))) {
                        block.onPlace(that.world, l1, j, i2);
                    }
    
                    if (block instanceof IContainer) {
                        // CraftBukkit start - Don't create tile entity if placement
                        // failed
                        if (that.getType(i, j, k) != block) { return false; }
                        // CraftBukkit end
    
                        tileentity = that.e(i, j, k);
                        if (tileentity == null) {
                            tileentity = ((IContainer) block).a(that.world, l);
                            that.world.setTileEntity(l1, j, i2, tileentity);
                        }
    
                        if (tileentity != null) {
                            tileentity.u();
                        }
                    }
    
                    that.n = true;
                    return true;
                }
            }
        }
     
Thread Status:
Not open for further replies.

Share This Page