Search code examples
javaperformancebukkit

"A single Server tick took 60,00 seconds (should be max 0,05)"


I wrote a generator for Islands in Minecraft. Each Island has to be at least 35 Blocks high. But the code I wrote seems to be so server intense that I get the following Error

---- Minecraft Crash Report ----
// There are four lights!

Time: 18.07.15 18:05
Description: Watching Server

java.lang.Error
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:187)
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:161)
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:131)
    at de.mineone.island.generator.Island.generateIsland(Island.java:114)
    at de.mineone.island.generator.Island.generate(Island.java:40)
    at de.mineone.island.generator.Island.<init>(Island.java:36)
    at de.mineone.island.main.Main$1.run(Main.java:80)
    at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:53)
    at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:349)
    at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:655)
    at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:284)
    at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:600)
    at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:508)
    at java.lang.Thread.run(Unknown Source)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- Head --
Stacktrace:
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:187)
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:161)
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:131)
    at de.mineone.island.generator.Island.generateIsland(Island.java:114)
    at de.mineone.island.generator.Island.generate(Island.java:40)
    at de.mineone.island.generator.Island.<init>(Island.java:36)
    at de.mineone.island.main.Main$1.run(Main.java:80)
    at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:53)
    at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:349)
    at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:655)
    at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:284)
    at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:600)

-- Thread Dump --
Details:
    Threads: "Server Watchdog" Id=39 RUNNABLE
    at sun.management.ThreadImpl.dumpThreads0(Native Method)
    at sun.management.ThreadImpl.dumpAllThreads(Unknown Source)
    at net.minecraft.server.v1_8_R1.ThreadWatchdog.run(SourceFile:43)
    at java.lang.Thread.run(Unknown Source)


"Netty Server IO #0" Id=21 RUNNABLE (in native)
    at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
    at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source)
    at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source)
    at sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
    -  locked io.netty.channel.nio.SelectedSelectionKeySet@51978c9e
    -  locked java.util.Collections$UnmodifiableSet@1c56ad43
    -  locked sun.nio.ch.WindowsSelectorImpl@5a968db1
    at sun.nio.ch.SelectorImpl.select(Unknown Source)
    at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:618)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:306)
    ...


"Thread-5" Id=19 RUNNABLE
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    -  locked java.io.BufferedOutputStream@52308ded
    at java.io.PrintStream.flush(Unknown Source)
    -  locked java.io.PrintStream@71b5ecc2
    at java.io.FilterOutputStream.flush(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
    at sun.nio.cs.StreamEncoder.flush(Unknown Source)
    -  locked java.io.OutputStreamWriter@5ecaeee0
    ...


"Server console handler" Id=18 RUNNABLE (in native)
    at org.fusesource.jansi.internal.Kernel32._getch(Native Method)
    at org.fusesource.jansi.internal.WindowsSupport.readByte(WindowsSupport.java:46)
    at org.bukkit.craftbukkit.libs.jline.WindowsTerminal.readByte(WindowsTerminal.java:184)
    at org.bukkit.craftbukkit.libs.jline.WindowsTerminal.access$000(WindowsTerminal.java:53)
    at org.bukkit.craftbukkit.libs.jline.WindowsTerminal$1.read(WindowsTerminal.java:151)
    at java.io.FilterInputStream.read(Unknown Source)
    at org.bukkit.craftbukkit.libs.jline.console.ConsoleReader$1.read(ConsoleReader.java:167)
    at org.bukkit.craftbukkit.libs.jline.internal.InputStreamReader.read(InputStreamReader.java:267)
    -  locked org.bukkit.craftbukkit.libs.jline.console.ConsoleReader$1@72e1a5a9
    ...


"DestroyJavaVM" Id=17 RUNNABLE


"Server thread" Id=15 RUNNABLE
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:187)
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:161)
    at org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:131)
    at de.mineone.island.generator.Island.generateIsland(Island.java:114)
    at de.mineone.island.generator.Island.generate(Island.java:40)
    at de.mineone.island.generator.Island.<init>(Island.java:36)
    at de.mineone.island.main.Main$1.run(Main.java:80)
    at org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:53)
    ...


