Repackage utils

This commit is contained in:
Daniel Mills
2021-07-16 02:11:37 -04:00
parent b9b30f9f53
commit da53a7d469
471 changed files with 1043 additions and 601 deletions

View File

@@ -0,0 +1,42 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.util.plugin.CancellableTask;
public abstract class AR implements Runnable, CancellableTask {
private int id = 0;
public AR() {
this(0);
}
public AR(int interval) {
id = J.ar(this, interval);
}
@Override
public void cancel() {
J.car(id);
}
public int getId() {
return id;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
/**
* Callback for async workers
*
* @param <T> the type of object to be returned in the runnable
* @author cyberpwn
*/
@FunctionalInterface
public interface Callback<T> {
/**
* Called when the callback calls back...
*
* @param t the object to be called back
*/
void run(T t);
}

View File

@@ -0,0 +1,23 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public interface CallbackCV<T> {
void run(T t);
}

View File

@@ -0,0 +1,50 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public class ChronoLatch {
private final long interval;
private long since;
public ChronoLatch(long interval, boolean openedAtStart) {
this.interval = interval;
since = System.currentTimeMillis() - (openedAtStart ? interval * 2 : 0);
}
public ChronoLatch(long interval) {
this(interval, true);
}
public void flipDown() {
since = System.currentTimeMillis();
}
public boolean couldFlip() {
return System.currentTimeMillis() - since > interval;
}
public boolean flip() {
if (System.currentTimeMillis() - since > interval) {
since = System.currentTimeMillis();
return true;
}
return false;
}
}

View File

@@ -0,0 +1,73 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.util.scheduling.Callback;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.Contained;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class Chunker<T> {
private ExecutorService executor;
private int threads;
private int workload;
private final KList<T> q;
public Chunker(KList<T> q) {
this.q = q;
}
public Chunker<T> threads(int threads) {
this.threads = threads;
return this;
}
public Chunker<T> workload(int workload) {
this.workload = workload;
return this;
}
public void execute(Consumer<T> consumer, Callback<Double> progress, int progressInterval) {
ChronoLatch cl = new ChronoLatch(progressInterval);
Contained<Integer> consumed = new Contained<>(0);
executor = Executors.newFixedThreadPool(threads);
int length = q.size();
int remaining = length;
while (remaining > 0) {
int at = remaining;
remaining -= (Math.min(remaining, workload));
int to = remaining;
executor.submit(() ->
{
J.dofor(at, (i) -> i >= to, -1, (i) -> J.attempt(() -> consumer.accept(q.get(i))));
consumed.mod((c) -> c += workload);
J.doif(() -> progress != null && cl.flip(), () -> progress.run((double) consumed.get() / (double) length));
});
}
executor.shutdown();
J.attempt(() -> executor.awaitTermination(100, TimeUnit.HOURS));
}
}

View File

@@ -0,0 +1,45 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import java.util.function.Function;
public class Contained<T> {
private T t;
public Contained(T t) {
set(t);
}
public Contained() {
this(null);
}
public void mod(Function<T, T> x) {
set(x.apply(t));
}
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}

View File

@@ -0,0 +1,114 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.function.NastyRunnable;
import com.volmit.iris.util.scheduling.J;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
import java.util.concurrent.ForkJoinWorkerThread;
public class GroupedExecutor {
private int xc;
private final ExecutorService service;
private final KMap<String, Integer> mirror;
public GroupedExecutor(int threadLimit, int priority, String name) {
xc = 1;
mirror = new KMap<>();
if (threadLimit == 1) {
service = Executors.newSingleThreadExecutor((r) ->
{
Thread t = new Thread(r);
t.setName(name);
t.setPriority(priority);
return t;
});
} else if (threadLimit > 1) {
final ForkJoinWorkerThreadFactory factory = pool -> {
final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
worker.setName(name + " " + xc++);
worker.setPriority(priority);
return worker;
};
service = new ForkJoinPool(threadLimit, factory, null, false);
} else {
service = Executors.newCachedThreadPool((r) ->
{
Thread t = new Thread(r);
t.setName(name + " " + xc++);
t.setPriority(priority);
return t;
});
}
}
public void waitFor(String g) {
if (g == null) {
return;
}
if (!mirror.containsKey(g)) {
return;
}
while (true) {
if (mirror.get(g) == 0) {
break;
}
}
}
public void queue(String q, NastyRunnable r) {
mirror.compute(q, (k, v) -> k == null || v == null ? 1 : v + 1);
service.execute(() ->
{
try {
r.run();
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
mirror.compute(q, (k, v) -> v - 1);
});
}
public void close() {
J.a(() ->
{
J.sleep(100);
service.shutdown();
});
}
public void closeNow() {
service.shutdown();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
import lombok.Data;
import java.util.concurrent.locks.ReentrantLock;
@Data
public class IrisLock {
private transient final ReentrantLock lock;
private transient final String name;
private transient boolean disabled = false;
public IrisLock(String name) {
this.name = name;
lock = new ReentrantLock(false);
}
public void lock() {
if (disabled) {
return;
}
lock.lock();
}
public void unlock() {
if (disabled) {
return;
}
try {
lock.unlock();
} catch (Throwable e) {
Iris.reportError(e);
}
}
}

View File

@@ -0,0 +1,326 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
import com.volmit.iris.util.function.NastyFunction;
import com.volmit.iris.util.function.NastyFuture;
import com.volmit.iris.util.function.NastyRunnable;
import com.volmit.iris.util.scheduling.AR;
import com.volmit.iris.util.scheduling.SR;
import org.bukkit.Bukkit;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@SuppressWarnings("ALL")
public class J {
private static int tid = 0;
private static final ExecutorService e = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
tid++;
Thread t = new Thread(r);
t.setName("Iris Actuator " + tid);
t.setPriority(8);
t.setUncaughtExceptionHandler((et, e) ->
{
Iris.info("Exception encountered in " + et.getName());
e.printStackTrace();
});
return t;
}
});
public static void dofor(int a, Function<Integer, Boolean> c, int ch, Consumer<Integer> d) {
for (int i = a; c.apply(i); i += ch) {
c.apply(i);
}
}
public static boolean doif(Supplier<Boolean> c, Runnable g) {
try {
if (c.get()) {
g.run();
return true;
}
} catch (NullPointerException e) {Iris.reportError(e);
// TODO: Fix this because this is just a suppression for an NPE on g
return false;
}
return false;
}
public static void arun(Runnable a) {
e.submit(() -> {
try {
a.run();
} catch (Throwable e) {Iris.reportError(e);
System.out.println("Failed to run async task");
e.printStackTrace();
}
});
}
public static void a(Runnable a) {
e.submit(() -> {
try {
a.run();
} catch (Throwable e) {Iris.reportError(e);
System.out.println("Failed to run async task");
e.printStackTrace();
}
});
}
public static <T> Future<T> a(Callable<T> a) {
return e.submit(a);
}
public static void attemptAsync(NastyRunnable r) {
J.a(() -> J.attempt(r));
}
public static <R> R attemptResult(NastyFuture<R> r, R onError) {
try {
return r.run();
} catch (Throwable e) {Iris.reportError(e);
}
return onError;
}
public static <T, R> R attemptFunction(NastyFunction<T, R> r, T param, R onError) {
try {
return r.run(param);
} catch (Throwable e) {Iris.reportError(e);
}
return onError;
}
public static boolean sleep(long ms) {
return J.attempt(() -> Thread.sleep(ms));
}
public static boolean attempt(NastyRunnable r) {
return attemptCatch(r) == null;
}
public static Throwable attemptCatch(NastyRunnable r) {
try {
r.run();
} catch (Throwable e) {Iris.reportError(e);
return e;
}
return null;
}
public static <T> T attempt(Supplier<T> t, T i) {
try {
return t.get();
} catch (Throwable e) {Iris.reportError(e);
return i;
}
}
private static KList<Runnable> afterStartup = new KList<>();
private static KList<Runnable> afterStartupAsync = new KList<>();
private static boolean started = false;
/**
* Dont call this unless you know what you are doing!
*/
public static void executeAfterStartupQueue() {
if (started) {
return;
}
started = true;
for (Runnable r : afterStartup) {
s(r);
}
for (Runnable r : afterStartupAsync) {
a(r);
}
afterStartup = null;
afterStartupAsync = null;
}
/**
* Schedule a sync task to be run right after startup. If the server has already
* started ticking, it will simply run it in a sync task.
* <p>
* If you dont know if you should queue this or not, do so, it's pretty
* forgiving.
*
* @param r the runnable
*/
public static void ass(Runnable r) {
if (started) {
s(r);
} else {
afterStartup.add(r);
}
}
/**
* Schedule an async task to be run right after startup. If the server has
* already started ticking, it will simply run it in an async task.
* <p>
* If you dont know if you should queue this or not, do so, it's pretty
* forgiving.
*
* @param r the runnable
*/
public static void asa(Runnable r) {
if (started) {
a(r);
} else {
afterStartupAsync.add(r);
}
}
/**
* Queue a sync task
*
* @param r the runnable
*/
public static void s(Runnable r) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, r);
}
/**
* Queue a sync task
*
* @param r the runnable
* @param delay the delay to wait in ticks before running
*/
public static void s(Runnable r, int delay) {
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, r, delay);
}
/**
* Cancel a sync repeating task
*
* @param id the task id
*/
public static void csr(int id) {
Bukkit.getScheduler().cancelTask(id);
}
/**
* Start a sync repeating task
*
* @param r the runnable
* @param interval the interval
* @return the task id
*/
public static int sr(Runnable r, int interval) {
return Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, r, 0, interval);
}
/**
* Start a sync repeating task for a limited amount of ticks
*
* @param r the runnable
* @param interval the interval in ticks
* @param intervals the maximum amount of intervals to run
*/
public static void sr(Runnable r, int interval, int intervals) {
FinalInteger fi = new FinalInteger(0);
new SR() {
@Override
public void run() {
fi.add(1);
r.run();
if (fi.get() >= intervals) {
cancel();
}
}
};
}
/**
* Call an async task dealyed
*
* @param r the runnable
* @param delay the delay to wait before running
*/
@SuppressWarnings("deprecation")
public static void a(Runnable r, int delay) {
Bukkit.getScheduler().scheduleAsyncDelayedTask(Iris.instance, r, delay);
}
/**
* Cancel an async repeat task
*
* @param id the id
*/
public static void car(int id) {
Bukkit.getScheduler().cancelTask(id);
}
/**
* Start an async repeat task
*
* @param r the runnable
* @param interval the interval in ticks
* @return the task id
*/
@SuppressWarnings("deprecation")
public static int ar(Runnable r, int interval) {
return Bukkit.getScheduler().scheduleAsyncRepeatingTask(Iris.instance, r, 0, interval);
}
/**
* Start an async repeating task for a limited time
*
* @param r the runnable
* @param interval the interval
* @param intervals the intervals to run
*/
public static void ar(Runnable r, int interval, int intervals) {
FinalInteger fi = new FinalInteger(0);
new AR() {
@Override
public void run() {
fi.add(1);
r.run();
if (fi.get() >= intervals) {
cancel();
}
}
};
}
}

