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;
  }
  @SuppressWarnings("rawtypes")
  public static MinecartMember getAt(World world, ChunkCoordinates coord, boolean checkmoving) {
    net.minecraft.server.Chunk chunk = WorldUtil.getChunk(world, coord.x >> 4, coord.z >> 4);
    if (chunk != null) {
      MinecartMember mm;
      MinecartMember result = null;
      for (List list : chunk.entitySlices) {
        for (Object e : list) {
          if (e instanceof MinecartMember) {
            mm = (MinecartMember) e;
            if (mm.getBlockX() != coord.x) continue;
            if (mm.getBlockY() != coord.y) continue;
            if (mm.getBlockZ() != coord.z) continue;
            result = mm;
            if (result.isHeadingTo(coord)) return result;
          }
        }
      }
      if (result == null && checkmoving) {
        Block b = world.getWorld().getBlockAt(coord.x, coord.y, coord.z);
        int id = b.getTypeId();

        // get the two connected rails to check
        if (BlockUtil.isRails(id)) {
          BlockFace[] possible = FaceUtil.getFaces(BlockUtil.getRails(b).getDirection());
          MinecartMember mm1 = getAt(Util.getRailsBlock(b.getRelative(possible[0])), false);
          MinecartMember mm2 = getAt(Util.getRailsBlock(b.getRelative(possible[1])), false);
          if (mm1 != null && mm2 != null && mm1.group == mm2.group) {
            Location loc = b.getLocation();
            return mm1.distance(loc) < mm2.distance(loc) ? mm1 : mm2;
          } else if (isHeadingTo(mm1, coord)) {
            return mm1;
          } else if (isHeadingTo(mm2, coord)) {
            return mm2;
          } else {
            return null;
          }
        } else if (Util.isPressurePlate(id)) {
          // check all directions
          MinecartMember mm1 = getAt(Util.getRailsBlock(b.getRelative(BlockFace.NORTH)), false);
          MinecartMember mm2 = getAt(Util.getRailsBlock(b.getRelative(BlockFace.SOUTH)), false);
          MinecartMember mm3 = getAt(Util.getRailsBlock(b.getRelative(BlockFace.EAST)), false);
          MinecartMember mm4 = getAt(Util.getRailsBlock(b.getRelative(BlockFace.WEST)), false);
          if (mm1 != null && mm2 != null && mm1.group == mm2.group) {
            Location loc = b.getLocation();
            return mm1.distance(loc) < mm2.distance(loc) ? mm1 : mm2;
          } else if (mm3 != null && mm4 != null && mm3.group == mm4.group) {
            Location loc = b.getLocation();
            return mm3.distance(loc) < mm4.distance(loc) ? mm3 : mm4;
          } else if (isHeadingTo(mm1, coord)) {
            return mm1;
          } else if (isHeadingTo(mm2, coord)) {
            return mm2;
          } else if (isHeadingTo(mm3, coord)) {
            return mm3;
          } else if (isHeadingTo(mm4, coord)) {
            return mm4;
          } else {
            return null;
          }
        }
      }
      return result;
    }
    return null;
  }