"Server Infinisleeper" Id=16 TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at net.minecraft.server.v1_8_R1.ThreadSleepForever.run(SourceFile:64)


"Snooper Timer" Id=12 WAITING on java.util.TaskQueue@3c43352b
    at java.lang.Object.wait(Native Method)
    -  waiting on java.util.TaskQueue@3c43352b
    at java.lang.Object.wait(Object.java:503)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)


"Attach Listener" Id=6 RUNNABLE


"Signal Dispatcher" Id=5 RUNNABLE


"Finalizer" Id=3 WAITING on java.lang.ref.ReferenceQueue$Lock@6057b8f5
    at java.lang.Object.wait(Native Method)
    -  waiting on java.lang.ref.ReferenceQueue$Lock@6057b8f5
    at java.lang.ref.ReferenceQueue.remove(Unknown Source)
    at java.lang.ref.ReferenceQueue.remove(Unknown Source)
    at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)


"Reference Handler" Id=2 WAITING on java.lang.ref.Reference$Lock@1f300e3d
    at java.lang.Object.wait(Native Method)
    -  waiting on java.lang.ref.Reference$Lock@1f300e3d
    at java.lang.Object.wait(Object.java:503)
    at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)



Stacktrace:
    at net.minecraft.server.v1_8_R1.ThreadWatchdog.run(SourceFile:59)
    at java.lang.Thread.run(Unknown Source)

-- System Details --
Details:
    Minecraft Version: 1.8
    Operating System: Windows 7 (amd64) version 6.1
    Java Version: 1.7.0_65, Oracle Corporation
    Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
    Memory: 99006072 bytes (94 MB) / 241586176 bytes (230 MB) up to 1037959168 bytes (989 MB)
    JVM Flags: 2 total; -Xincgc -Xmx1G
    IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
    CraftBukkit Information: 
   Running: CraftBukkit version git-Bukkit-f498585 (MC: 1.8) (Implementing API version 1.8-R0.1-SNAPSHOT) true
   Plugins: { Island v0.1 de.mineone.island.main.Main [MinecraftTechnicLP, harry_potter4567],}
   Warnings: DEFAULT
   Threads: { WAITING Snooper Timer: [java.lang.Object.wait(Native Method), java.lang.Object.wait(Object.java:503), java.util.TimerThread.mainLoop(Unknown Source), java.util.TimerThread.run(Unknown Source)], WAITING Finalizer: [java.lang.Object.wait(Native Method), java.lang.ref.ReferenceQueue.remove(Unknown Source), java.lang.ref.ReferenceQueue.remove(Unknown Source), java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)], RUNNABLE Server thread: [org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:187), org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:161), org.bukkit.util.noise.OctaveGenerator.noise(OctaveGenerator.java:131), de.mineone.island.generator.Island.generateIsland(Island.java:114), de.mineone.island.generator.Island.generate(Island.java:40), de.mineone.island.generator.Island.<init>(Island.java:36), de.mineone.island.main.Main$1.run(Main.java:80), org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftTask.run(CraftTask.java:53), org.bukkit.craftbukkit.v1_8_R1.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:349), net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:655), net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:284), net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:600), net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:508), java.lang.Thread.run(Unknown Source)], RUNNABLE DestroyJavaVM: [], TIMED_WAITING Server Infinisleeper: [java.lang.Thread.sleep(Native Method), net.minecraft.server.v1_8_R1.ThreadSleepForever.run(SourceFile:64)], RUNNABLE Server Watchdog: [java.lang.Thread.dumpThreads(Native Method), java.lang.Thread.getAllStackTraces(Unknown Source), org.bukkit.craftbukkit.v1_8_R1.CraftCrashReport.call(CraftCrashReport.java:28), net.minecraft.server.v1_8_R1.CrashReportSystemDetails.a(SourceFile:78), net.minecraft.server.v1_8_R1.CrashReport.h(CrashReport.java:43), net.minecraft.server.v1_8_R1.CrashReport.<init>(CrashReport.java:32), net.minecraft.server.v1_8_R1.ThreadWatchdog.run(SourceFile:57), java.lang.Thread.run(Unknown Source)], RUNNABLE Netty Server IO #0: [sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method), sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source), sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source), sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source), sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source), sun.nio.ch.SelectorImpl.select(Unknown Source), io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:618), io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:306), io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116), java.lang.Thread.run(Unknown Source)], WAITING Reference Handler: [java.lang.Object.wait(Native Method), java.lang.Object.wait(Object.java:503), java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)], RUNNABLE Attach Listener: [], RUNNABLE Server console handler: [org.fusesource.jansi.internal.Kernel32._getch(Native Method), org.fusesource.jansi.internal.WindowsSupport.readByte(WindowsSupport.java:46), org.bukkit.craftbukkit.libs.jline.WindowsTerminal.readByte(WindowsTerminal.java:184), org.bukkit.craftbukkit.libs.jline.WindowsTerminal.access$000(WindowsTerminal.java:53), org.bukkit.craftbukkit.libs.jline.WindowsTerminal$1.read(WindowsTerminal.java:151), java.io.FilterInputStream.read(Unknown Source), org.bukkit.craftbukkit.libs.jline.console.ConsoleReader$1.read(ConsoleReader.java:167), org.bukkit.craftbukkit.libs.jline.internal.InputStreamReader.read(InputStreamReader.java:267), org.bukkit.craftbukkit.libs.jline.internal.InputStreamReader.read(InputStreamReader.java:204), org.bukkit.craftbukkit.libs.jline.console.ConsoleReader.readCharacter(ConsoleReader.java:995), org.bukkit.craftbukkit.libs.jline.console.ConsoleReader.readLine(ConsoleReader.java:1167), net.minecraft.server.v1_8_R1.ThreadCommandReader.run(ThreadCommandReader.java:33)], RUNNABLE Signal Dispatcher: [], WAITING Thread-5: [sun.misc.Unsafe.park(Native Method), java.util.concurrent.locks.LockSupport.park(Unknown Source), java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source), java.util.concurrent.LinkedBlockingQueue.take(Unknown Source), com.mojang.util.QueueLogAppender.getNextLogEvent(QueueLogAppender.java:77), org.bukkit.craftbukkit.v1_8_R1.util.TerminalConsoleWriterThread.run(TerminalConsoleWriterThread.java:25), java.lang.Thread.run(Unknown Source)],}
   Recent tasks from -29-1{}
    Profiler Position: N/A (disabled)
    Player Count: 0 / 20; []
    Is Modded: Definitely; Server brand changed to 'CraftBukkit'
    Type: Dedicated Server (map_server.txt)