View File

@@ -0,0 +1,47 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
public abstract class Looper extends Thread {
@SuppressWarnings("BusyWait")
public void run() {
while (!interrupted()) {
try {
long m = loop();
if (m < 0) {
break;
}
//noinspection BusyWait
Thread.sleep(m);
} catch (InterruptedException e) {Iris.reportError(e);
break;
} catch (Throwable e) {Iris.reportError(e);
e.printStackTrace();
}
}
Iris.info("Thread " + getName() + " Shutdown.");
}
protected abstract long loop();
}

View File

@@ -0,0 +1,62 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public class O<T> implements Observable<T> {
private T t = null;
private KList<Observer<T>> observers;
@Override
public T get() {
return t;
}
@Override
public O<T> set(T t) {
this.t = t;
if (observers != null && observers.hasElements()) {
observers.forEach((o) -> o.onChanged(t, t));
}
return this;
}
@Override
public boolean has() {
return t != null;
}
@Override
public O<T> clearObservers() {
observers.clear();
return this;
}
@Override
public O<T> observe(Observer<T> t) {
if (observers == null) {
observers = new KList<>();
}
observers.add(t);
return this;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public interface Observable<T> {
T get();
Observable<T> set(T t);
boolean has();
Observable<T> clearObservers();
Observable<T> observe(Observer<T> t);
}

View File

@@ -0,0 +1,24 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
@FunctionalInterface
public interface Observer<T> {
void onChanged(T from, T to);
}

View File

@@ -0,0 +1,123 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public class PrecisionStopwatch {
private long nanos;
private long startNano;
private long millis;
private long startMillis;
private double time;
private boolean profiling;
public static PrecisionStopwatch start() {
PrecisionStopwatch p = new PrecisionStopwatch();
p.begin();
return p;
}
public PrecisionStopwatch() {
reset();
profiling = false;
}
public void begin() {
profiling = true;
startNano = System.nanoTime();
startMillis = System.currentTimeMillis();
}
public void end() {
if (!profiling) {
return;
}
profiling = false;
nanos = System.nanoTime() - startNano;
millis = System.currentTimeMillis() - startMillis;
time = (double) nanos / 1000000.0;
time = (double) millis - time > 1.01 ? millis : time;
}
public void reset() {
nanos = -1;
millis = -1;
startNano = -1;
startMillis = -1;
time = -0;
profiling = false;
}
public double getTicks() {
return getMilliseconds() / 50.0;
}
public double getSeconds() {
return getMilliseconds() / 1000.0;
}
public double getMinutes() {
return getSeconds() / 60.0;
}
public double getHours() {
return getMinutes() / 60.0;
}
public double getMilliseconds() {
nanos = System.nanoTime() - startNano;
millis = System.currentTimeMillis() - startMillis;
time = (double) nanos / 1000000.0;
time = (double) millis - time > 1.01 ? millis : time;
return time;
}
public long getNanoseconds() {
return (long) (time * 1000000.0);
}
public long getNanos() {
return nanos;
}
public long getStartNano() {
return startNano;
}
public long getMillis() {
return millis;
}
public long getStartMillis() {
return startMillis;
}
public double getTime() {
return time;
}
public boolean isProfiling() {
return profiling;
}
public void rewind(long l) {
startMillis -= l;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
@SuppressWarnings("ALL")
public interface Queue<T> {
Queue<T> queue(T t);
Queue<T> queue(KList<T> t);
boolean hasNext(int amt);
boolean hasNext();
T next();
KList<T> next(int amt);
Queue<T> clear();
int size();
static <T> Queue<T> create(KList<T> t) {
return new ShurikenQueue<T>().queue(t);
}
@SuppressWarnings("unchecked")
static <T> Queue<T> create(T... t) {
return new ShurikenQueue<T>().queue(new KList<T>().add(t));
}
boolean contains(T p);
}

View File

@@ -0,0 +1,62 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
public class QueueExecutor extends Looper {
private final Queue<Runnable> queue;
private boolean shutdown;
public QueueExecutor() {
queue = new ShurikenQueue<>();
shutdown = false;
}
public Queue<Runnable> queue() {
return queue;
}
@Override
protected long loop() {
while (queue.hasNext()) {
try {
queue.next().run();
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
}
if (shutdown && !queue.hasNext()) {
interrupt();
return -1;
}
return Math.max(500, (long) getRunTime() * 10);
}
public double getRunTime() {
return 0;
}
public void shutdown() {
shutdown = true;
}
}

View File

@@ -0,0 +1,29 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public abstract class S implements Runnable {
public S() {
J.s(this);
}
public S(int delay) {
J.s(this, delay);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.util.plugin.CancellableTask;
public abstract class SR implements Runnable, CancellableTask {
private int id = 0;
public SR() {
this(0);
}
public SR(int interval) {
id = J.sr(this, interval);
}
@Override
public void cancel() {
J.csr(id);
}
public int getId() {
return id;
}
}

View File

@@ -0,0 +1,97 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public class ShurikenQueue<T> implements Queue<T> {
private KList<T> queue;
private boolean randomPop;
private boolean reversePop;
public ShurikenQueue() {
clear();
}
public ShurikenQueue<T> responsiveMode() {
reversePop = true;
return this;
}
public ShurikenQueue<T> randomMode() {
randomPop = true;
return this;
}
@Override
public ShurikenQueue<T> queue(T t) {
queue.add(t);
return this;
}
@Override
public ShurikenQueue<T> queue(KList<T> t) {
queue.add(t);
return this;
}
@Override
public boolean hasNext(int amt) {
return queue.size() >= amt;
}
@Override
public boolean hasNext() {
return !queue.isEmpty();
}
@Override
public T next() {
return reversePop ? queue.popLast() : randomPop ? queue.popRandom() : queue.pop();
}
@Override
public KList<T> next(int amt) {
KList<T> t = new KList<>();
for (int i = 0; i < amt; i++) {
if (!hasNext()) {
break;
}
t.add(next());
}
return t;
}
@Override
public ShurikenQueue<T> clear() {
queue = new KList<>();
return this;
}
@Override
public int size() {
return queue.size();
}
@Override
public boolean contains(T p) {
return queue.contains(p);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public class Switch {
private volatile boolean b;
/**
* Defaulted off
*/
public Switch() {
b = false;
}
public void flip() {
b = true;
}
public boolean isFlipped() {
return b;
}
public void reset() {
b = false;
}
}

View File

@@ -0,0 +1,205 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
import com.volmit.iris.util.function.NastyRunnable;
import com.volmit.iris.util.math.M;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
import java.util.concurrent.ForkJoinWorkerThread;
public class TaskExecutor {
private int xc;
private final ExecutorService service;
public TaskExecutor(int threadLimit, int priority, String name) {
xc = 1;
if (threadLimit == 1) {
service = Executors.newSingleThreadExecutor((r) ->
{
Thread t = new Thread(r);
t.setName(name);
t.setPriority(priority);
return t;
});
} else if (threadLimit > 1) {
final ForkJoinWorkerThreadFactory factory = pool -> {
final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
worker.setName(name + " " + xc++);
worker.setPriority(priority);
return worker;
};
service = new ForkJoinPool(threadLimit, factory, null, false);
} else {
service = Executors.newCachedThreadPool((r) ->
{
Thread t = new Thread(r);
t.setName(name + " " + xc++);
t.setPriority(priority);
return t;
});
}
}
public TaskGroup startWork() {
return new TaskGroup(this);
}
public void close() {
J.a(() ->
{
J.sleep(10000);
service.shutdown();
});
}
public void closeNow() {
service.shutdown();
}
public static class TaskGroup {
private final KList<AssignedTask> tasks;
private final TaskExecutor e;
public TaskGroup(TaskExecutor e) {
tasks = new KList<>();
this.e = e;
}
public TaskGroup queue(NastyRunnable... r) {
for (NastyRunnable i : r) {
tasks.add(new AssignedTask(i));
}
return this;
}
public TaskGroup queue(KList<NastyRunnable> r) {
for (NastyRunnable i : r) {
tasks.add(new AssignedTask(i));
}
return this;
}
public TaskResult execute() {
double timeElapsed = 0;
int tasksExecuted = 0;
int tasksFailed = 0;
int tasksCompleted = 0;
tasks.forEach((t) -> t.go(e));
long msv = M.ns();
waiting:
while (true) {
try {
//noinspection BusyWait
Thread.sleep(0);
} catch (InterruptedException ignored) {
}
for (AssignedTask i : tasks) {
if (i.state.equals(TaskState.QUEUED) || i.state.equals(TaskState.RUNNING)) {
continue waiting;
}
}
timeElapsed = (double) (M.ns() - msv) / 1000000D;
for (AssignedTask i : tasks) {
if (i.state.equals(TaskState.COMPLETED)) {
tasksCompleted++;
} else {
tasksFailed++;
}
tasksExecuted++;
}
break;
}
return new TaskResult(timeElapsed, tasksExecuted, tasksFailed, tasksCompleted);
}
}
@SuppressWarnings("ClassCanBeRecord")
@ToString
public static class TaskResult {
public TaskResult(double timeElapsed, int tasksExecuted, int tasksFailed, int tasksCompleted) {
this.timeElapsed = timeElapsed;
this.tasksExecuted = tasksExecuted;
this.tasksFailed = tasksFailed;
this.tasksCompleted = tasksCompleted;
}
public final double timeElapsed;
public final int tasksExecuted;
public final int tasksFailed;
public final int tasksCompleted;
}
public enum TaskState {
QUEUED,
RUNNING,
COMPLETED,
FAILED
}
public static class AssignedTask {
@Getter
@Setter
private TaskState state;
@Getter
private final NastyRunnable task;
public AssignedTask(NastyRunnable task) {
this.task = task;
state = TaskState.QUEUED;
}
public void go(TaskExecutor e) {
e.service.execute(() ->
{
state = TaskState.RUNNING;
try {
task.run();
state = TaskState.COMPLETED;
} catch (Throwable ex) {Iris.reportError(ex);
ex.printStackTrace();
Iris.reportError(ex);
state = TaskState.FAILED;
}
});
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
import com.volmit.iris.Iris;
/**
* Not particularly efficient or perfectly accurate but is great at fast thread
* switching detection
*
* @author dan
*/
public class ThreadMonitor extends Thread {
private final Thread monitor;
private boolean running;
private State lastState;
private final ChronoLatch cl;
private PrecisionStopwatch st;
int cycles = 0;
private final RollingSequence sq = new RollingSequence(3);
private ThreadMonitor(Thread monitor) {
running = true;
st = PrecisionStopwatch.start();
this.monitor = monitor;
lastState = State.NEW;
cl = new ChronoLatch(1000);
start();
}
public void run() {
while (running) {
try {
//noinspection BusyWait
Thread.sleep(0);
State s = monitor.getState();
if (lastState != s) {
cycles++;
pushState(s);
}
lastState = s;
if (cl.flip()) {
Iris.info("Cycles: " + Form.f(cycles) + " (" + Form.duration(sq.getAverage(), 2) + ")");
}
} catch (Throwable e) {Iris.reportError(e);
running = false;
break;
}
}
}
public void pushState(State s) {
if (s != State.RUNNABLE) {
if (st != null) {
sq.put(st.getMilliseconds());
}
} else {
st = PrecisionStopwatch.start();
}
}
public void unbind() {
running = false;
}
public static ThreadMonitor bind(Thread monitor) {
return new ThreadMonitor(monitor);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util;
public class Wrapper<T> {
private T t;
public Wrapper(T t) {
set(t);
}
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((t == null) ? 0 : t.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Wrapper<?> other)) {
return false;
}
if (t == null) {
return other.t == null;
} else return t.equals(other.t);
}
@Override
public String toString() {
if (t != null) {
return get().toString();
}
return super.toString() + " (null)";
}
}