public static boolean SpawnCustomTrees(
      World world, Random rand, WorldConfig worldSettings, int x, int y, int z) {

    if (!worldSettings.HasCustomTrees) return false;

    Chunk chunk = world.getWorld().getChunkAt(x >> 4, z >> 4);

    BiomeBase localBiomeBase =
        world.getWorldChunkManager().getBiome(chunk.getX() * 16 + 16, chunk.getZ() * 16 + 16);

    boolean objectSpawned = false;
    int spawnattemps = 0;
    while (!objectSpawned && spawnattemps < worldSettings.objectSpawnRatio) {
      CustomObject SelectedObject =
          worldSettings.Objects.get(rand.nextInt(worldSettings.Objects.size()));

      spawnattemps++;

      if (SelectedObject.branch
          || !SelectedObject.canSpawnInBiome(localBiomeBase)
          || !SelectedObject.tree) continue;

      int randomRoll = rand.nextInt(100);

      if (randomRoll < SelectedObject.rarity) {
        if (CustomObjectGen.ObjectCanSpawn(world, x, y, z, SelectedObject))
          objectSpawned =
              GenerateCustomObject(world, rand, worldSettings, x, y, z, SelectedObject, true);
      }
    }
    return objectSpawned;
  }
  public static boolean SpawnCustomObjects(
      World world,
      Random rand,
      WorldConfig worldSettings,
      int chunk_x,
      int chunk_z,
      BiomeBase localBiomeBase) {

    if (worldSettings.Objects.size() == 0) return false;

    boolean objectSpawned = false;
    int spawnattemps = 0;
    while (!objectSpawned) {
      if (spawnattemps > worldSettings.objectSpawnRatio) return false;

      spawnattemps++;

      CustomObject SelectedObject =
          worldSettings.Objects.get(rand.nextInt(worldSettings.Objects.size()));

      if (SelectedObject.branch || !SelectedObject.canSpawnInBiome(localBiomeBase)) continue;

      int randomRoll = rand.nextInt(100);
      int ObjectRarity = SelectedObject.rarity;

      while (randomRoll < ObjectRarity) {
        int x = chunk_x + rand.nextInt(16);
        int z = chunk_z + rand.nextInt(16);
        int y = world.getHighestBlockYAt(x, z);
        ObjectRarity -= 100;

        if (!ObjectCanSpawn(world, x, y, z, SelectedObject)) continue;

        objectSpawned =
            GenerateCustomObject(world, rand, worldSettings, x, y, z, SelectedObject, false);
        // Checked Biome, Branch, Tree - soo try to generate.

        // here we spawn object and check group spawning

        if (objectSpawned && !SelectedObject.groupId.endsWith("")) {
          ArrayList<CustomObject> groupList =
              worldSettings.ObjectGroups.get(SelectedObject.groupId);
          if (groupList == null) return objectSpawned;

          int attempts = 3;
          if ((SelectedObject.groupFrequencyMax - SelectedObject.groupFrequencyMin) > 0)
            attempts =
                SelectedObject.groupFrequencyMin
                    + rand.nextInt(
                        SelectedObject.groupFrequencyMax - SelectedObject.groupFrequencyMin);

          while (attempts > 0) {
            attempts--;

            int objIndex = rand.nextInt(groupList.size());
            CustomObject ObjectFromGroup = groupList.get(objIndex);

            // duno about this check, but maybe it is correct
            if (ObjectFromGroup.branch || !ObjectFromGroup.canSpawnInBiome(localBiomeBase))
              continue;

            x =
                x
                    + rand.nextInt(
                        SelectedObject.groupSeperationMax - SelectedObject.groupSeperationMin)
                    + SelectedObject.groupSeperationMin;
            z =
                z
                    + rand.nextInt(
                        SelectedObject.groupSeperationMax - SelectedObject.groupSeperationMin)
                    + SelectedObject.groupSeperationMin;
            int _y = world.getHighestBlockYAt(x, z);
            if ((y - _y) > 10 || (_y - y) > 10) continue;

            if (!ObjectCanSpawn(world, x, y, z, ObjectFromGroup)) continue;
            GenerateCustomObject(world, rand, worldSettings, x, _y, z, ObjectFromGroup, false);
          }
        }
      }
    }
    return objectSpawned;
  }