The Islands are generated with the following class

package de.mineone.island.generator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Banner;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.util.noise.SimplexOctaveGenerator;

import de.mineone.island.main.Main;

public class Island {

    private static final int EDGE_BIAS = 12;
    private static final int HEIGHT = 50;

    private Location loc;
    private int xWidth;
    private int zWidth;
    private Banner flag;
    private DyeColor color;
    private ArrayList<Integer> illegalX = new ArrayList<Integer>();
    private ArrayList<Integer> illegalZ = new ArrayList<Integer>();

    public Island(Location loc, int xWidth, int zWidth, DyeColor color) {
        this.loc = loc;
        this.xWidth = xWidth;
        this.zWidth = zWidth;
        this.color = color;

        generate();
    }

    public void generate() {
        generateIsland();
        generateFlag();
        generateTrees();
    }

    private void generateIsland() {
        HashMap<Integer, Material> lvlMat = new HashMap<Integer, Material>();
        lvlMat.put(1, Material.SAND);
        lvlMat.put(2, Material.SAND);
        lvlMat.put(3, Material.SAND);
        lvlMat.put(4, Material.SAND);
        lvlMat.put(5, Material.SAND);
        lvlMat.put(6, Material.SAND);
        lvlMat.put(7, Material.SAND);
        lvlMat.put(8, Material.SAND);
        lvlMat.put(9, Material.SAND);
        lvlMat.put(10, Material.SAND);
        lvlMat.put(11, Material.SAND);
        lvlMat.put(12, Material.SAND);
        lvlMat.put(13, Material.SAND);
        lvlMat.put(14, Material.SAND);
        lvlMat.put(15, Material.SAND);
        lvlMat.put(16, Material.SAND);
        lvlMat.put(17, Material.SAND);
        lvlMat.put(18, Material.SAND);
        lvlMat.put(19, Material.SAND);
        lvlMat.put(20, Material.SAND);
        lvlMat.put(21, Material.SAND);

        lvlMat.put(22, Material.SAND);
        lvlMat.put(23, Material.SAND);
        lvlMat.put(24, Material.SAND);

        lvlMat.put(25, Material.DIRT);
        lvlMat.put(26, Material.DIRT);
        lvlMat.put(27, Material.DIRT);
        lvlMat.put(28, Material.DIRT);
        lvlMat.put(29, Material.DIRT);
        lvlMat.put(30, Material.DIRT);
        lvlMat.put(31, Material.DIRT);
        lvlMat.put(32, Material.DIRT);
        lvlMat.put(33, Material.DIRT);
        lvlMat.put(34, Material.DIRT);
        lvlMat.put(35, Material.DIRT);

        lvlMat.put(36, Material.STONE);
        lvlMat.put(37, Material.STONE);
        lvlMat.put(38, Material.STONE);
        lvlMat.put(39, Material.STONE);
        lvlMat.put(40, Material.STONE);
        lvlMat.put(41, Material.STONE);
        lvlMat.put(42, Material.STONE);
        lvlMat.put(43, Material.STONE);
        lvlMat.put(44, Material.STONE);
        lvlMat.put(45, Material.STONE);
        lvlMat.put(46, Material.STONE);
        lvlMat.put(47, Material.STONE);
        lvlMat.put(48, Material.STONE);
        lvlMat.put(49, Material.STONE);
        lvlMat.put(50, Material.STONE);
        lvlMat.put(51, Material.STONE);


        double[] rollingParticle = getRollingParticle();
        SimplexOctaveGenerator gen = new SimplexOctaveGenerator(new Random(), 8);
        gen.setScale(1 / 512.0D);

        ArrayList<XYZLocation> blocks = new ArrayList<XYZLocation>();
        int highestBlock = 0;

        while(highestBlock < 35) {
            blocks.clear();
            int hb = 0;
            for(int x = 0; x < xWidth; x++) {
                for(int z = 0; z < zWidth; z++) {
                    double noise = gen.noise(x, z, 0.5, 0.5) * HEIGHT * rollingParticle[x + z * xWidth];

                    for(int y = 1; y < noise + 1; y++) {
                        if(y > hb) hb = y;
                        if(y == ((int)noise) + 1) {
                            blocks.add(new XYZLocation(x, y, z, true));
                        } else {
                            blocks.add(new XYZLocation(x, y, z, false));
                        }
                    }

                }
            }
            highestBlock = hb;
        }

        for(XYZLocation xyz : blocks) {
            Material mat = lvlMat.get(xyz.getY());
            Location l = loc.add(xyz.getLocation(loc.getWorld()));

            loc.getWorld().getChunkAt(l).load();
            if(xyz.isSurface() && mat == Material.DIRT) {
                loc.getWorld().getBlockAt(l).setBiome(Biome.BEACH);
                loc.getWorld().getBlockAt(l).setType(Material.GRASS);
            } else {
                loc.getWorld().getBlockAt(l).setType(mat);
            }
        }

    }

