Posted March 23, 20187 yr Hello! I made a custom dimension and i got strange problem. Whenever I add any structure to generate in my dimension minecraft gets strange server lags. I tried everything. Changing way of registering biome,dimension, moving custom structure from custom biome decorator to Generator Handler that implements IWorldGenerator and then registering it in main class. Nothing helped. These server lags lasts for about 1-2 minutes, and then everything is just fine. During the lag, I cannot break blocks, entites are lagged, etc. When I do not generate the structure, my dimension isn't laggy. My dimension is multi biome and the bug occurs no matter which forge version I use. I am working on minecraft 1.12. I can post the whole code on github if someone knows what can cause these lags. What can be wrong? Generators are copied from vanilla (changed only blocks). Spoiler @Mod.EventHandler public void preInit(FMLPreInitializationEvent event) { KCore.instance.dimRegistry(); { public static final int DIMENSION_ID = DimensionManager.getNextFreeDimId(); public static final DimensionType Mystic_DIMENSION = DimensionType.register("MYSTIC", "_mystic", DIMENSION_ID, WorldProviderMystic.class, false); public static void dimRegistry() { DimensionManager.registerDimension(DIMENSION_ID, KCore.Mystic_DIMENSION); } public void init(FMLInitializationEvent e) { GameRegistry.registerWorldGenerator(new WorldGeneratorHandler(), 10); } @Override public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) { int X = (chunkX*16)+8+random.nextInt(8)-random.nextInt(8); int Z = (chunkZ*16)+8+random.nextInt(8)-random.nextInt(8); int Y=0; BlockPos pos = new BlockPos(X,Y,Z); Biome actualBiome = world.getBiomeForCoordsBody(pos); //FOREST if(actualBiome==KCore.MysticForest) { for(int j=0;j<this.treesPerChunkForest;j++){ X = (chunkX*16)+8+random.nextInt(8)-random.nextInt(8); Z = (chunkZ*16)+8+random.nextInt(8)-random.nextInt(8); BlockPos tmp = new BlockPos(X,0,Z); int TOP = world.getHeight(tmp).getY(); BlockPos blockposnew = new BlockPos(X,TOP,Z); this.getRandomTreeFeatureForest(random).generate(world, random, blockposnew); } for (int i3 = 0; i3 < this.grassPerChunkForest; ++i3) { X = (chunkX*16)+8+random.nextInt(8)-random.nextInt(8); Z = (chunkZ*16)+8+random.nextInt(8)-random.nextInt(8); BlockPos tmp = new BlockPos(X,0,Z); int TOP = world.getHeight(tmp).getY()+1; BlockPos blockposnew = new BlockPos(X,TOP,Z); this.getRandomWorldGenForGrassForest(random).generate(world, random, blockposnew); } } } @SubscribeEvent public static void registerBiomes(final RegistryEvent.Register<Biome> event) { final IForgeRegistry<Biome> registry = event.getRegistry(); final Biome[] biomes = { KCore.MysticForest, KCore.MysticPlains, KCore.MysticDesert, KCore.MysticSwamps }; registry.registerAll(biomes); BiomeDictionary.addTypes(KCore.instance.MysticForest, BiomeDictionary.Type.FOREST,BiomeDictionary.Type.DENSE); BiomeDictionary.addTypes(KCore.instance.MysticPlains, BiomeDictionary.Type.PLAINS,BiomeDictionary.Type.DENSE); BiomeDictionary.addTypes(KCore.instance.MysticDesert, BiomeDictionary.Type.PLAINS,BiomeDictionary.Type.DEAD,BiomeDictionary.Type.HOT); BiomeDictionary.addTypes(KCore.instance.MysticSwamps, BiomeDictionary.Type.DRY); } Spoiler public class WorldGenBasicMysticTree extends WorldGenAbstractBasicMysticTree { /** The minimum height of a generated tree. */ private final int minTreeHeight; /** True if this tree should grow Vines. */ private final boolean vinesGrow; public WorldGenBasicMysticTree(boolean p_i2027_1_) { this(p_i2027_1_, 4, false); } public WorldGenBasicMysticTree(boolean notify, int minTreeHeightIn, boolean growVines) { super(notify); this.minTreeHeight = minTreeHeightIn; this.vinesGrow = growVines; } public boolean generate(World worldIn, Random rand, BlockPos position) { int i = rand.nextInt(3) + this.minTreeHeight; boolean flag = true; if (position.getY() >= 1 && position.getY() + i + 1 <= worldIn.getHeight()) { for (int j = position.getY(); j <= position.getY() + 1 + i; ++j) { int k = 1; if (j == position.getY()) { k = 0; } if (j >= position.getY() + 1 + i - 2) { k = 2; } BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); for (int l = position.getX() - k; l <= position.getX() + k && flag; ++l) { for (int i1 = position.getZ() - k; i1 <= position.getZ() + k && flag; ++i1) { if (j >= 0 && j < worldIn.getHeight()) { if (!this.isReplaceable(worldIn,blockpos$mutableblockpos.setPos(l, j, i1))) { flag = false; } } else { flag = false; } } } } if (!flag) { return false; } else { IBlockState state = worldIn.getBlockState(position.down()); if ((worldIn.getBlockState(position.down()) == KCore.CorruptedDirt.getDefaultState() || worldIn.getBlockState(position)==KCore.CorruptedDirt.getDefaultState() || state.getBlock() == KCore.CorruptedGrass)) { for (int i3 = position.getY() - 3 + i; i3 <= position.getY() + i; ++i3) { int i4 = i3 - (position.getY() + i); int j1 = 1 - i4 / 2; for (int k1 = position.getX() - j1; k1 <= position.getX() + j1; ++k1) { int l1 = k1 - position.getX(); for (int i2 = position.getZ() - j1; i2 <= position.getZ() + j1; ++i2) { int j2 = i2 - position.getZ(); if (Math.abs(l1) != j1 || Math.abs(j2) != j1 || rand.nextInt(2) != 0 && i4 != 0) { BlockPos blockpos = new BlockPos(k1, i3, i2); state = worldIn.getBlockState(blockpos); if (state.getBlock().isAir(state, worldIn, blockpos) || state.getBlock().isLeaves(state, worldIn, blockpos) || state.getMaterial() == Material.VINE) { this.setBlockAndNotifyAdequately(worldIn, blockpos, KCore.MysticLeaves.getDefaultState()); } } } } } for (int j3 = 0; j3 < i; ++j3) { BlockPos upN = position.up(j3); state = worldIn.getBlockState(upN); if (state.getBlock().isAir(state, worldIn, upN) || state.getBlock().isLeaves(state, worldIn, upN) || state.getMaterial() == Material.VINE) { this.setBlockAndNotifyAdequately(worldIn, position.up(j3), KCore.MysticLog.getDefaultState()); if (this.vinesGrow && j3 > 0) { if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(-1, j3, 0))) { this.addVine(worldIn, position.add(-1, j3, 0), BlockVine.EAST); } if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(1, j3, 0))) { this.addVine(worldIn, position.add(1, j3, 0), BlockVine.WEST); } if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(0, j3, -1))) { this.addVine(worldIn, position.add(0, j3, -1), BlockVine.SOUTH); } if (rand.nextInt(3) > 0 && worldIn.isAirBlock(position.add(0, j3, 1))) { this.addVine(worldIn, position.add(0, j3, 1), BlockVine.NORTH); } } } } if (this.vinesGrow) { for (int k3 = position.getY() - 3 + i; k3 <= position.getY() + i; ++k3) { int j4 = k3 - (position.getY() + i); int k4 = 2 - j4 / 2; BlockPos.MutableBlockPos blockpos$mutableblockpos1 = new BlockPos.MutableBlockPos(); for (int l4 = position.getX() - k4; l4 <= position.getX() + k4; ++l4) { for (int i5 = position.getZ() - k4; i5 <= position.getZ() + k4; ++i5) { blockpos$mutableblockpos1.setPos(l4, k3, i5); state = worldIn.getBlockState(blockpos$mutableblockpos1); if (state.getBlock().isLeaves(state, worldIn, blockpos$mutableblockpos1)) { BlockPos blockpos2 = blockpos$mutableblockpos1.west(); BlockPos blockpos3 = blockpos$mutableblockpos1.east(); BlockPos blockpos4 = blockpos$mutableblockpos1.north(); BlockPos blockpos1 = blockpos$mutableblockpos1.south(); if (rand.nextInt(4) == 0 && worldIn.isAirBlock(blockpos2)) { this.addHangingVine(worldIn, blockpos2, BlockVine.EAST); } if (rand.nextInt(4) == 0 && worldIn.isAirBlock(blockpos3)) { this.addHangingVine(worldIn, blockpos3, BlockVine.WEST); } if (rand.nextInt(4) == 0 && worldIn.isAirBlock(blockpos4)) { this.addHangingVine(worldIn, blockpos4, BlockVine.SOUTH); } if (rand.nextInt(4) == 0 && worldIn.isAirBlock(blockpos1)) { this.addHangingVine(worldIn, blockpos1, BlockVine.NORTH); } } } } } if (rand.nextInt(5) == 0 && i > 5) { for (int l3 = 0; l3 < 2; ++l3) { for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL) { if (rand.nextInt(4 - l3) == 0) { EnumFacing enumfacing1 = enumfacing.getOpposite(); this.placeCocoa(worldIn, rand.nextInt(3), position.add(enumfacing1.getFrontOffsetX(), i - 5 + l3, enumfacing1.getFrontOffsetZ()), enumfacing); } } } } } return true; } else { return false; } } } else { return false; } } private void placeCocoa(World worldIn, int p_181652_2_, BlockPos pos, EnumFacing side) { this.setBlockAndNotifyAdequately(worldIn, pos, Blocks.COCOA.getDefaultState().withProperty(BlockCocoa.AGE, Integer.valueOf(p_181652_2_)).withProperty(BlockCocoa.FACING, side)); } private void addVine(World worldIn, BlockPos pos, PropertyBool prop) { this.setBlockAndNotifyAdequately(worldIn, pos, Blocks.VINE.getDefaultState().withProperty(prop, Boolean.valueOf(true))); } private void addHangingVine(World worldIn, BlockPos pos, PropertyBool prop) { this.addVine(worldIn, pos, prop); int i = 4; for (BlockPos blockpos = pos.down(); worldIn.isAirBlock(blockpos) && i > 0; --i) { this.addVine(worldIn, blockpos, prop); blockpos = blockpos.down(); } } } public class WorldGenMiniTallGrass extends WorldGenerator { private BlockMysticBush grassToGen; public WorldGenMiniTallGrass(BlockMysticBush block) { grassToGen=block; } public boolean generate(World worldIn, Random rand, BlockPos position) { for (IBlockState iblockstate = worldIn.getBlockState(position); (iblockstate.getBlock().isAir(iblockstate, worldIn, position) || iblockstate.getBlock().isLeaves(iblockstate, worldIn, position)) && position.getY() > 0; iblockstate = worldIn.getBlockState(position)) { position = position.down(); } for (int i = 0; i < 64; ++i) { BlockPos blockpos = new BlockPos(position.getX()+rand.nextInt(6) - rand.nextInt(6), position.getY()+rand.nextInt(4) - rand.nextInt(4), position.getZ()+rand.nextInt(6) - rand.nextInt(6)); if (worldIn.isAirBlock(blockpos) && grassToGen.canBlockStay(worldIn, blockpos, grassToGen.getDefaultState())) { worldIn.setBlockState(blockpos, this.grassToGen.getDefaultState(), 2); } } return true; } } Edited March 26, 20187 yr by Krevik Solved
March 24, 20187 yr You might be causing "cascading" during generation. This is where during the generation of a chunk you place a block (or call a function such as looking at neighbor blocks) that causes adjacent chunks to have to load and generate. Learn more about it here: Check out my tutorials here: http://jabelarminecraft.blogspot.com/
March 24, 20187 yr Author 50 minutes ago, jabelar said: You might be causing "cascading" during generation. This is where during the generation of a chunk you place a block (or call a function such as looking at neighbor blocks) that causes adjacent chunks to have to load and generate. Learn more about it here: I actually knew about this. Lags occure even if there's no word about cascading in console
March 24, 20187 yr Well, when it is lagging there is something happening that is taking the computer's processing time. There are really three common categories of lag that modders can create: 1) cascading as discussed 2) inefficient loops. Like if you're searching an area for something over and over again. 3) improper use of wait loops or other code that halts continued execution of the thread. Are you making custom trees? What is your full code for generation? Anyway, you just need to observe what is taking the time. You can do this by either setting breakpoints and using debug mode in Eclipse to figure out what is executing or you can add judicious console or logger print statements to trace the execution. By looking at the timestamps you can figure out what is taking the time and narrow it down. Like if you put a print statement at the beginning and end of your methods you can see how long each is taking, or maybe see that they are being called much more times than you expect. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
March 24, 20187 yr Author 11 minutes ago, jabelar said: Well, when it is lagging there is something happening that is taking the computer's processing time. There are really three common categories of lag that modders can create: 1) cascading as discussed 2) inefficient loops. Like if you're searching an area for something over and over again. 3) improper use of wait loops or other code that halts continued execution of the thread. Are you making custom trees? What is your full code for generation? Anyway, you just need to observe what is taking the time. You can do this by either setting breakpoints and using debug mode in Eclipse to figure out what is executing or you can add judicious console or logger print statements to trace the execution. By looking at the timestamps you can figure out what is taking the time and narrow it down. Like if you put a print statement at the beginning and end of your methods you can see how long each is taking, or maybe see that they are being called much more times than you expect. Added code. Actually the problem is I tried a lot of structures e.g. some small constant structures like mushroom from blocks, and any of them cause these lags, even if (as I said) there is no word about cascading in console. Yea I am making custom trees but disabling them from generation doesn't help Thanks will be trying with these print statements.
March 25, 20187 yr Do any of your blocks contain TileEntities? Do any of your blocks do anything when placed? and as Jabelar stated, you should try to see where everything is bottle-necking by comparing the before & after time of your methods/loops' executions. Oh, and use bit-shifting instead of multiplying/dividing by 16. By habit you'll likely (in the future) divide by 16 to get chunk-coordinate from a block coordinate. This will be incorrect for negative values, due to how integers are rounded down (-15/16 = -0.9375). chunkX << 4 = blockX, blockX >> 4 = chunkX Edited March 25, 20187 yr by Matryoshika Also previously known as eAndPi. "Pi, is there a station coming up where we can board your train of thought?" -Kronnn Published Mods: Underworld Handy links: Vic_'s Forge events Own WIP Tutorials.
March 25, 20187 yr Author 2 hours ago, Matryoshika said: Do any of your blocks contain TileEntities? Do any of your blocks do anything when placed? and as Jabelar stated, you should try to see where everything is bottle-necking by comparing the before & after time of your methods/loops' executions. Oh, and use bit-shifting instead of multiplying/dividing by 16. By habit you'll likely (in the future) divide by 16 to get chunk-coordinate from a block coordinate. This will be incorrect for negative values, due to how integers are rounded down (-15/16 = 0.9375). chunkX << 4 = blockX, blockX >> 4 = chunkX Yes some of my blocks do something and they"re "ticking" but even if they"re disabled from generation lags occure. Also these blocks start ticking after these lags end. Yes I have some tileEntities but they"re not generated, they"re available only from crafting table. Thanks will remember about shifting!
March 25, 20187 yr Author Checked with these print Statements and it seems that structures are not causing these lags. Every structure is generated very fast and finished also. Lags occure even if no structure is actually being generated. So It seems that generators are correct, but there's problem with something "higher". Edited March 25, 20187 yr by Krevik Forgot about sth
March 26, 20187 yr Author Found a solution. I was just using setBlockState method instead of setBlockAndNotifyAdequately Even if no generate method was called there were lags (Idk why) but now the lags are gone Edited March 26, 20187 yr by Krevik forgot about State
March 26, 20187 yr Cool. I think the big learning is having the skills to track down these things yourself. As long as you can observe the execution of a program you can always debug it. Check out my tutorials here: http://jabelarminecraft.blogspot.com/
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.