    @SuppressWarnings("unused")
    private double[] getGradient() {
        double[] gradient = new double[xWidth * zWidth];

        int xMid = xWidth / 2;
        int zMid = zWidth / 2;
        double xStep = 0.4 / xMid;
        double zStep = 0.4 / zMid;
        for(int x = 0; x < xWidth; x++) {
            int xMultiplier = x > xMid ? xMid - x * -1 : x;
            for(int z = 0; z < zWidth; z++) {
                int zMultiplier = z > zMid ? zMid - z * -1 : z;
                gradient[x + z * xWidth] = xMultiplier * xStep + zMultiplier * zStep + 0.2;
            }
        }

        return gradient;
    }

    private double[] normalize(double[] array) {
        int highest = 0;
        int lowest = Integer.MAX_VALUE;

        for(int x = 0; x < xWidth; x++) {
            for(int z = 0; z < zWidth; z++) {
                int i = x + z * xWidth;
                if(array[i] < lowest) lowest = (int) array[i];
                if(array[i] > highest) highest = (int) array[i];
            }
        }

        for(int x = 0; x < xWidth; x++) {
            for(int z = 0; z < zWidth; z++) {
                int i = x + z * xWidth;
                double percent = (array[i] - lowest) / (highest - lowest);
                array[i] = percent;
            }
        }

        return array;
    }

    private ArrayList<BlockLocation> getNeighbourHood(int srcX, int srcZ) {
        ArrayList<BlockLocation> locs = new ArrayList<BlockLocation>();

        for(int x = -1; x <= 1; x++) {
            for(int z = -1; z <= 1; z++) {
                if(x + srcX >= 0 && x + srcX < xWidth && z + srcZ >= 0 && z + srcZ < zWidth) {
                    if(x != 0 || z != 0) {
                        locs.add(new BlockLocation(x + srcX, z + srcZ));
                    }
                }
            }
        }

        return locs;
    }

    private double[] getRollingParticle() {
        double[] rollingParticle = new double[xWidth * zWidth];

        for(int i = 0; i < 2000; i++) {

            int srcX = (int) (Math.random() * (xWidth - (EDGE_BIAS * 2)) + EDGE_BIAS);
            int srcZ = (int) (Math.random() * (zWidth - (EDGE_BIAS * 2)) + EDGE_BIAS);

            for(int length = 0; length < 50; length++) {

                srcX += Math.round(Math.random() * 2 - 1);
                srcZ += Math.round(Math.random() * 2 - 1);

                if(srcX < 1 || srcX > xWidth - 2 || srcZ < 1 || srcZ > zWidth - 2) break;

                for(BlockLocation loc : getNeighbourHood(srcX, srcZ)) {
                    if(rollingParticle[loc.getX() + loc.getZ() * xWidth] < rollingParticle[srcX + srcZ * xWidth]) {
                        srcX = loc.getX();
                        srcZ = loc.getZ();
                        break;
                    }
                }
                rollingParticle[srcX + srcZ * xWidth] += 1;

            }

        }
        return normalize(rollingParticle);
    }

    private void generateFlag() {
        Location highestLoc = null;
        int highest = 0;

        for(int x = 0; x < xWidth; x++) {
            for(int z = 0; z < xWidth; z++) {
                Location l = loc.clone().add(x, 0, z);
                l.setY(l.getWorld().getHighestBlockYAt(l));

                if(l.getBlockY() > highest) {
                    highest = l.getBlockY();
                    highestLoc = l;
                }
            }
        }

        loc.getWorld().getBlockAt(highestLoc.clone().add(0, 0, 0)).setType(Material.DARK_OAK_FENCE);
        loc.getWorld().getBlockAt(highestLoc.clone().add(0, 1, 0)).setType(Material.DARK_OAK_FENCE);

        Block block = loc.getWorld().getBlockAt(highestLoc.clone().add(0, 2, 0));
        block.setType(Material.STANDING_BANNER);
        Banner b = (Banner) block.getState();
        b.setBaseColor(color);
        b.update();
        if(!illegalX.contains(b.getLocation().getBlockX())) illegalX.add(b.getLocation().getBlockX());
        if(!illegalZ.contains(b.getLocation().getBlockZ())) illegalZ.add(b.getLocation().getBlockZ());
    }

    private void generateTrees() {
        for(int i = 0; i < Main.TREES; i++) {
            Location tree = null;
            while(tree == null) {
                Random rdm = new Random();
                Location l = new Location(loc.getWorld(), rdm.nextInt(xWidth), 0, rdm.nextInt(zWidth));
                l.setY(loc.getWorld().getHighestBlockYAt(l));
                if(!(l.getBlockY() < 25 || illegalX.contains(l.getX()) || illegalX.contains(l.getX() + 1) || illegalX.contains(l.getX() - 1) || illegalZ.contains(l.getZ()) || illegalZ.contains(l.getZ() + 1) || illegalZ.contains(l.getZ() - 1))) {
                    tree = l;
                }
            }
            generateRandomTree(loc.clone().add(tree));
        }
    }

    @SuppressWarnings("deprecation")
    private void generateRandomTree(Location l) {
        int blocks = new Random().nextInt(5) + 8;
        for(int b = 0; b <= blocks; b++) {
            loc.getWorld().getBlockAt(l).setType(Material.LOG);
            loc.getWorld().getBlockAt(l).setData((byte) 3);
            if(!illegalX.contains(l.getBlockX())) {
                illegalX.add(l.getBlockX());
            }
            if(!illegalZ.contains(l.getBlockZ())) {
                illegalZ.add(l.getBlockZ());
            }

            if(b == blocks) continue;

            Random rdm = new Random();
            switch(rdm.nextInt(19)) {
            case 0:
                l.add(1, 0, 0);
                break;
            case 1:
                l.add(-1, 0, 0);
                break;
            case 2:
                l.add(0, 0, 1);
                break;
            case 3:
                l.add(0, 0, -1);
                break;
            default:
                l.add(0, 1, 0);
                break;
            }
        }
        //loc.getWorld().getBlockAt(loc.clone().add(x, y, z)).setBiome(Biome.BEACH);

        ArrayList<Block> leaves = new ArrayList<Block>();

        for(int x = -4; x <= 4; x++) {
            if(x == -4 || x == 4) {
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, 0)));
            } else if(x == -3 || x == 3) {
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, 0)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, 3)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, -3)));
            } else if(x == -2 || x == 2) {
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, 0)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, 2)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, -2)));
            } else if(x == -1 || x == 1) {
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, 0)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, 1)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, -1)));
            } else if(x == 0) {
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, -4)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, -3)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, -2)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, -1)));

                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, 0)));

                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, 4)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, 3)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 2, 2)));
                leaves.add(loc.getWorld().getBlockAt(l.clone().add(x, 1, 1)));
            } 
        }

        for(Block b : leaves) {
            if(!illegalX.contains(b.getLocation().getBlockX())) {
                illegalX.add(b.getLocation().getBlockX());
            }
            if(!illegalZ.contains(b.getLocation().getBlockZ())) {
                illegalZ.add(b.getLocation().getBlockZ());
            }
            b.setBiome(Biome.BEACH);
            b.setType(Material.LEAVES);
            b.setData((byte) 3);
        }

    }

    public Banner getFlag() {
        return flag;
    }

}

The XYZLocation does only store the 3 Integers and one boolean and the BlockLocation 2 Integers. This is only to save as few instances of the world as possible and also Integers instead of doubles.

The Islands are generated before Players are able to join, so if there is a possibiltity to prevent the server from crahing, this would be extreamly helpful too.

I worked on this for days and wasnt able to figure out a resolution so thanks for any help in advance.


Solution

  • You made a infinity loop in your code, depending on the generated random, noise will stay below -1, causing the y for-loop to never execute, hence variable hb is never updated to any other value than 0. Using math.abs to make variable noise never below 0 isn't a good solution since there will be always a risk that for any coordinate the noise may hover between 0 and 35, causing the bug again.

    A solution to the bug would be changing the code to select a different spot in the fourth dimensional noise spectrum of the generator, and trying again with that spot to see if it yields better noise with heights of at least 35.

    An implementation of this would be the following:

        int attempt = 0;
    
        while(highestBlock < 35) {
            attempt++;
            blocks.clear();
            int hb = 0;
            for(int x = 0; x < xWidth; x++) {
                for(int z = 0; z < zWidth; z++) {
                    double noise = gen.noise(x, z, attempt*5, 0.5, 0.5) * HEIGHT * rollingParticle[x + z * xWidth];
                    double noisePlusOne = noise + 1;
                    for(int y = 1; y < noisePlusOne; y++) {
                        if(y > hb) hb = y;
                        if(y == ((int)noise)) {
                            blocks.add(new XYZLocation(x, y, z, true));
                        } else {
                            blocks.add(new XYZLocation(x, y, z, false));
                        }
                    }
    
                }
            }
            System.out.println("max:" + hb);
            highestBlock = hb;
        }
    

    Notice I added a system.out debug statement to print out the max blocks, you should see it changing when trying to solve a island height conflict, if its still taking to long, you may want to increase the third argument to gen.noise, for example use attempt*10 to make it shift faster through the noise spectrum. I recommend you play with the argument to see what gives the best result.