From 7691d2df53ef193e493f1770df1db3352a26c3eb Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Sat, 15 Aug 2026 22:32:40 -0400 Subject: [PATCH] dwa --- .../iris/core/commands/CommandPregen.java | 11 +- .../iris/modded/command/ModdedPregenJob.java | 10 +- .../art/arcane/iris/core/gui/GuiHost.java | 38 +++ .../iris/core/gui/NoiseExplorerGUI.java | 4 +- .../arcane/iris/core/gui/PregenRenderer.java | 120 +++++--- .../arcane/iris/core/gui/PregeneratorJob.java | 92 ++++-- .../art/arcane/iris/core/gui/VisionGUI.java | 9 +- .../BukkitCommandMessagesExtended.java | 4 +- .../core/localization/DesktopUiMessages.java | 4 +- .../core/localization/RuntimeUiMessages.java | 4 +- .../core/pregenerator/IrisPregenerator.java | 208 +++++++------- .../core/pregenerator/PregenRateTracker.java | 100 +++++++ .../iris/core/pregenerator/PregenRates.java | 28 ++ .../methods/AsyncPregenMethod.java | 4 +- .../iris/core/tools/IrisPackBenchmarking.java | 21 +- .../iris/util/project/noise/CloverNoise.java | 261 +++++++++++------- core/src/main/resources/languages/de_DE.json | 10 +- core/src/main/resources/languages/es_ES.json | 10 +- core/src/main/resources/languages/fi_FI.json | 10 +- core/src/main/resources/languages/fr_FR.json | 10 +- core/src/main/resources/languages/he_IL.json | 10 +- core/src/main/resources/languages/it_IT.json | 10 +- core/src/main/resources/languages/ja-JP.json | 10 +- core/src/main/resources/languages/ko_KR.json | 10 +- core/src/main/resources/languages/lt_LT.json | 10 +- core/src/main/resources/languages/nl_NL.json | 10 +- core/src/main/resources/languages/pl_PL.json | 10 +- core/src/main/resources/languages/pt_PT.json | 10 +- core/src/main/resources/languages/ru_RU.json | 10 +- core/src/main/resources/languages/tr_TR.json | 10 +- core/src/main/resources/languages/vi_VI.json | 10 +- core/src/main/resources/languages/zh_CN.json | 10 +- core/src/main/resources/languages/zh_TW.json | 10 +- .../art/arcane/iris/core/gui/GuiHostTest.java | 58 ++++ .../pregenerator/PregenRateTrackerTest.java | 73 +++++ .../AsyncPregenMethodConcurrencyCapTest.java | 8 +- .../project/noise/CloverNoiseParityTest.java | 43 +++ 37 files changed, 889 insertions(+), 381 deletions(-) create mode 100644 core/src/main/java/art/arcane/iris/core/pregenerator/PregenRateTracker.java create mode 100644 core/src/main/java/art/arcane/iris/core/pregenerator/PregenRates.java create mode 100644 core/src/test/java/art/arcane/iris/core/gui/GuiHostTest.java create mode 100644 core/src/test/java/art/arcane/iris/core/pregenerator/PregenRateTrackerTest.java create mode 100644 core/src/test/java/art/arcane/iris/util/project/noise/CloverNoiseParityTest.java diff --git a/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandPregen.java b/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandPregen.java index bab287a01..96b642f17 100644 --- a/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandPregen.java +++ b/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandPregen.java @@ -123,6 +123,15 @@ public class CommandPregen implements DirectorExecutor { String world = progress.worldName() == null ? "?" : progress.worldName(); sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_PREGEN_PREGEN, MessageArgument.untrusted("world", world), MessageArgument.untrusted("value", Form.f(progress.generated())), MessageArgument.untrusted("value2", Form.f(progress.totalChunks())), MessageArgument.untrusted("value3", String.format("%.1f", progress.percent())), MessageArgument.untrusted("value4", (progress.paused() ? C.YELLOW + " PAUSED" : "")))); - sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_PREGEN_SPEED_S_ETA_ELAPSED_METHOD, MessageArgument.untrusted("value", Form.f((int) progress.chunksPerSecond())), MessageArgument.untrusted("value2", Form.duration(progress.eta(), 2)), MessageArgument.untrusted("value3", Form.duration(progress.elapsed(), 2)), MessageArgument.untrusted("value4", progress.method()), MessageArgument.untrusted("value5", (progress.failed() > 0 ? C.RED + " Failed: " + Form.f(progress.failed()) : "")))); + sender().sendMessage(IrisLanguage.text( + BukkitCommandMessagesExtended.COMMAND_PREGEN_SPEED_S_ETA_ELAPSED_METHOD, + MessageArgument.untrusted("overall", Form.f(progress.overallChunksPerSecond(), 1)), + MessageArgument.untrusted("tenSecond", Form.f(progress.chunksPerSecond(), 1)), + MessageArgument.untrusted("thirtySecond", Form.f(progress.thirtySecondChunksPerSecond(), 1)), + MessageArgument.untrusted("sixtySecond", Form.f(progress.sixtySecondChunksPerSecond(), 1)), + MessageArgument.untrusted("eta", Form.duration(progress.eta(), 2)), + MessageArgument.untrusted("elapsed", Form.duration(progress.elapsed(), 2)), + MessageArgument.untrusted("method", progress.method()), + MessageArgument.untrusted("failures", progress.failed() > 0 ? C.RED + " Failed: " + Form.f(progress.failed()) : ""))); } } diff --git a/adapters/modded-common/src/main/java/art/arcane/iris/modded/command/ModdedPregenJob.java b/adapters/modded-common/src/main/java/art/arcane/iris/modded/command/ModdedPregenJob.java index f35a9091b..fc257cf35 100644 --- a/adapters/modded-common/src/main/java/art/arcane/iris/modded/command/ModdedPregenJob.java +++ b/adapters/modded-common/src/main/java/art/arcane/iris/modded/command/ModdedPregenJob.java @@ -170,7 +170,10 @@ public final class ModdedPregenJob { RuntimeUiMessages.PREGEN_STATUS_CHUNKS_FAILED, MessageArgument.trusted("generated", Form.f(progress.generated())), MessageArgument.trusted("total", Form.f(progress.totalChunks())), - MessageArgument.trusted("speed", Form.f((int) progress.chunksPerSecond())), + MessageArgument.trusted("overall", Form.f(progress.overallChunksPerSecond(), 1)), + MessageArgument.trusted("tenSecond", Form.f(progress.chunksPerSecond(), 1)), + MessageArgument.trusted("thirtySecond", Form.f(progress.thirtySecondChunksPerSecond(), 1)), + MessageArgument.trusted("sixtySecond", Form.f(progress.sixtySecondChunksPerSecond(), 1)), MessageArgument.trusted("failed", Form.f(progress.failed())) ); } @@ -178,7 +181,10 @@ public final class ModdedPregenJob { RuntimeUiMessages.PREGEN_STATUS_CHUNKS, MessageArgument.trusted("generated", Form.f(progress.generated())), MessageArgument.trusted("total", Form.f(progress.totalChunks())), - MessageArgument.trusted("speed", Form.f((int) progress.chunksPerSecond())) + MessageArgument.trusted("overall", Form.f(progress.overallChunksPerSecond(), 1)), + MessageArgument.trusted("tenSecond", Form.f(progress.chunksPerSecond(), 1)), + MessageArgument.trusted("thirtySecond", Form.f(progress.thirtySecondChunksPerSecond(), 1)), + MessageArgument.trusted("sixtySecond", Form.f(progress.sixtySecondChunksPerSecond(), 1)) ); } diff --git a/core/src/main/java/art/arcane/iris/core/gui/GuiHost.java b/core/src/main/java/art/arcane/iris/core/gui/GuiHost.java index 72b2947ca..45b6c4962 100644 --- a/core/src/main/java/art/arcane/iris/core/gui/GuiHost.java +++ b/core/src/main/java/art/arcane/iris/core/gui/GuiHost.java @@ -19,11 +19,18 @@ package art.arcane.iris.core.gui; import art.arcane.iris.core.IrisSettings; +import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.engine.framework.Engine; +import javax.swing.JFrame; +import java.awt.Desktop; import java.awt.GraphicsEnvironment; +import java.awt.desktop.QuitResponse; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicBoolean; public final class GuiHost { + private static final AtomicBoolean DESKTOP_QUIT_GUARD_INSTALLED = new AtomicBoolean(false); private static volatile Provider provider = new Provider() { }; private static volatile boolean desktopSuppressed = false; @@ -69,6 +76,37 @@ public final class GuiHost { return !desktopSuppressed && !GraphicsEnvironment.isHeadless(); } + public static void prepareFrame(JFrame frame) { + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + prepareServerDesktop(); + } + + private static void prepareServerDesktop() { + if (!isAvailable() + || !System.getProperty("os.name", "").toLowerCase(Locale.ROOT).contains("mac") + || !DESKTOP_QUIT_GUARD_INSTALLED.compareAndSet(false, true)) { + return; + } + + try { + if (!Desktop.isDesktopSupported()) { + return; + } + Desktop desktop = Desktop.getDesktop(); + if (!desktop.isSupported(Desktop.Action.APP_QUIT_HANDLER)) { + return; + } + desktop.setQuitHandler((event, response) -> cancelDesktopQuit(response)); + } catch (Throwable error) { + IrisLogging.reportError(error); + IrisLogging.warn("Unable to install the Iris desktop quit guard; use the server stop command instead of macOS Quit"); + } + } + + static void cancelDesktopQuit(QuitResponse response) { + response.cancelQuit(); + } + /** * Outcome of a server triggered desktop gui launch request. */ diff --git a/core/src/main/java/art/arcane/iris/core/gui/NoiseExplorerGUI.java b/core/src/main/java/art/arcane/iris/core/gui/NoiseExplorerGUI.java index 082ff59f5..f8d6075c4 100644 --- a/core/src/main/java/art/arcane/iris/core/gui/NoiseExplorerGUI.java +++ b/core/src/main/java/art/arcane/iris/core/gui/NoiseExplorerGUI.java @@ -174,7 +174,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener { private static JFrame buildFrame(String title, NoiseExplorerGUI nv, Engine engine, Supplier> customGen, String customName) { JFrame frame = new JFrame(title); - frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + GuiHost.prepareFrame(frame); frame.getContentPane().setBackground(BG); frame.setLayout(new BorderLayout()); @@ -188,7 +188,7 @@ public class NoiseExplorerGUI extends JPanel implements MouseWheelListener { frame.setVisible(true); frame.addWindowListener(new WindowAdapter() { @Override - public void windowClosing(WindowEvent e) { + public void windowClosed(WindowEvent e) { GuiHost.get().unregisterHotloadHook(nv.hotloadHook); } }); diff --git a/core/src/main/java/art/arcane/iris/core/gui/PregenRenderer.java b/core/src/main/java/art/arcane/iris/core/gui/PregenRenderer.java index 6c3eaf5c6..d241c32da 100644 --- a/core/src/main/java/art/arcane/iris/core/gui/PregenRenderer.java +++ b/core/src/main/java/art/arcane/iris/core/gui/PregenRenderer.java @@ -22,105 +22,135 @@ import art.arcane.iris.core.localization.DesktopUiMessages; import art.arcane.iris.core.localization.IrisLanguage; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.core.IrisSettings; -import art.arcane.volmlib.util.collection.KList; -import art.arcane.volmlib.util.function.Consumer2; import art.arcane.volmlib.util.math.M; -import art.arcane.volmlib.util.math.Position2; -import art.arcane.iris.util.common.scheduling.J; +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import javax.swing.JFrame; import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.Timer; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Frame; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.util.concurrent.locks.ReentrantLock; public final class PregenRenderer extends JPanel implements KeyListener { private static final long serialVersionUID = 2094606939770332040L; - // Backstop: if paint() ever stalls (iconified frame, EDT hiccup), the producer must not - // grow this without bound — one entry per drawn chunk adds up fast on a big pregen. - private static final int MAX_QUEUED_DRAWS = 250_000; - private KList order = new KList<>(); + private static final int MAX_PENDING_DRAWS = 16_384; + private Long2ObjectLinkedOpenHashMap pending = new Long2ObjectLinkedOpenHashMap<>(); private final ReentrantLock lock = new ReentrantLock(); private final int res = 512; private final BufferedImage image = new BufferedImage(res, res, BufferedImage.TYPE_INT_RGB); + private final Graphics2D imageGraphics = image.createGraphics(); private final PregenRenderSource source; private final Runnable onPause; - private Graphics2D bg; - private JFrame frame; + private final Timer repaintTimer; + private volatile boolean renderingEnabled; + private boolean disposed; + private volatile JFrame frame; private PregenRenderer(PregenRenderSource source, Runnable onPause) { this.source = source; this.onPause = onPause; + repaintTimer = new Timer(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250, event -> repaint()); } public static PregenRenderer open(String title, PregenRenderSource source, Runnable onPause) { PregenRenderer renderer = new PregenRenderer(source, onPause); JFrame frame = new JFrame(title); + GuiHost.prepareFrame(frame); renderer.frame = frame; + renderer.renderingEnabled = true; frame.addKeyListener(renderer); frame.add(renderer); frame.setSize(1000, 1000); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent event) { + renderer.disposeRenderer(); + } + }); + frame.addWindowStateListener(event -> renderer.renderingEnabled = (event.getNewState() & Frame.ICONIFIED) == 0); frame.setVisible(true); + renderer.repaintTimer.start(); return renderer; } - public Consumer2 drawFunction() { - return (Position2 c, Color color) -> { - lock.lock(); - try { - if (order.size() < MAX_QUEUED_DRAWS) { - order.add(() -> draw(c, color, bg)); - } - } finally { - lock.unlock(); - } - }; - } - public void submit(int x, int z, Color color) { - drawFunction().accept(new Position2(x, z), color); + if (!renderingEnabled) { + return; + } + + long key = ((long) x << 32) ^ (z & 0xffffffffL); + lock.lock(); + try { + pending.putAndMoveToFirst(key, color); + if (pending.size() > MAX_PENDING_DRAWS) { + pending.removeLast(); + } + } finally { + lock.unlock(); + } } public boolean isVisibleFrame() { - // An iconified frame still reports isVisible() but AWT stops repainting it, which - // would stop the only queue drain while the producer keeps appending. - JFrame activeFrame = frame; - return activeFrame != null && activeFrame.isVisible() - && (activeFrame.getExtendedState() & java.awt.Frame.ICONIFIED) == 0; + return renderingEnabled; } public void close() { + if (!SwingUtilities.isEventDispatchThread()) { + SwingUtilities.invokeLater(this::close); + return; + } JFrame activeFrame = frame; if (activeFrame != null) { - frame = null; - activeFrame.setVisible(false); activeFrame.dispose(); + } else { + disposeRenderer(); } } + private void disposeRenderer() { + if (disposed) { + return; + } + disposed = true; + renderingEnabled = false; + frame = null; + repaintTimer.stop(); + lock.lock(); + try { + pending.clear(); + } finally { + lock.unlock(); + } + imageGraphics.dispose(); + } + @Override public void paint(Graphics gx) { Graphics2D g = (Graphics2D) gx; - bg = (Graphics2D) image.getGraphics(); - // Swap the queue under the lock and drain outside it: generation threads must not - // block on the lock while the EDT walks a large batch, and pop()-per-entry was O(N^2). - KList batch; + Long2ObjectLinkedOpenHashMap batch; lock.lock(); try { - batch = order; - order = new KList<>(); + batch = pending; + pending = new Long2ObjectLinkedOpenHashMap<>(); } finally { lock.unlock(); } - for (Runnable r : batch) { + for (Long2ObjectMap.Entry entry : batch.long2ObjectEntrySet()) { try { - r.run(); + long key = entry.getLongKey(); + draw((int) (key >> 32), (int) key, entry.getValue(), imageGraphics); } catch (Throwable e) { IrisLogging.reportError(e); } @@ -143,15 +173,13 @@ public final class PregenRenderer extends JPanel implements KeyListener { g.drawString(IrisLanguage.plain(DesktopUiMessages.PREGEN_PAUSE_HINT), 20, hh += h); } - J.sleep(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250); - repaint(); } - private void draw(Position2 p, Color c, Graphics2D bg) { - double pw = M.lerpInverse(source.min().getX(), source.max().getX(), p.getX()); - double ph = M.lerpInverse(source.min().getZ(), source.max().getZ(), p.getZ()); - double pwa = M.lerpInverse(source.min().getX(), source.max().getX(), p.getX() + 1); - double pha = M.lerpInverse(source.min().getZ(), source.max().getZ(), p.getZ() + 1); + private void draw(int chunkX, int chunkZ, Color c, Graphics2D bg) { + double pw = M.lerpInverse(source.min().getX(), source.max().getX(), chunkX); + double ph = M.lerpInverse(source.min().getZ(), source.max().getZ(), chunkZ); + double pwa = M.lerpInverse(source.min().getX(), source.max().getX(), chunkX + 1); + double pha = M.lerpInverse(source.min().getZ(), source.max().getZ(), chunkZ + 1); int x = (int) M.lerp(0, res, pw); int z = (int) M.lerp(0, res, ph); int xa = (int) M.lerp(0, res, pwa); diff --git a/core/src/main/java/art/arcane/iris/core/gui/PregeneratorJob.java b/core/src/main/java/art/arcane/iris/core/gui/PregeneratorJob.java index 880e295b0..4fbef3eb4 100644 --- a/core/src/main/java/art/arcane/iris/core/gui/PregeneratorJob.java +++ b/core/src/main/java/art/arcane/iris/core/gui/PregeneratorJob.java @@ -29,22 +29,26 @@ import art.arcane.iris.core.pregenerator.PregenApiPhase; import art.arcane.iris.core.pregenerator.PregenApiSink; import art.arcane.iris.core.pregenerator.PregenListener; import art.arcane.iris.core.pregenerator.PregenPhaseTracker; +import art.arcane.iris.core.pregenerator.PregenRates; import art.arcane.iris.core.pregenerator.PregenTask; import art.arcane.iris.core.pregenerator.PregeneratorMethod; import art.arcane.iris.engine.framework.Engine; import art.arcane.volmlib.util.format.Form; import art.arcane.volmlib.util.format.MemoryMonitor; -import art.arcane.volmlib.util.function.Consumer2; import art.arcane.volmlib.util.mantle.runtime.Mantle; import art.arcane.volmlib.util.localization.MessageArgument; import art.arcane.volmlib.util.math.Position2; import art.arcane.iris.util.common.scheduling.J; import java.awt.Color; +import java.awt.EventQueue; import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -64,7 +68,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { private static final AtomicReference instance = new AtomicReference<>(); private final MemoryMonitor monitor; private final PregenTask task; - private final boolean saving; + private final AtomicBoolean saving; private final List> onProgress = new CopyOnWriteArrayList<>(); private final List whenDone = new CopyOnWriteArrayList<>(); private final IrisPregenerator pregenerator; @@ -75,9 +79,11 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { private final Thread worker; private final PregenPhaseTracker apiPhases = new PregenPhaseTracker(); private PregenRenderer renderer; - private Consumer2 drawFunction; private String[] info; private volatile double lastChunksPerSecond = 0D; + private volatile double lastOverallChunksPerSecond = 0D; + private volatile double lastThirtySecondChunksPerSecond = 0D; + private volatile double lastSixtySecondChunksPerSecond = 0D; private volatile long lastChunksRemaining = 0L; private volatile long lastGenerated = 0L; private volatile long lastTotalChunks = 0L; @@ -88,13 +94,26 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) { this.engine = engine; monitor = new MemoryMonitor(50); - saving = false; + saving = new AtomicBoolean(false); info = new String[]{IrisLanguage.plain(DesktopUiMessages.PREGEN_INITIALIZING)}; this.task = task; this.pregenerator = new IrisPregenerator(task, method, this); max = new Position2(Integer.MIN_VALUE, Integer.MIN_VALUE); min = new Position2(Integer.MAX_VALUE, Integer.MAX_VALUE); - service = Executors.newVirtualThreadPerTaskExecutor(); + service = new ThreadPoolExecutor( + 1, + 1, + 0L, + TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(1_024), + runnable -> { + Thread thread = new Thread(runnable, "Iris Pregen Renderer"); + thread.setDaemon(true); + thread.setPriority(Thread.MIN_PRIORITY); + thread.setUncaughtExceptionHandler((activeThread, error) -> IrisLogging.reportError(error)); + return thread; + }, + new ThreadPoolExecutor.DiscardOldestPolicy()); switch (GuiHost.serverGuiLaunch(task.isGui())) { case OPEN -> open(); @@ -238,7 +257,10 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { return inst == null ? -1L : Math.max(0L, inst.lastChunksRemaining); } - public record PregenProgress(double percent, long generated, long totalChunks, double chunksPerSecond, long chunksRemaining, long eta, long elapsed, String method, boolean paused, long failed, String worldName, String worldIdentity) { + public record PregenProgress(double percent, long generated, long totalChunks, double chunksPerSecond, + double overallChunksPerSecond, double thirtySecondChunksPerSecond, + double sixtySecondChunksPerSecond, long chunksRemaining, long eta, long elapsed, + String method, boolean paused, long failed, String worldName, String worldIdentity) { } public static PregenProgress progressSnapshot() { @@ -253,6 +275,9 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { lastGenerated, lastTotalChunks, Math.max(0D, lastChunksPerSecond), + Math.max(0D, lastOverallChunksPerSecond), + Math.max(0D, lastThirtySecondChunksPerSecond), + Math.max(0D, lastSixtySecondChunksPerSecond), Math.max(0L, lastChunksRemaining), lastEta, lastElapsed, @@ -321,10 +346,12 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { public void draw(int x, int z, Color color) { try { - if (renderer != null && drawFunction != null && renderer.isVisibleFrame()) { - drawFunction.accept(new Position2(x, z), color); + PregenRenderer activeRenderer = renderer; + if (activeRenderer != null && activeRenderer.isVisibleFrame()) { + activeRenderer.submit(x, z, color); } - } catch (Throwable ignored) { + } catch (Throwable error) { + IrisLogging.reportError(error); IrisLogging.error("Failed to draw pregen"); } } @@ -339,26 +366,24 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { } public void close() { - J.a(() -> { - try { - monitor.close(); - if (renderer == null) { - return; - } - J.sleep(3000); - renderer.close(); - } catch (Throwable ignored) { - IrisLogging.error("Error closing pregen gui"); + try { + monitor.close(); + PregenRenderer activeRenderer = renderer; + if (activeRenderer != null) { + activeRenderer.close(); } - }); + } catch (Throwable error) { + IrisLogging.reportError(error); + IrisLogging.error("Error closing pregen gui"); + } } public void open() { - J.a(() -> { + EventQueue.invokeLater(() -> { try { renderer = PregenRenderer.open(IrisLanguage.plain(DesktopUiMessages.PREGEN_TITLE), this, PregeneratorJob::pauseResume); - drawFunction = renderer.drawFunction(); - } catch (Throwable ignored) { + } catch (Throwable error) { + IrisLogging.reportError(error); IrisLogging.error("Error opening pregen gui"); } }); @@ -366,7 +391,11 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { @Override public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, long generated, long totalChunks, long chunksRemaining, long eta, long elapsed, String method, boolean cached) { + PregenRates rateSnapshot = pregenerator.getRates(); lastChunksPerSecond = chunksPerSecond; + lastOverallChunksPerSecond = rateSnapshot.overall(); + lastThirtySecondChunksPerSecond = rateSnapshot.thirtySecond(); + lastSixtySecondChunksPerSecond = rateSnapshot.sixtySecond(); lastChunksRemaining = chunksRemaining; lastGenerated = generated; lastTotalChunks = totalChunks; @@ -377,16 +406,17 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { info = new String[]{ IrisLanguage.plain( paused() ? DesktopUiMessages.PREGEN_PROGRESS_PAUSED - : saving ? DesktopUiMessages.PREGEN_PROGRESS_SAVING : DesktopUiMessages.PREGEN_PROGRESS_GENERATING, + : saving.getAndSet(false) ? DesktopUiMessages.PREGEN_PROGRESS_SAVING : DesktopUiMessages.PREGEN_PROGRESS_GENERATING, MessageArgument.trusted("generated", Form.f(generated)), MessageArgument.trusted("total", Form.f(totalChunks)), MessageArgument.trusted("percent", Form.pc(percent, 0)) ), IrisLanguage.plain( cached ? DesktopUiMessages.PREGEN_SPEED_CACHED : DesktopUiMessages.PREGEN_SPEED, - MessageArgument.trusted("chunksPerSecond", Form.f(chunksPerSecond, 0)), - MessageArgument.trusted("regionsPerMinute", Form.f(regionsPerMinute, 1)), - MessageArgument.trusted("chunksPerMinute", Form.f(chunksPerMinute, 0)) + MessageArgument.trusted("overall", Form.f(rateSnapshot.overall(), 1)), + MessageArgument.trusted("tenSecond", Form.f(rateSnapshot.tenSecond(), 1)), + MessageArgument.trusted("thirtySecond", Form.f(rateSnapshot.thirtySecond(), 1)), + MessageArgument.trusted("sixtySecond", Form.f(rateSnapshot.sixtySecond(), 1)) ), IrisLanguage.plain( DesktopUiMessages.PREGEN_TIME, @@ -441,7 +471,10 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { @Override public void onChunkGenerated(int x, int z, boolean cached) { if (renderer == null || !renderer.isVisibleFrame()) return; - service.submit(() -> { + if (service.isShutdown()) { + return; + } + service.execute(() -> { if (engine != null) { draw(x, z, engine.draw((x << 4) + 8, (z << 4) + 8)); return; @@ -517,6 +550,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource { @Override public void onSaving() { + saving.set(true); dispatchApiPhases(apiPhases.onSaving()); } diff --git a/core/src/main/java/art/arcane/iris/core/gui/VisionGUI.java b/core/src/main/java/art/arcane/iris/core/gui/VisionGUI.java index 895604f5f..6aac2efa7 100644 --- a/core/src/main/java/art/arcane/iris/core/gui/VisionGUI.java +++ b/core/src/main/java/art/arcane/iris/core/gui/VisionGUI.java @@ -179,19 +179,20 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener }); frame.addWindowListener(new WindowAdapter() { @Override - public void windowClosing(WindowEvent windowEvent) { - e.shutdown(); - eh.shutdown(); + public void windowClosed(WindowEvent windowEvent) { + e.shutdownNow(); + eh.shutdownNow(); } }); } public static void launch(Engine g) { - J.a(() -> createAndShowGUI(g)); + EventQueue.invokeLater(() -> createAndShowGUI(g)); } private static void createAndShowGUI(Engine r) { JFrame frame = new JFrame(IrisLanguage.plain(DesktopUiMessages.VISION_TITLE)); + GuiHost.prepareFrame(frame); VisionGUI nv = new VisionGUI(frame); nv.engine = r; nv.overlay = GuiHost.get().overlayFor(r); diff --git a/core/src/main/java/art/arcane/iris/core/localization/BukkitCommandMessagesExtended.java b/core/src/main/java/art/arcane/iris/core/localization/BukkitCommandMessagesExtended.java index 8d96c99e8..4c659c982 100644 --- a/core/src/main/java/art/arcane/iris/core/localization/BukkitCommandMessagesExtended.java +++ b/core/src/main/java/art/arcane/iris/core/localization/BukkitCommandMessagesExtended.java @@ -525,7 +525,9 @@ public final class BukkitCommandMessagesExtended { ); public static final TextKey COMMAND_PREGEN_SPEED_S_ETA_ELAPSED_METHOD = TextKey.of( "iris.bukkit.commandpregen.speed_s_eta_elapsed_method", - C.GREEN + "Speed: " + C.GOLD + "{value}" + "/s" + C.GREEN + " ETA: " + C.GOLD + "{value2}" + C.GREEN + " Elapsed: " + C.GOLD + "{value3}" + C.GREEN + " Method: " + C.GOLD + "{value4}" + "{value5}" + C.GREEN + "Rates: " + C.GOLD + "overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s" + + C.GREEN + " ETA: " + C.GOLD + "{eta}" + C.GREEN + " Elapsed: " + C.GOLD + "{elapsed}" + + C.GREEN + " Method: " + C.GOLD + "{method}" + "{failures}" ); public static final TextKey COMMAND_STRUCTURE_COULD_NOT_RESOLVE_PACK_DIMENSION = TextKey.of( "iris.bukkit.commandstructure.could_not_resolve_pack_dimension", diff --git a/core/src/main/java/art/arcane/iris/core/localization/DesktopUiMessages.java b/core/src/main/java/art/arcane/iris/core/localization/DesktopUiMessages.java index fdc896cce..af17ffe7e 100644 --- a/core/src/main/java/art/arcane/iris/core/localization/DesktopUiMessages.java +++ b/core/src/main/java/art/arcane/iris/core/localization/DesktopUiMessages.java @@ -88,8 +88,8 @@ public final class DesktopUiMessages { public static final TextKey PREGEN_PROGRESS_PAUSED = TextKey.of("iris.desktop.pregen.progress_paused", "PAUSED {generated} of {total} ({percent} complete)"); public static final TextKey PREGEN_PROGRESS_SAVING = TextKey.of("iris.desktop.pregen.progress_saving", "Saving... {generated} of {total} ({percent} complete)"); public static final TextKey PREGEN_PROGRESS_GENERATING = TextKey.of("iris.desktop.pregen.progress_generating", "Generating {generated} of {total} ({percent} complete)"); - public static final TextKey PREGEN_SPEED = TextKey.of("iris.desktop.pregen.speed", "Speed: {chunksPerSecond} chunks/s, {regionsPerMinute} regions/m, {chunksPerMinute} chunks/m"); - public static final TextKey PREGEN_SPEED_CACHED = TextKey.of("iris.desktop.pregen.speed_cached", "Speed: cached {chunksPerSecond} chunks/s, {regionsPerMinute} regions/m, {chunksPerMinute} chunks/m"); + public static final TextKey PREGEN_SPEED = TextKey.of("iris.desktop.pregen.speed", "Speed: overall {overall}, 10s {tenSecond}, 30s {thirtySecond}, 60s {sixtySecond} chunks/s"); + public static final TextKey PREGEN_SPEED_CACHED = TextKey.of("iris.desktop.pregen.speed_cached", "Speed (cached): overall {overall}, 10s {tenSecond}, 30s {thirtySecond}, 60s {sixtySecond} chunks/s"); public static final TextKey PREGEN_TIME = TextKey.of("iris.desktop.pregen.time", "{remaining} remaining ({elapsed} elapsed)"); public static final TextKey PREGEN_METHOD = TextKey.of("iris.desktop.pregen.method", "Generation method: {method}"); public static final TextKey PREGEN_MEMORY = TextKey.of("iris.desktop.pregen.memory", "Memory: {used} ({usage}) Pressure: {pressure}/s"); diff --git a/core/src/main/java/art/arcane/iris/core/localization/RuntimeUiMessages.java b/core/src/main/java/art/arcane/iris/core/localization/RuntimeUiMessages.java index e5a107420..093469a40 100644 --- a/core/src/main/java/art/arcane/iris/core/localization/RuntimeUiMessages.java +++ b/core/src/main/java/art/arcane/iris/core/localization/RuntimeUiMessages.java @@ -126,8 +126,8 @@ public final class RuntimeUiMessages { public static final TextKey PREGEN_FAILED_FRAGMENT = TextKey.of("iris.runtime.pregen.failed_fragment", " failed {failed}"); public static final TextKey PREGEN_STATUS_CONTEXT = TextKey.of("iris.runtime.pregen.status.context", "Dimension {dimension} · Method {method}"); public static final TextKey PREGEN_STATUS_PROGRESS = TextKey.of("iris.runtime.pregen.status.progress", "{percent}%"); - public static final TextKey PREGEN_STATUS_CHUNKS = TextKey.of("iris.runtime.pregen.status.chunks", "Chunks {generated}/{total} · Speed {speed}/s"); - public static final TextKey PREGEN_STATUS_CHUNKS_FAILED = TextKey.of("iris.runtime.pregen.status.chunks_failed", "Chunks {generated}/{total} · Speed {speed}/s · Failed {failed}"); + public static final TextKey PREGEN_STATUS_CHUNKS = TextKey.of("iris.runtime.pregen.status.chunks", "Chunks {generated}/{total} · Rates overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s"); + public static final TextKey PREGEN_STATUS_CHUNKS_FAILED = TextKey.of("iris.runtime.pregen.status.chunks_failed", "Chunks {generated}/{total} · Rates overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}"); public static final TextKey PREGEN_STATUS_TIME = TextKey.of("iris.runtime.pregen.status.time", "ETA {eta} · Elapsed {elapsed}"); public static final TextKey PREGEN_STATUS_TIME_PAUSED = TextKey.of("iris.runtime.pregen.status.time_paused", "ETA {eta} · Elapsed {elapsed} · PAUSED"); public static final TextKey PREGEN_PAUSE_BUTTON = TextKey.of("iris.runtime.pregen.button.pause", "Pause/Resume"); diff --git a/core/src/main/java/art/arcane/iris/core/pregenerator/IrisPregenerator.java b/core/src/main/java/art/arcane/iris/core/pregenerator/IrisPregenerator.java index 7a5b79203..c4a88a0b6 100644 --- a/core/src/main/java/art/arcane/iris/core/pregenerator/IrisPregenerator.java +++ b/core/src/main/java/art/arcane/iris/core/pregenerator/IrisPregenerator.java @@ -30,7 +30,6 @@ import art.arcane.volmlib.util.format.Form; import art.arcane.volmlib.util.mantle.runtime.Mantle; import art.arcane.volmlib.util.math.M; import art.arcane.volmlib.util.math.Position2; -import art.arcane.volmlib.util.math.RollingSequence; import art.arcane.volmlib.util.scheduling.ChronoLatch; import art.arcane.iris.util.common.scheduling.J; import art.arcane.volmlib.util.scheduling.Looper; @@ -51,20 +50,16 @@ public class IrisPregenerator { private final Looper ticker; private final AtomicBoolean paused; private final AtomicBoolean shutdown; - private final RollingSequence cachedPerSecond; - private final RollingSequence chunksPerSecond; - private final RollingSequence chunksPerMinute; - private final RollingSequence regionsPerMinute; + private final PregenRateTracker rateTracker; private final KList chunksPerSecondHistory; private final AtomicLong generated; - private final AtomicLong generatedLast; - private final AtomicLong generatedLastMinute; private final AtomicLong cached; - private final AtomicLong cachedLast; - private final AtomicLong cachedLastMinute; + private final AtomicLong lastCachedAtMillis; + private final AtomicLong historyLastGenerated; + private final AtomicLong historyLastCached; + private final AtomicLong historyLastMillis; private final AtomicLong totalChunks; private final AtomicLong startTime; - private final ChronoLatch minuteLatch; private final AtomicReference currentGeneratorMethod; private final KSet generatedRegions; private final KSet retry; @@ -74,12 +69,13 @@ public class IrisPregenerator { private final ChronoLatch heapReclaimLatch; private final AtomicLong failed; private final IrisPackBenchmarking benchmarking; + private volatile PregenRates rates; public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) { this.jobId = JOB_SEQUENCE.incrementAndGet(); benchmarking = IrisPackBenchmarking.getInstance(); this.listener = listenify(listener); - cl = new ChronoLatch(10000); + cl = new ChronoLatch(30000, false); saveLatch = new ChronoLatch(IrisSettings.get().getPregen().getSaveIntervalMs()); heapReclaimLatch = new ChronoLatch(1000); failed = new AtomicLong(0); @@ -91,85 +87,21 @@ public class IrisPregenerator { retry = new KSet<>(); net = new KSet<>(); currentGeneratorMethod = new AtomicReference<>("Void"); - minuteLatch = new ChronoLatch(60000, false); - cachedPerSecond = new RollingSequence(5); - chunksPerSecond = new RollingSequence(10); - chunksPerMinute = new RollingSequence(10); - regionsPerMinute = new RollingSequence(10); chunksPerSecondHistory = new KList<>(); generated = new AtomicLong(0); - generatedLast = new AtomicLong(0); - generatedLastMinute = new AtomicLong(0); cached = new AtomicLong(); - cachedLast = new AtomicLong(0); - cachedLastMinute = new AtomicLong(0); + lastCachedAtMillis = new AtomicLong(0L); + historyLastGenerated = new AtomicLong(0L); + historyLastCached = new AtomicLong(0L); + historyLastMillis = new AtomicLong(M.ms()); totalChunks = new AtomicLong(0); startTime = new AtomicLong(M.ms()); + rateTracker = new PregenRateTracker(startTime.get(), 0L); + rates = PregenRates.ZERO; ticker = new Looper() { @Override protected long loop() { - long eta = computeETA(); - - long secondCached = cached.get() - cachedLast.get(); - cachedLast.set(cached.get()); - cachedPerSecond.put(secondCached); - - long secondGenerated = generated.get() - generatedLast.get() - secondCached; - generatedLast.set(generated.get()); - if (secondCached == 0 || secondGenerated != 0) { - chunksPerSecond.put(secondGenerated); - synchronized (chunksPerSecondHistory) { - chunksPerSecondHistory.add((int) secondGenerated); - } - } - - if (minuteLatch.flip()) { - long minuteCached = cached.get() - cachedLastMinute.get(); - cachedLastMinute.set(cached.get()); - - long minuteGenerated = generated.get() - generatedLastMinute.get() - minuteCached; - generatedLastMinute.set(generated.get()); - if (minuteCached == 0 || minuteGenerated != 0) { - chunksPerMinute.put(minuteGenerated); - regionsPerMinute.put((double) minuteGenerated / 1024D); - } - } - boolean cached = cachedPerSecond.getAverage() != 0; - - listener.onTick( - cached ? cachedPerSecond.getAverage() : chunksPerSecond.getAverage(), - chunksPerMinute.getAverage(), - regionsPerMinute.getAverage(), - (double) generated.get() / (double) totalChunks.get(), generated.get(), - totalChunks.get(), - totalChunks.get() - generated.get(), eta, M.ms() - startTime.get(), currentGeneratorMethod.get(), - cached); - - IrisProtocolServer protocolServer = IrisServices.getOrNull(IrisProtocolServer.class); - if (protocolServer != null) { - protocolServer.broadcastPregenProgress( - jobId, - generated.get(), - totalChunks.get(), - cached ? cachedPerSecond.getAverage() : chunksPerSecond.getAverage(), - eta, - paused.get() ? IrisMessage.PregenProgress.STATE_PAUSED : IrisMessage.PregenProgress.STATE_RUNNING); - } - - if (cl.flip()) { - double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100; - - IrisLogging.info("%s: %s of %s (%.0f%%), %s/s ETA: %s", - benchmarking != null ? "Benchmarking" : "Pregen", - Form.f(generated.get()), - Form.f(totalChunks.get()), - percentage, - cached ? - "Cached " + Form.f((int) cachedPerSecond.getAverage()) : - Form.f((int) chunksPerSecond.getAverage()), - Form.duration(eta, 2) - ); - } + publishProgress(M.ms(), cl.flip()); return 1000; } }; @@ -179,16 +111,81 @@ public class IrisPregenerator { long gen = generated.get(); long total = totalChunks.get(); long remaining = total - gen; - double d; - if (gen > 1024) { - d = remaining * ((double) (M.ms() - startTime.get()) / (double) gen); - } else { - double cps = chunksPerSecond.getAverage(); - d = cps > 0 ? (remaining / cps) * 1000 : 0; - } + double cps = gen > 1024 ? rates.overall() : rates.tenSecond(); + double d = cps > 0D ? (remaining / cps) * 1000D : 0D; return Double.isFinite(d) && d != INVALID ? (long) d : 0; } + private void publishProgress(long now, boolean logProgress) { + long generatedCount = generated.get(); + long total = totalChunks.get(); + rates = rateTracker.sample(generatedCount, now); + sampleHistory(now, generatedCount, cached.get()); + long eta = computeETA(); + long lastCachedAt = lastCachedAtMillis.get(); + boolean cachedProgress = lastCachedAt > 0L && now - lastCachedAt <= 10_000L; + double chunksPerMinute = rates.sixtySecond() * 60D; + double percentage = total > 0L ? (double) generatedCount / (double) total : 0D; + + listener.onTick( + rates.tenSecond(), + chunksPerMinute, + chunksPerMinute / 1024D, + percentage, + generatedCount, + total, + Math.max(0L, total - generatedCount), + eta, + now - startTime.get(), + currentGeneratorMethod.get(), + cachedProgress); + + IrisProtocolServer protocolServer = IrisServices.getOrNull(IrisProtocolServer.class); + if (protocolServer != null) { + protocolServer.broadcastPregenProgress( + jobId, + generatedCount, + total, + rates.tenSecond(), + eta, + paused.get() ? IrisMessage.PregenProgress.STATE_PAUSED : IrisMessage.PregenProgress.STATE_RUNNING); + } + + if (logProgress) { + IrisLogging.info("%s: %s of %s (%.0f%%), rates overall=%s 10s=%s 30s=%s 60s=%s chunks/s%s, ETA: %s", + benchmarking != null ? "Benchmarking" : "Pregen", + Form.f(generatedCount), + Form.f(total), + percentage * 100D, + formatRate(rates.overall()), + formatRate(rates.tenSecond()), + formatRate(rates.thirtySecond()), + formatRate(rates.sixtySecond()), + cachedProgress ? " (cached)" : "", + Form.duration(eta, 2)); + } + } + + private void sampleHistory(long now, long generatedCount, long cachedCount) { + long previousTime = historyLastMillis.getAndSet(now); + long previousGenerated = historyLastGenerated.getAndSet(generatedCount); + long previousCached = historyLastCached.getAndSet(cachedCount); + long elapsed = now - previousTime; + long completed = generatedCount - previousGenerated - (cachedCount - previousCached); + if (elapsed <= 0L || completed <= 0L) { + return; + } + + int chunksPerSecond = (int) Math.round((double) completed * 1_000D / (double) elapsed); + synchronized (chunksPerSecondHistory) { + chunksPerSecondHistory.add(chunksPerSecond); + } + } + + private static String formatRate(double rate) { + return Form.f(rate, 1); + } + public long getJobId() { return jobId; @@ -207,7 +204,12 @@ public class IrisPregenerator { try { init(); task.iterateAllChunks((_a, _b) -> totalChunks.incrementAndGet()); - startTime.set(M.ms()); + long startedAt = M.ms(); + startTime.set(startedAt); + rateTracker.reset(startedAt, generated.get()); + historyLastGenerated.set(generated.get()); + historyLastCached.set(cached.get()); + historyLastMillis.set(startedAt); ticker.start(); checkRegions(); int[] regionBounds = task.regionBounds(); @@ -219,6 +221,7 @@ public class IrisPregenerator { IrisLogging.reportError(e); IrisLogging.error("Pregen aborted after " + Form.duration((long) p.getMilliseconds()) + " due to " + e.getClass().getSimpleName() + ": " + e.getMessage()); } finally { + publishProgress(M.ms(), false); shutdown(); } if (completed && allVisitsComplete()) { @@ -227,7 +230,7 @@ public class IrisPregenerator { logIncompleteCompletion(p); } if (benchmarking != null) { - benchmarking.finishedBenchmark(snapshotChunksPerSecondHistory()); + benchmarking.finishedBenchmark(snapshotChunksPerSecondHistory(), rates.overall()); } } @@ -250,7 +253,8 @@ public class IrisPregenerator { IrisLogging.info("Pregen finished: generated=" + Form.f(generated.get()) + " total=" + Form.f(totalChunks.get()) + " failed=" + Form.f(failedCount) - + " duration=" + Form.duration((long) stopwatch.getMilliseconds())); + + " duration=" + Form.duration((long) stopwatch.getMilliseconds()) + + formatRateSummary()); } private void logIncompleteCompletion(PrecisionStopwatch stopwatch) { @@ -263,7 +267,16 @@ public class IrisPregenerator { + " total=" + Form.f(total) + " failed=" + Form.f(failedCount) + " remaining=" + Form.f(remaining) - + " duration=" + Form.duration((long) stopwatch.getMilliseconds())); + + " duration=" + Form.duration((long) stopwatch.getMilliseconds()) + + formatRateSummary()); + } + + private String formatRateSummary() { + return " rates[overall=" + formatRate(rates.overall()) + + ", 10s=" + formatRate(rates.tenSecond()) + + ", 30s=" + formatRate(rates.thirtySecond()) + + ", 60s=" + formatRate(rates.sixtySecond()) + + "] chunks/s"; } private void checkRegions() { @@ -433,6 +446,10 @@ public class IrisPregenerator { return failed.get(); } + public PregenRates getRates() { + return rates; + } + public void pause() { paused.set(true); } @@ -457,7 +474,10 @@ public class IrisPregenerator { public void onChunkGenerated(int x, int z, boolean c) { listener.onChunkGenerated(x, z, c); generated.addAndGet(1); - if (c) cached.addAndGet(1); + if (c) { + cached.addAndGet(1); + lastCachedAtMillis.set(M.ms()); + } } @Override diff --git a/core/src/main/java/art/arcane/iris/core/pregenerator/PregenRateTracker.java b/core/src/main/java/art/arcane/iris/core/pregenerator/PregenRateTracker.java new file mode 100644 index 000000000..25970000e --- /dev/null +++ b/core/src/main/java/art/arcane/iris/core/pregenerator/PregenRateTracker.java @@ -0,0 +1,100 @@ +/* + * Iris is a World Generator for Minecraft Servers + * Copyright (c) 2026 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 . + */ + +package art.arcane.iris.core.pregenerator; + +final class PregenRateTracker { + private static final int CAPACITY = 64; + private static final long TEN_SECONDS_MILLIS = 10_000L; + private static final long THIRTY_SECONDS_MILLIS = 30_000L; + private static final long SIXTY_SECONDS_MILLIS = 60_000L; + + private final long[] timestamps = new long[CAPACITY]; + private final long[] completed = new long[CAPACITY]; + private long startedAtMillis; + private long startedCompleted; + private int next; + private int size; + + PregenRateTracker(long startedAtMillis, long startedCompleted) { + reset(startedAtMillis, startedCompleted); + } + + synchronized void reset(long atMillis, long completedCount) { + startedAtMillis = atMillis; + startedCompleted = completedCount; + next = 0; + size = 0; + append(atMillis, completedCount); + } + + synchronized PregenRates sample(long completedCount, long atMillis) { + int latestIndex = latestIndex(); + long normalizedTime = Math.max(atMillis, timestamps[latestIndex]); + if (normalizedTime == timestamps[latestIndex]) { + completed[latestIndex] = completedCount; + } else { + append(normalizedTime, completedCount); + } + + return new PregenRates( + rate(startedCompleted, startedAtMillis, completedCount, normalizedTime), + windowRate(completedCount, normalizedTime, TEN_SECONDS_MILLIS), + windowRate(completedCount, normalizedTime, THIRTY_SECONDS_MILLIS), + windowRate(completedCount, normalizedTime, SIXTY_SECONDS_MILLIS)); + } + + private double windowRate(long completedCount, long atMillis, long windowMillis) { + long cutoff = atMillis - windowMillis; + int selectedIndex = oldestIndex(); + for (int offset = 0; offset < size; offset++) { + int index = (oldestIndex() + offset) % CAPACITY; + if (timestamps[index] > cutoff) { + break; + } + selectedIndex = index; + } + return rate(completed[selectedIndex], timestamps[selectedIndex], completedCount, atMillis); + } + + private static double rate(long fromCompleted, long fromMillis, long toCompleted, long toMillis) { + long elapsedMillis = toMillis - fromMillis; + if (elapsedMillis <= 0L) { + return 0D; + } + long delta = Math.max(0L, toCompleted - fromCompleted); + return (double) delta * 1_000D / (double) elapsedMillis; + } + + private void append(long atMillis, long completedCount) { + timestamps[next] = atMillis; + completed[next] = completedCount; + next = (next + 1) % CAPACITY; + if (size < CAPACITY) { + size++; + } + } + + private int latestIndex() { + return (next - 1 + CAPACITY) % CAPACITY; + } + + private int oldestIndex() { + return (next - size + CAPACITY) % CAPACITY; + } +} diff --git a/core/src/main/java/art/arcane/iris/core/pregenerator/PregenRates.java b/core/src/main/java/art/arcane/iris/core/pregenerator/PregenRates.java new file mode 100644 index 000000000..9be5906b2 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/core/pregenerator/PregenRates.java @@ -0,0 +1,28 @@ +/* + * Iris is a World Generator for Minecraft Servers + * Copyright (c) 2026 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 . + */ + +package art.arcane.iris.core.pregenerator; + +public record PregenRates( + double overall, + double tenSecond, + double thirtySecond, + double sixtySecond +) { + public static final PregenRates ZERO = new PregenRates(0D, 0D, 0D, 0D); +} diff --git a/core/src/main/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java b/core/src/main/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java index e4c3090e0..ada2c93fc 100644 --- a/core/src/main/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java +++ b/core/src/main/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethod.java @@ -604,11 +604,11 @@ public class AsyncPregenMethod implements PregeneratorMethod { } static int resolvePaperLikeConcurrencyWorkerThreads(int detectedWorkerPoolThreads, int detectedCpuThreads, int configuredWorldGenThreads) { + int provisionedWorkerThreads = Math.max(1, configuredWorldGenThreads); if (detectedWorkerPoolThreads > 0) { - return detectedWorkerPoolThreads; + return Math.max(detectedWorkerPoolThreads, provisionedWorkerThreads); } - int provisionedWorkerThreads = Math.max(1, configuredWorldGenThreads); return Math.max(provisionedWorkerThreads, detectedCpuThreads); } diff --git a/core/src/main/java/art/arcane/iris/core/tools/IrisPackBenchmarking.java b/core/src/main/java/art/arcane/iris/core/tools/IrisPackBenchmarking.java index 10b801b74..ffda6e75d 100644 --- a/core/src/main/java/art/arcane/iris/core/tools/IrisPackBenchmarking.java +++ b/core/src/main/java/art/arcane/iris/core/tools/IrisPackBenchmarking.java @@ -65,7 +65,7 @@ public class IrisPackBenchmarking { } - public void finishedBenchmark(KList cps) { + public void finishedBenchmark(KList cps, double overallCps) { try { String time = Form.duration((long) stopwatch.getMilliseconds()); World benchmarkWorld = benchmarkWorld(); @@ -76,7 +76,7 @@ public class IrisPackBenchmarking { IrisLogging.info("-----------------"); IrisLogging.info("Results:"); IrisLogging.info("- Total time: " + time); - IrisLogging.info("- Average CPS: " + calculateAverage(cps)); + IrisLogging.info("- Average CPS: " + overallCps); IrisLogging.info(" - Median CPS: " + calculateMedian(cps)); IrisLogging.info(" - Highest CPS: " + findHighest(cps)); IrisLogging.info(" - Lowest CPS: " + findLowest(cps)); @@ -98,7 +98,7 @@ public class IrisPackBenchmarking { writer.write("- " + metrics); writer.write("Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n"); writer.write("- Total time: " + time + "\n"); - writer.write("- Average CPS: " + calculateAverage(cps) + "\n"); + writer.write("- Average CPS: " + overallCps + "\n"); writer.write(" - Median CPS: " + calculateMedian(cps) + "\n"); writer.write(" - Highest CPS: " + findHighest(cps) + "\n"); writer.write(" - Lowest CPS: " + findLowest(cps) + "\n"); @@ -173,15 +173,10 @@ public class IrisPackBenchmarking { return WorldIdentity.resolve(IrisWorldStorage.keyFromName("benchmark")).orElse(null); } - private double calculateAverage(KList list) { - double sum = 0; - for (int num : list) { - sum += num; - } - return sum / list.size(); - } - private double calculateMedian(KList list) { + if (list.isEmpty()) { + return 0D; + } KList sorted = new KList<>(list); Collections.sort(sorted); int middle = sorted.size() / 2; @@ -194,10 +189,10 @@ public class IrisPackBenchmarking { } private int findLowest(KList list) { - return Collections.min(list); + return list.isEmpty() ? 0 : Collections.min(list); } private int findHighest(KList list) { - return Collections.max(list); + return list.isEmpty() ? 0 : Collections.max(list); } } diff --git a/core/src/main/java/art/arcane/iris/util/project/noise/CloverNoise.java b/core/src/main/java/art/arcane/iris/util/project/noise/CloverNoise.java index 1f37697f9..170cf6d5c 100644 --- a/core/src/main/java/art/arcane/iris/util/project/noise/CloverNoise.java +++ b/core/src/main/java/art/arcane/iris/util/project/noise/CloverNoise.java @@ -111,8 +111,12 @@ public class CloverNoise implements NoiseGenerator { private Vector2 offset(Vector2 position) { double hash = hash(position); double scale = Math.floor(hash * 50 + 1) / 100; - Vector2 offset = new Vector2(Math.sin(hash * Math.PI * 100), Math.cos(hash * Math.PI * 100)).mult(scale).add(0.5); - return position.add(offset.mult(POINT_SPREAD * 2)).add(0.5 - POINT_SPREAD); + double angle = hash * Math.PI * 100; + double offsetX = Math.sin(angle) * scale + 0.5; + double offsetY = Math.cos(angle) * scale + 0.5; + return new Vector2( + position.x + offsetX * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD), + position.y + offsetY * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD)); } /** @@ -205,9 +209,9 @@ public class CloverNoise implements NoiseGenerator { w *= s; u *= s; - double fv = hash(f.floor()); - double gv = hash(g.floor()); - double hv = hash(h.floor()); + double fv = hash(f); + double gv = hash(g); + double hv = hash(h); return u * fv + v * gv + w * hv; } @@ -409,9 +413,13 @@ public class CloverNoise implements NoiseGenerator { } private double hash(Vector3 position) { - long x = (long) Math.floor(position.getX()); - long y = (long) Math.floor(position.getY()); - long z = (long) Math.floor(position.getZ()); + return hash(position.x, position.y, position.z); + } + + private double hash(double positionX, double positionY, double positionZ) { + long x = (long) Math.floor(positionX); + long y = (long) Math.floor(positionY); + long z = (long) Math.floor(positionZ); long hash = seed; hash ^= mix(x + 0x9E3779B97F4A7C15L); hash ^= mix(y + 0xC2B2AE3D27D4EB4FL); @@ -426,25 +434,46 @@ public class CloverNoise implements NoiseGenerator { } private Vector3 offset(Vector3 position) { - double hash = hash(position); + return offset(position.x, position.y, position.z); + } + + private Vector3 offset(Vector3 position, double xOffset, double yOffset, double zOffset) { + return offset(position.x + xOffset, position.y + yOffset, position.z + zOffset); + } + + private Vector3 offset(double positionX, double positionY, double positionZ) { + double hash = hash(positionX, positionY, positionZ); double theta = hash * Math.PI * 2000; double height = (((Math.floor(hash * 1000) + 0.5) / 100) % 1 - 0.5) * Math.PI / 2; double layer = Math.floor(hash * 10 + 1) / 10; - Vector3 offset = new Vector3(Math.sin(theta) * Math.cos(height), Math.sin(height), Math.cos(theta) * Math.cos(height)).mult(layer).add(0.5); - return position.add(offset.mult(POINT_SPREAD * 2).add(0.5 - POINT_SPREAD)); + double cosHeight = Math.cos(height); + double offsetX = Math.sin(theta) * cosHeight * layer + 0.5; + double offsetY = Math.sin(height) * layer + 0.5; + double offsetZ = Math.cos(theta) * cosHeight * layer + 0.5; + return new Vector3( + positionX + (offsetX * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD)), + positionY + (offsetY * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD)), + positionZ + (offsetZ * (POINT_SPREAD * 2) + (0.5 - POINT_SPREAD))); } - private boolean boundary(Vector3 p, Vector3 c_00, Vector3 c_10, Vector3 c_20, Vector3 c_01, Vector3 c_11, Vector3 c_21, Vector3 c_02, Vector3 c_12, Vector3 c_22) { - Vector2 d_p_c11 = p.yx().sub(c_11.yx()); - Vector2 m_p_c11 = d_p_c11.mult(c_11.xy()); + private boolean boundary(int permutation, Vector3 p, Vector3 c_00, Vector3 c_10, Vector3 c_20, Vector3 c_01, Vector3 c_11, Vector3 c_21, Vector3 c_02, Vector3 c_12, Vector3 c_22) { + double px = permutedX(p, permutation); + double py = permutedY(p, permutation); + double pz = permutedZ(p, permutation); + double c11x = permutedX(c_11, permutation); + double c11y = permutedY(c_11, permutation); + double deltaX = py - c11y; + double deltaY = px - c11x; + double multipliedX = deltaX * c11x; + double multipliedY = deltaY * c11y; - double side_nx = m_p_c11.sub(d_p_c11.mult(c_01.xy())).ymx(); - double side_px = m_p_c11.sub(d_p_c11.mult(c_21.xy())).ymx(); + double side_nx = side(multipliedX, multipliedY, deltaX, deltaY, c_01, permutation); + double side_px = side(multipliedX, multipliedY, deltaX, deltaY, c_21, permutation); Vector3 a, b, c, d; - if (side_nx < 0 && p.x < c_11.x || side_px > 0 && p.x >= c_11.x) { - double side_py = m_p_c11.sub(d_p_c11.mult(c_12.xy())).ymx(); + if (side_nx < 0 && px < c11x || side_px > 0 && px >= c11x) { + double side_py = side(multipliedX, multipliedY, deltaX, deltaY, c_12, permutation); if (side_py > 0.) { a = c_01; @@ -458,7 +487,7 @@ public class CloverNoise implements NoiseGenerator { d = c_21; } } else { - double side_ny = m_p_c11.sub(d_p_c11.mult(c_10.xy())).ymx(); + double side_ny = side(multipliedX, multipliedY, deltaX, deltaY, c_10, permutation); if (side_ny > 0.) { a = c_10; @@ -477,22 +506,56 @@ public class CloverNoise implements NoiseGenerator { Vector3 g = c; Vector3 h = d; - Vector3 ac = a.sub(c); - Vector3 pa = p.sub(a); + double acx = permutedX(a, permutation) - permutedX(c, permutation); + double acy = permutedY(a, permutation) - permutedY(c, permutation); + double pax = px - permutedX(a, permutation); + double pay = py - permutedY(a, permutation); - if (pa.x * ac.y - pa.y * ac.x > 0) { + if (pax * acy - pay * acx > 0) { h = b; } - Vector2 bc_v0 = g.xy().sub(f.xy()); - Vector2 bc_v1 = h.xy().sub(f.xy()); - Vector2 bc_v2 = p.xy().sub(f.xy()); - double den = 1 / (bc_v0.x * bc_v1.y - bc_v1.x * bc_v0.y); - double v = (bc_v2.x * bc_v1.y - bc_v1.x * bc_v2.y) * den; - double w = (bc_v0.x * bc_v2.y - bc_v2.x * bc_v0.y) * den; + double fx = permutedX(f, permutation); + double fy = permutedY(f, permutation); + double v0x = permutedX(g, permutation) - fx; + double v0y = permutedY(g, permutation) - fy; + double v1x = permutedX(h, permutation) - fx; + double v1y = permutedY(h, permutation) - fy; + double v2x = px - fx; + double v2y = py - fy; + double den = 1 / (v0x * v1y - v1x * v0y); + double v = (v2x * v1y - v1x * v2y) * den; + double w = (v0x * v2y - v2x * v0y) * den; double u = 1 - v - w; - return p.z < u * f.z + v * g.z + w * h.z; + return pz < u * permutedZ(f, permutation) + + v * permutedZ(g, permutation) + + w * permutedZ(h, permutation); + } + + private static double side(double multipliedX, double multipliedY, double deltaX, double deltaY, Vector3 candidate, int permutation) { + double x = multipliedX - deltaX * permutedX(candidate, permutation); + double y = multipliedY - deltaY * permutedY(candidate, permutation); + return y - x; + } + + private static double permutedX(Vector3 vector, int permutation) { + return switch (permutation) { + case 1 -> vector.y; + default -> vector.x; + }; + } + + private static double permutedY(Vector3 vector, int permutation) { + return permutation == 0 ? vector.y : vector.z; + } + + private static double permutedZ(Vector3 vector, int permutation) { + return switch (permutation) { + case 1 -> vector.x; + case 2 -> vector.y; + default -> vector.z; + }; } /** @@ -505,35 +568,35 @@ public class CloverNoise implements NoiseGenerator { Vector3 p_floor = p.floor(); Vector3 c_111 = offset(p_floor); - Vector3 c_100 = offset(p_floor.add(0, -1, -1)); - Vector3 c_010 = offset(p_floor.add(-1, 0, -1)); - Vector3 c_110 = offset(p_floor.add(0, 0, -1)); - Vector3 c_210 = offset(p_floor.add(1, 0, -1)); - Vector3 c_120 = offset(p_floor.add(0, 1, -1)); - Vector3 c_001 = offset(p_floor.add(-1, -1, 0)); - Vector3 c_101 = offset(p_floor.add(0, -1, 0)); - Vector3 c_201 = offset(p_floor.add(1, -1, 0)); - Vector3 c_011 = offset(p_floor.add(-1, 0, 0)); - Vector3 c_211 = offset(p_floor.add(1, 0, 0)); - Vector3 c_021 = offset(p_floor.add(-1, 1, 0)); - Vector3 c_121 = offset(p_floor.add(0, 1, 0)); - Vector3 c_221 = offset(p_floor.add(1, 1, 0)); - Vector3 c_102 = offset(p_floor.add(0, -1, 1)); - Vector3 c_012 = offset(p_floor.add(-1, 0, 1)); - Vector3 c_112 = offset(p_floor.add(0, 0, 1)); - Vector3 c_212 = offset(p_floor.add(1, 0, 1)); - Vector3 c_122 = offset(p_floor.add(0, 1, 1)); + Vector3 c_100 = offset(p_floor, 0, -1, -1); + Vector3 c_010 = offset(p_floor, -1, 0, -1); + Vector3 c_110 = offset(p_floor, 0, 0, -1); + Vector3 c_210 = offset(p_floor, 1, 0, -1); + Vector3 c_120 = offset(p_floor, 0, 1, -1); + Vector3 c_001 = offset(p_floor, -1, -1, 0); + Vector3 c_101 = offset(p_floor, 0, -1, 0); + Vector3 c_201 = offset(p_floor, 1, -1, 0); + Vector3 c_011 = offset(p_floor, -1, 0, 0); + Vector3 c_211 = offset(p_floor, 1, 0, 0); + Vector3 c_021 = offset(p_floor, -1, 1, 0); + Vector3 c_121 = offset(p_floor, 0, 1, 0); + Vector3 c_221 = offset(p_floor, 1, 1, 0); + Vector3 c_102 = offset(p_floor, 0, -1, 1); + Vector3 c_012 = offset(p_floor, -1, 0, 1); + Vector3 c_112 = offset(p_floor, 0, 0, 1); + Vector3 c_212 = offset(p_floor, 1, 0, 1); + Vector3 c_122 = offset(p_floor, 0, 1, 1); - boolean x_bound = boundary(p.yzx(), c_100.yzx(), c_110.yzx(), c_120.yzx(), c_101.yzx(), c_111.yzx(), c_121.yzx(), c_102.yzx(), c_112.yzx(), c_122.yzx()); - boolean y_bound = boundary(p.xzy(), c_010.xzy(), c_110.xzy(), c_210.xzy(), c_011.xzy(), c_111.xzy(), c_211.xzy(), c_012.xzy(), c_112.xzy(), c_212.xzy()); - boolean z_bound = boundary(p, c_001, c_101, c_201, c_011, c_111, c_211, c_021, c_121, c_221); + boolean x_bound = boundary(1, p, c_100, c_110, c_120, c_101, c_111, c_121, c_102, c_112, c_122); + boolean y_bound = boundary(2, p, c_010, c_110, c_210, c_011, c_111, c_211, c_012, c_112, c_212); + boolean z_bound = boundary(0, p, c_001, c_101, c_201, c_011, c_111, c_211, c_021, c_121, c_221); Vector3 a, b, c, d, e, f, g, h; if (x_bound) { if (y_bound) { if (z_bound) { - a = offset(p_floor.add(-1, -1, -1)); + a = offset(p_floor, -1, -1, -1); b = c_001; c = c_010; d = c_011; @@ -543,7 +606,7 @@ public class CloverNoise implements NoiseGenerator { h = c_111; } else { a = c_001; - b = offset(p_floor.add(-1, -1, 1)); + b = offset(p_floor, -1, -1, 1); c = c_011; d = c_012; e = c_101; @@ -555,7 +618,7 @@ public class CloverNoise implements NoiseGenerator { if (z_bound) { a = c_010; b = c_011; - c = offset(p_floor.add(-1, 1, -1)); + c = offset(p_floor, -1, 1, -1); d = c_021; e = c_110; f = c_111; @@ -565,7 +628,7 @@ public class CloverNoise implements NoiseGenerator { a = c_011; b = c_012; c = c_021; - d = offset(p_floor.add(-1, 1, 1)); + d = offset(p_floor, -1, 1, 1); e = c_111; f = c_112; g = c_121; @@ -579,7 +642,7 @@ public class CloverNoise implements NoiseGenerator { b = c_101; c = c_110; d = c_111; - e = offset(p_floor.add(1, -1, -1)); + e = offset(p_floor, 1, -1, -1); f = c_201; g = c_210; h = c_211; @@ -589,7 +652,7 @@ public class CloverNoise implements NoiseGenerator { c = c_111; d = c_112; e = c_201; - f = offset(p_floor.add(1, -1, 1)); + f = offset(p_floor, 1, -1, 1); g = c_211; h = c_212; } @@ -601,7 +664,7 @@ public class CloverNoise implements NoiseGenerator { d = c_121; e = c_210; f = c_211; - g = offset(p_floor.add(1, 1, -1)); + g = offset(p_floor, 1, 1, -1); h = c_221; } else { a = c_111; @@ -611,20 +674,17 @@ public class CloverNoise implements NoiseGenerator { e = c_211; f = c_212; g = c_221; - h = offset(p_floor.add(1, 1, 1)); + h = offset(p_floor, 1, 1, 1); } } } - Vector3 ah = a.sub(h); - Vector3 pa = p.sub(a); - - double plane_b = ah.cross(b.sub(h)).mult(pa).xpypz(); - double plane_c = ah.cross(c.sub(h)).mult(pa).xpypz(); - double plane_d = ah.cross(d.sub(h)).mult(pa).xpypz(); - double plane_e = ah.cross(e.sub(h)).mult(pa).xpypz(); - double plane_f = ah.cross(f.sub(h)).mult(pa).xpypz(); - double plane_g = ah.cross(g.sub(h)).mult(pa).xpypz(); + double plane_b = dotDifferenceCrossDifferences(p, a, a, h, b, h); + double plane_c = dotDifferenceCrossDifferences(p, a, a, h, c, h); + double plane_d = dotDifferenceCrossDifferences(p, a, a, h, d, h); + double plane_e = dotDifferenceCrossDifferences(p, a, a, h, e, h); + double plane_f = dotDifferenceCrossDifferences(p, a, a, h, f, h); + double plane_g = dotDifferenceCrossDifferences(p, a, a, h, g, h); Vector3 i, j, k, l; @@ -651,21 +711,11 @@ public class CloverNoise implements NoiseGenerator { l = b; } - Vector3 bc_ap = p.sub(i); - Vector3 bc_bp = p.sub(j); - - Vector3 bc_ab = j.sub(i); - Vector3 bc_ac = k.sub(i); - Vector3 bc_ad = l.sub(i); - - Vector3 bc_bc = k.sub(j); - Vector3 bc_bd = l.sub(j); - - double bc_va6 = bc_bp.mult(bc_bd.cross(bc_bc)).xpypz(); - double bc_vb6 = bc_ap.mult(bc_ac.cross(bc_ad)).xpypz(); - double bc_vc6 = bc_ap.mult(bc_ad.cross(bc_ab)).xpypz(); - double bc_vd6 = bc_ap.mult(bc_ab.cross(bc_ac)).xpypz(); - double bc_v6 = 1 / bc_ab.mult(bc_ac.cross(bc_ad)).xpypz(); + double bc_va6 = dotDifferenceCrossDifferences(p, j, l, j, k, j); + double bc_vb6 = dotDifferenceCrossDifferences(p, i, k, i, l, i); + double bc_vc6 = dotDifferenceCrossDifferences(p, i, l, i, j, i); + double bc_vd6 = dotDifferenceCrossDifferences(p, i, j, i, k, i); + double bc_v6 = 1 / dotDifferenceCrossDifferences(j, i, k, i, l, i); double v = bc_va6 * bc_v6; double w = bc_vb6 * bc_v6; @@ -682,14 +732,37 @@ public class CloverNoise implements NoiseGenerator { fiw /= s; fit /= s; - double iv = hash(i.floor()); - double jv = hash(j.floor()); - double kv = hash(k.floor()); - double lv = hash(l.floor()); + double iv = hash(i); + double jv = hash(j); + double kv = hash(k); + double lv = hash(l); return fiv * iv + fiw * jv + fit * kv + fiu * lv; } + private static double dotDifferenceCrossDifferences( + Vector3 dotValue, + Vector3 dotOrigin, + Vector3 crossLeftValue, + Vector3 crossLeftOrigin, + Vector3 crossRightValue, + Vector3 crossRightOrigin + ) { + double dotX = dotValue.x - dotOrigin.x; + double dotY = dotValue.y - dotOrigin.y; + double dotZ = dotValue.z - dotOrigin.z; + double leftX = crossLeftValue.x - crossLeftOrigin.x; + double leftY = crossLeftValue.y - crossLeftOrigin.y; + double leftZ = crossLeftValue.z - crossLeftOrigin.z; + double rightX = crossRightValue.x - crossRightOrigin.x; + double rightY = crossRightValue.y - crossRightOrigin.y; + double rightZ = crossRightValue.z - crossRightOrigin.z; + double crossX = leftY * rightZ - leftZ * rightY; + double crossY = leftZ * rightX - leftX * rightZ; + double crossZ = leftX * rightY - leftY * rightX; + return dotX * crossX + dotY * crossY + dotZ * crossZ; + } + /** * Generates 3D Clover Noise at a specific point. * @@ -917,7 +990,7 @@ public class CloverNoise implements NoiseGenerator { } public Vector2 add(double xa, double ya) { - return add(new Vector2(xa, ya)); + return new Vector2(x + xa, y + ya); } public Vector2 add(double a) { @@ -925,11 +998,11 @@ public class CloverNoise implements NoiseGenerator { } public Vector2 sub(Vector2 s) { - return add(s.negate()); + return new Vector2(x - s.x, y - s.y); } public Vector2 sub(double xs, double ys) { - return sub(new Vector2(xs, ys)); + return new Vector2(x - xs, y - ys); } public Vector2 sub(double s) { @@ -941,7 +1014,7 @@ public class CloverNoise implements NoiseGenerator { } public Vector2 mult(double xm, double ym) { - return mult(new Vector2(xm, ym)); + return new Vector2(x * xm, y * ym); } public Vector2 mult(double m) { @@ -1029,7 +1102,7 @@ public class CloverNoise implements NoiseGenerator { } public Vector3 add(double xa, double ya, double za) { - return add(new Vector3(xa, ya, za)); + return new Vector3(x + xa, y + ya, z + za); } public Vector3 add(double a) { @@ -1037,11 +1110,11 @@ public class CloverNoise implements NoiseGenerator { } public Vector3 sub(Vector3 s) { - return add(s.negate()); + return new Vector3(x - s.x, y - s.y, z - s.z); } public Vector3 sub(double xs, double ys, double zs) { - return sub(new Vector3(xs, ys, zs)); + return new Vector3(x - xs, y - ys, z - zs); } public Vector3 sub(double s) { @@ -1053,7 +1126,7 @@ public class CloverNoise implements NoiseGenerator { } public Vector3 mult(double mx, double my, double mz) { - return mult(new Vector3(mx, my, mz)); + return new Vector3(x * mx, y * my, z * mz); } public Vector3 mult(double m) { diff --git a/core/src/main/resources/languages/de_DE.json b/core/src/main/resources/languages/de_DE.json index 458a16961..dca490f37 100644 --- a/core/src/main/resources/languages/de_DE.json +++ b/core/src/main/resources/languages/de_DE.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eKeine aktiven Vorgenerierungsaufgaben zum Pausieren oder Fortsetzen.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eKeine aktive Vorgenerationsaufgabe.", "iris.bukkit.commandpregen.pregen": "§aVorgenerierung §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aGeschwindigkeit: §6{value}/s§a ETA: §6{value2}§a Verstrichen: §6{value3}§a Methode: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aGeschwindigkeit: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cDer Pack für Dimension {value} konnte nicht aufgelöst werden", "iris.bukkit.commandstructure.wrote_structure_index": "§aStrukturindex geschrieben: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cDer Pack für Dimension {value} konnte nicht aufgelöst werden", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " fehlgeschlagen {failed}", "iris.runtime.pregen.status.context": "Dimension {dimension} · Methode {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Chunks {generated}/{total} · Geschwindigkeit {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Chunks {generated}/{total} · Geschwindigkeit {speed}/s · Fehlgeschlagen {failed}", + "iris.runtime.pregen.status.chunks": "Chunks {generated}/{total} · Geschwindigkeit overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Chunks {generated}/{total} · Geschwindigkeit overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Verstrichen {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Verstrichen {elapsed} · PAUSIERT", "iris.runtime.pregen.button.pause": "Pause/Wiederaufnahme", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "pausiert {generated} von {total} ({percent} abgeschlossen)", "iris.desktop.pregen.progress_saving": "Speichern... {generated} von {total} ({percent} abgeschlossen)", "iris.desktop.pregen.progress_generating": "{generated} von {total} werden generiert ({percent} abgeschlossen)", - "iris.desktop.pregen.speed": "Geschwindigkeit: {chunksPerSecond} Chunks/s, {regionsPerMinute} Regionen/m, {chunksPerMinute} Chunks/m", - "iris.desktop.pregen.speed_cached": "Geschwindigkeit: zwischengespeichert {chunksPerSecond} Chunks/s, {regionsPerMinute} Regionen/m, {chunksPerMinute} Chunks/m", + "iris.desktop.pregen.speed": "Geschwindigkeit: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Geschwindigkeit: zwischengespeichert {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} verbleibend ({elapsed} abgelaufen)", "iris.desktop.pregen.method": "Erzeugungsmethode: {method}", "iris.desktop.pregen.memory": "Speicher: {used} ({usage}) Druck: {pressure}/s", diff --git a/core/src/main/resources/languages/es_ES.json b/core/src/main/resources/languages/es_ES.json index 21a836f9d..365561766 100644 --- a/core/src/main/resources/languages/es_ES.json +++ b/core/src/main/resources/languages/es_ES.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eNo hay tareas de pregeneración activas que pausar o reanudar.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eNo hay ninguna tarea de pregeneración activa.", "iris.bukkit.commandpregen.pregen": "§aPregen §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVelocidad: §6{value}/s§a ETA: §6{value2}§a Transcurrido: §6{value3}§a Método: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVelocidad: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cNo se pudo resolver el pack de la dimensión {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aÍndice de estructuras escrito: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cNo se pudo resolver el pack de la dimensión {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " fallidos {failed}", "iris.runtime.pregen.status.context": "Dimensión {dimension} · Método {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Chunks {generated}/{total} · Velocidad {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Chunks {generated}/{total} · Velocidad {speed}/s · Fallidos {failed}", + "iris.runtime.pregen.status.chunks": "Chunks {generated}/{total} · Velocidad overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Chunks {generated}/{total} · Velocidad overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Transcurrido {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Transcurrido {elapsed} · PAUSADO", "iris.runtime.pregen.button.pause": "Pausar/Reanudar", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "PAUSADO {generated} de {total} ({percent} completado)", "iris.desktop.pregen.progress_saving": "Guardando... {generated} de {total} ({percent} completado)", "iris.desktop.pregen.progress_generating": "Generando {generated} de {total} ({percent} completado)", - "iris.desktop.pregen.speed": "Velocidad: {chunksPerSecond} chunks/s, {regionsPerMinute} regiones/m, {chunksPerMinute} chunks/m", - "iris.desktop.pregen.speed_cached": "Velocidad: en caché {chunksPerSecond} chunks/s, {regionsPerMinute} regiones/m, {chunksPerMinute} chunks/m", + "iris.desktop.pregen.speed": "Velocidad: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Velocidad: en caché {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} restantes ({elapsed} transcurridos)", "iris.desktop.pregen.method": "Método de generación: {method}", "iris.desktop.pregen.memory": "Memoria: {used} ({usage}) Presión: {pressure}/s", diff --git a/core/src/main/resources/languages/fi_FI.json b/core/src/main/resources/languages/fi_FI.json index 4ff3f73d4..0576b6ba4 100644 --- a/core/src/main/resources/languages/fi_FI.json +++ b/core/src/main/resources/languages/fi_FI.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eEi aktiivisia esisukupolven tehtäviä tauon/tauon pysäyttämiseksi.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eEi aktiivista esisukupolven tehtävää.", "iris.bukkit.commandpregen.pregen": "§aPregen. §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aNopeus: §6{value}/s§a ETA: §6{value2}§a kuoritut: §6{value3}§a Menetelmä: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aNopeus: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cPakkausta ei voitu ratkaista mitan vuoksi {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aKirjoitetun rakenteen indeksi: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cPakkausta ei voitu ratkaista mitan vuoksi {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " epäonnistui {failed}", "iris.runtime.pregen.status.context": "Mitat {dimension} · Menetelmä {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Palat {generated}/{total} · Nopeus {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Palat {generated}/{total} · Nopeus {speed}/s · Ei onnistunut {failed}", + "iris.runtime.pregen.status.chunks": "Palat {generated}/{total} · Nopeus overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Palat {generated}/{total} · Nopeus overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Elaped {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Elaped {elapsed} · keskeytetty", "iris.runtime.pregen.button.pause": "Keskeytä/Poista", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "keskeytetty {generated} / {total} ({percent} täydellinen)", "iris.desktop.pregen.progress_saving": "Tallennus... {generated} / {total} ({percent} täydellinen)", "iris.desktop.pregen.progress_generating": "Luodaan {generated} / {total} ({percent} täydellinen)", - "iris.desktop.pregen.speed": "Nopeus: {chunksPerSecond} chunkia/s, {regionsPerMinute} alueet/m {chunksPerMinute} chunkia/m", - "iris.desktop.pregen.speed_cached": "Nopeus: välimuisti {chunksPerSecond} chunkia/s, {regionsPerMinute} alueet/m {chunksPerMinute} chunkia/m", + "iris.desktop.pregen.speed": "Nopeus: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Nopeus: välimuisti {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} jäljellä ({elapsed} Kulunut)", "iris.desktop.pregen.method": "Generointimenetelmä: {method}", "iris.desktop.pregen.memory": "Muisti: {used} ({usage}) Paine: {pressure}/s", diff --git a/core/src/main/resources/languages/fr_FR.json b/core/src/main/resources/languages/fr_FR.json index 7bf9711d5..b01c327dc 100644 --- a/core/src/main/resources/languages/fr_FR.json +++ b/core/src/main/resources/languages/fr_FR.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eAucune tâche de prégénération active à suspendre ou reprendre.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eAucune tâche de prégénération active.", "iris.bukkit.commandpregen.pregen": "§aPregen §6{world}§a : §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVitesse : §6{value}/s§a ETA : §6{value2}§a Écoulé : §6{value3}§a Méthode : §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVitesse : §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cImpossible de résoudre le pack de la dimension {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aIndex des structures écrit : §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cImpossible de résoudre le pack de la dimension {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " échecs {failed}", "iris.runtime.pregen.status.context": "Dimension {dimension} · Méthode {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Chunks {generated}/{total} · Vitesse {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Chunks {generated}/{total} · Vitesse {speed}/s · Échecs {failed}", + "iris.runtime.pregen.status.chunks": "Chunks {generated}/{total} · Vitesse overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Chunks {generated}/{total} · Vitesse overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Écoulé {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Écoulé {elapsed} · EN PAUSE", "iris.runtime.pregen.button.pause": "Pause/Reprise", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "EN PAUSE {generated} sur {total} ({percent} terminés)", "iris.desktop.pregen.progress_saving": "Enregistrement... {generated} sur {total} ({percent} terminés)", "iris.desktop.pregen.progress_generating": "Génération de {generated} sur {total} ({percent} terminés)", - "iris.desktop.pregen.speed": "Vitesse : {chunksPerSecond} chunks/s, {regionsPerMinute} régions/m, {chunksPerMinute} chunks/m", - "iris.desktop.pregen.speed_cached": "Vitesse : cache {chunksPerSecond} chunks/s, {regionsPerMinute} régions/m, {chunksPerMinute} chunks/m", + "iris.desktop.pregen.speed": "Vitesse : {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Vitesse : cache {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} restantes ({elapsed} écoulées)", "iris.desktop.pregen.method": "Méthode de génération : {method}", "iris.desktop.pregen.memory": "Mémoire : {used} ({usage}) Pression : {pressure}/s", diff --git a/core/src/main/resources/languages/he_IL.json b/core/src/main/resources/languages/he_IL.json index c722522a6..b9a963927 100644 --- a/core/src/main/resources/languages/he_IL.json +++ b/core/src/main/resources/languages/he_IL.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eאין משימות קדם-דור פעיל להפסקה/לא לשימוש.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eאין משימה חדשנית פעילה.", "iris.bukkit.commandpregen.pregen": "§aהפרסוגן §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aמהירות: §6{value}/s§a ETA: §6{value2}§a מת: §6{value3}§a שיטה: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aמהירות: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cלא יכול לפתור את החבילה לממד {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aמדד מבנה נכתב: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cלא יכול לפתור את החבילה לממד {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " נכשל {failed}", "iris.runtime.pregen.status.context": "המימד {dimension} • שיטת {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "צ'אנק {generated}/{total} מהירות {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "צ'אנק {generated}/{total} מהירות {speed}/s • נכשל {failed}", + "iris.runtime.pregen.status.chunks": "צ'אנק {generated}/{total} מהירות overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "צ'אנק {generated}/{total} מהירות overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} • Elapse {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} • Elapse {elapsed} · מושהה", "iris.runtime.pregen.button.pause": "המונחים: המשך", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "מושהה {generated} של {total} ({percent} שלם)", "iris.desktop.pregen.progress_saving": "חיסכון... {generated} של {total} ({percent} שלם)", "iris.desktop.pregen.progress_generating": "ייצור {generated} של {total} ({percent} שלם)", - "iris.desktop.pregen.speed": "מהירות: {chunksPerSecond} צ'אנקים/s, {regionsPerMinute} אזורים/m, {chunksPerMinute} צ'אנקים/m", - "iris.desktop.pregen.speed_cached": "מהירות: במטמון {chunksPerSecond} צ'אנקים/s, {regionsPerMinute} אזורים/m, {chunksPerMinute} צ'אנקים/m", + "iris.desktop.pregen.speed": "מהירות: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "מהירות: במטמון {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} הנותרים ({elapsed} מת)", "iris.desktop.pregen.method": "שיטת דור: {method}", "iris.desktop.pregen.memory": "זיכרון:{used} ({usage}לחץ:{pressure}/s", diff --git a/core/src/main/resources/languages/it_IT.json b/core/src/main/resources/languages/it_IT.json index a08cd4565..1871dd82b 100644 --- a/core/src/main/resources/languages/it_IT.json +++ b/core/src/main/resources/languages/it_IT.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eNessuna attività di pregenerazione da mettere in pausa o riprendere.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eNessun compito di pregenerazione attivo.", "iris.bukkit.commandpregen.pregen": "§aPregenerazione §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVelocità: §6{value}/s§a ETA: §6{value2}§a Trascorso: §6{value3}§a Metodo: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVelocità: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cImpossibile risolvere il pack della dimensione {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aIndice delle strutture scritto in: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cImpossibile risolvere il pack della dimensione {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " non riusciti {failed}", "iris.runtime.pregen.status.context": "Dimensione {dimension} · Metodo {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Chunk {generated}/{total} · Velocità {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Chunk {generated}/{total} · Velocità {speed}/s · Non riusciti {failed}", + "iris.runtime.pregen.status.chunks": "Chunk {generated}/{total} · Velocità overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Chunk {generated}/{total} · Velocità overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Trascorso {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Trascorso {elapsed} · IN PAUSA", "iris.runtime.pregen.button.pause": "Pausa/Riprendi", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "in pausa {generated} di {total} ({percent} completo)", "iris.desktop.pregen.progress_saving": "Salvataggio... {generated} di {total} ({percent} completato)", "iris.desktop.pregen.progress_generating": "Generazione {generated} di {total} ({percent} completo)", - "iris.desktop.pregen.speed": "Velocità: {chunksPerSecond} chunk/s, {regionsPerMinute} regioni/m, {chunksPerMinute} chunk/m", - "iris.desktop.pregen.speed_cached": "Velocità: cache {chunksPerSecond} chunk/s, {regionsPerMinute} regioni/m, {chunksPerMinute} chunk/m", + "iris.desktop.pregen.speed": "Velocità: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Velocità: cache {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} rimanenti ({elapsed} trascorso)", "iris.desktop.pregen.method": "Metodo di generazione: {method}", "iris.desktop.pregen.memory": "Memoria: {used} ({usage}) Pressione: {pressure}/s", diff --git a/core/src/main/resources/languages/ja-JP.json b/core/src/main/resources/languages/ja-JP.json index 200a197c2..be3cae3e7 100644 --- a/core/src/main/resources/languages/ja-JP.json +++ b/core/src/main/resources/languages/ja-JP.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§e一時停止を切り替えられる実行中の事前生成タスクはありません。", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§e実行中の事前生成タスクはありません。", "iris.bukkit.commandpregen.pregen": "§a事前生成 §6{world}§a: §6{value}/{value2}§a(§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a速度: §6{value}/s§a ETA: §6{value2}§a 経過時間: §6{value3}§a 方式: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a速度: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cディメンション {value} のパックを解決できませんでした", "iris.bukkit.commandstructure.wrote_structure_index": "§a構造物インデックスを書き込みました: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cディメンション {value} のパックを解決できませんでした", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " 失敗 {failed}", "iris.runtime.pregen.status.context": "ディメンション {dimension} · 方式 {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "チャンク {generated}/{total} · 速度 {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "チャンク {generated}/{total} · 速度 {speed}/s · 失敗 {failed}", + "iris.runtime.pregen.status.chunks": "チャンク {generated}/{total} · 速度 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "チャンク {generated}/{total} · 速度 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · 経過時間 {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · 経過時間 {elapsed} · 一時停止中", "iris.runtime.pregen.button.pause": "一時停止/再開", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "一時停止中 {generated}/{total}({percent} 完了)", "iris.desktop.pregen.progress_saving": "保存中... {generated}/{total}({percent} 完了)", "iris.desktop.pregen.progress_generating": "生成中 {generated}/{total}({percent} 完了)", - "iris.desktop.pregen.speed": "速度: {chunksPerSecond} チャンク/s、{regionsPerMinute} リージョン/m、{chunksPerMinute} チャンク/m", - "iris.desktop.pregen.speed_cached": "速度: キャッシュ {chunksPerSecond} チャンク/s、{regionsPerMinute} リージョン/m、{chunksPerMinute} チャンク/m", + "iris.desktop.pregen.speed": "速度: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "速度: キャッシュ {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "残り {remaining}(経過 {elapsed})", "iris.desktop.pregen.method": "生成方法: {method}", "iris.desktop.pregen.memory": "メモリ: {used}({usage})負荷: {pressure}/s", diff --git a/core/src/main/resources/languages/ko_KR.json b/core/src/main/resources/languages/ko_KR.json index 36a4c4440..c97277c6c 100644 --- a/core/src/main/resources/languages/ko_KR.json +++ b/core/src/main/resources/languages/ko_KR.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§ePX/재개에 능동적 전 세대 작업.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§e활동적인 전세대 업무 없음.", "iris.bukkit.commandpregen.pregen": "§a사전 생성 §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a속도: §6{value}/s§a ETA: §6{value2}§a 탈출 : §6{value3}§a 방법: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a속도: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§c차원을 위한 팩을 해결할 수 없습니다 {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§a기록함 구조 색인: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§c차원을 위한 팩을 해결할 수 없습니다 {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " 실패한 {failed}", "iris.runtime.pregen.status.context": "크기 : {dimension} · 방법 {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "주 메뉴 {generated}/{total} · 속도 {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "주 메뉴 {generated}/{total} · 속도 {speed}/s · 실패 {failed}", + "iris.runtime.pregen.status.chunks": "주 메뉴 {generated}/{total} · 속도 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "주 메뉴 {generated}/{total} · 속도 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · 탈출 {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · 탈출 {elapsed} · 일시 중지", "iris.runtime.pregen.button.pause": "일시 중지/재개", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "일시 중지 {generated}/{total} ({percent} 완료)", "iris.desktop.pregen.progress_saving": "저장 중... {generated}/{total} ({percent} 완료)", "iris.desktop.pregen.progress_generating": "전체 {total} 중 {generated} 생성 중 ({percent} 완료)", - "iris.desktop.pregen.speed": "속도: {chunksPerSecond} 청크/s, {regionsPerMinute} 지구/m, {chunksPerMinute} 청크/m", - "iris.desktop.pregen.speed_cached": "속도: 캐시 {chunksPerSecond} 청크/s, {regionsPerMinute} 지구/m, {chunksPerMinute} 청크/m", + "iris.desktop.pregen.speed": "속도: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "속도: 캐시 {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} 나머지 ({elapsed} 탈출)", "iris.desktop.pregen.method": "생성 방법: {method}", "iris.desktop.pregen.memory": "기억: {used} ({usage}) 압력: {pressure}/s", diff --git a/core/src/main/resources/languages/lt_LT.json b/core/src/main/resources/languages/lt_LT.json index 0cc09c144..fc3fd4d06 100644 --- a/core/src/main/resources/languages/lt_LT.json +++ b/core/src/main/resources/languages/lt_LT.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eNėra aktyvaus regeneravimo užduotys sustabdyti / išjungti.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eAktyvios regeneracijos užduoties nėra.", "iris.bukkit.commandpregen.pregen": "§agreat- britain _ counties. kgm §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aGreitis: §6{value}/s§a ETA: §6{value2}§a Nuplikyti: §6{value3}§a Metodas: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aGreitis: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cNepavyko išspręsti pakuotės dimensijai {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aįrašyta struktūros indeksas: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cNepavyko išspręsti pakuotės dimensijai {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " nepavyko {failed}", "iris.runtime.pregen.status.context": "Matmuo {dimension} · Metodas {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Šakutės. {generated}/{total} · Greitis {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Šakutės. {generated}/{total} · Greitis {speed}/s · Nepavyko {failed}", + "iris.runtime.pregen.status.chunks": "Šakutės. {generated}/{total} · Greitis overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Šakutės. {generated}/{total} · Greitis overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Elapsad {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Elapsad {elapsed} · pristabdyta", "iris.runtime.pregen.button.pause": "Pristabdyti / tęsti", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "pristabdyta {generated} iš {total} ({percent} užbaigti)", "iris.desktop.pregen.progress_saving": "Taupoma... {generated} iš {total} ({percent} užbaigti)", "iris.desktop.pregen.progress_generating": "Generuojama {generated} iš {total} ({percent} užbaigti)", - "iris.desktop.pregen.speed": "Greitis: {chunksPerSecond} chunkai/s, {regionsPerMinute} regionai / m, {chunksPerMinute} chunkai / m", - "iris.desktop.pregen.speed_cached": "Greitis: cached {chunksPerSecond} chunkai/s, {regionsPerMinute} regionai / m, {chunksPerMinute} chunkai / m", + "iris.desktop.pregen.speed": "Greitis: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Greitis: cached {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} likę ({elapsed} praėjo)", "iris.desktop.pregen.method": "Gamybos būdas: {method}", "iris.desktop.pregen.memory": "Atmintis: {used} ({usage}) Slėgis: {pressure}/s", diff --git a/core/src/main/resources/languages/nl_NL.json b/core/src/main/resources/languages/nl_NL.json index 91b64d25a..126eb8738 100644 --- a/core/src/main/resources/languages/nl_NL.json +++ b/core/src/main/resources/languages/nl_NL.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eGeen actieve pregeneratietaken om te pauzeren/ontspannen.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eGeen actieve pregeneratie taak.", "iris.bukkit.commandpregen.pregen": "§aVoorbereiding §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aSnelheid: §6{value}/s§a ETA: §6{value2}§a Vervallen: §6{value3}§a Methode: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aSnelheid: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cKon het pakket voor dimensie niet oplossen {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aSchreef structuurindex: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cKon het pakket voor dimensie niet oplossen {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " mislukt {failed}", "iris.runtime.pregen.status.context": "Dimensie {dimension} · Methode {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Knobbels {generated}/{total} · Snelheid {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Knobbels {generated}/{total} · Snelheid {speed}/s · mislukt {failed}", + "iris.runtime.pregen.status.chunks": "Knobbels {generated}/{total} · Snelheid overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Knobbels {generated}/{total} · Snelheid overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Vervallen {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Vervallen {elapsed} · gepauzeerd", "iris.runtime.pregen.button.pause": "Pauze/hervatten", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "gepauzeerd {generated} van {total} ({percent} volledig)", "iris.desktop.pregen.progress_saving": "Opslaan... {generated} van {total} ({percent} volledig)", "iris.desktop.pregen.progress_generating": "Genereren {generated} van {total} ({percent} volledig)", - "iris.desktop.pregen.speed": "Snelheid: {chunksPerSecond} chunks/s, {regionsPerMinute} regio's/m, {chunksPerMinute} chunks/m", - "iris.desktop.pregen.speed_cached": "Snelheid: gecached {chunksPerSecond} chunks/s, {regionsPerMinute} regio's/m, {chunksPerMinute} chunks/m", + "iris.desktop.pregen.speed": "Snelheid: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Snelheid: gecached {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} resterende ({elapsed} verlopen)", "iris.desktop.pregen.method": "Generatiemethode: {method}", "iris.desktop.pregen.memory": "Geheugen: {used} ({usage}) Druk {pressure}/s", diff --git a/core/src/main/resources/languages/pl_PL.json b/core/src/main/resources/languages/pl_PL.json index e0e24ac4e..610e59eda 100644 --- a/core/src/main/resources/languages/pl_PL.json +++ b/core/src/main/resources/languages/pl_PL.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eBrak aktywnych zadań pregeneracyjnych do zatrzymania / wyłączenia.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eBrak aktywnego zadania pregeneracji.", "iris.bukkit.commandpregen.pregen": "§aPregon §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aPrędkość: §6{value}/s§a ETA: §6{value2}§a Upłynęło: §6{value3}§a Metoda: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aPrędkość: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cNie można rozwiązać pakietu dla wymiaru {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aIndeks struktury napisanej: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cNie można rozwiązać pakietu dla wymiaru {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " nieudany {failed}", "iris.runtime.pregen.status.context": "Wymiar {dimension} · Metoda {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Kawałki {generated}/{total} · Prędkość {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Kawałki {generated}/{total} · Prędkość {speed}/s · Nieudany {failed}", + "iris.runtime.pregen.status.chunks": "Kawałki {generated}/{total} · Prędkość overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Kawałki {generated}/{total} · Prędkość overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Upłynął {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Upłynął {elapsed} · wstrzymano", "iris.runtime.pregen.button.pause": "Pauza / Wznowienie", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "wstrzymano {generated} z {total} ({percent} całkowita)", "iris.desktop.pregen.progress_saving": "Zapisywanie... {generated} z {total} ({percent} całkowita)", "iris.desktop.pregen.progress_generating": "Generowanie {generated} z {total} ({percent} całkowita)", - "iris.desktop.pregen.speed": "Prędkość: {chunksPerSecond} chunki/s, {regionsPerMinute} regiony / m, {chunksPerMinute} części / m", - "iris.desktop.pregen.speed_cached": "Prędkość: buforowana {chunksPerSecond} chunki/s, {regionsPerMinute} regiony / m, {chunksPerMinute} części / m", + "iris.desktop.pregen.speed": "Prędkość: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Prędkość: buforowana {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} pozostałe ({elapsed} elapsed)", "iris.desktop.pregen.method": "Metoda wytwarzania: {method}", "iris.desktop.pregen.memory": "Pamięć: {used} ({usage}) Ciśnienie: {pressure}/s", diff --git a/core/src/main/resources/languages/pt_PT.json b/core/src/main/resources/languages/pt_PT.json index 9a276f13a..b20ff8e49 100644 --- a/core/src/main/resources/languages/pt_PT.json +++ b/core/src/main/resources/languages/pt_PT.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eNenhuma tarefa ativa de pré-geração para pausar/despachar.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eNenhuma tarefa ativa de pré-geração.", "iris.bukkit.commandpregen.pregen": "§aPregenName §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVelocidade: §6{value}/s§a ETA: §6{value2}§a Eclodido: §6{value3}§a Método: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aVelocidade: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cNão foi possível resolver o pacote para a dimensão {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aÍndice de estrutura escrito: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cNão foi possível resolver o pacote para a dimensão {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " falhou {failed}", "iris.runtime.pregen.status.context": "Dimensão {dimension} · Método {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Pedaços {generated}/{total} · Velocidade {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Pedaços {generated}/{total} · Velocidade {speed}/s · Falhou {failed}", + "iris.runtime.pregen.status.chunks": "Pedaços {generated}/{total} · Velocidade overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Pedaços {generated}/{total} · Velocidade overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Sucedeu {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Sucedeu {elapsed} · pausado", "iris.runtime.pregen.button.pause": "Pausa/Resumir", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "pausado {generated} de {total} ({percent} completo)", "iris.desktop.pregen.progress_saving": "Salvando... {generated} de {total} ({percent} completo)", "iris.desktop.pregen.progress_generating": "Gerando {generated} de {total} ({percent} completo)", - "iris.desktop.pregen.speed": "Velocidade: {chunksPerSecond} chunks/s, {regionsPerMinute} regiões/m, {chunksPerMinute} chunks/m", - "iris.desktop.pregen.speed_cached": "Velocidade: em cache {chunksPerSecond} chunks/s, {regionsPerMinute} regiões/m, {chunksPerMinute} chunks/m", + "iris.desktop.pregen.speed": "Velocidade: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Velocidade: em cache {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} restantes ({elapsed} transcorrido)", "iris.desktop.pregen.method": "Método de geração: {method}", "iris.desktop.pregen.memory": "Memória: {used} ({usage}) Pressão: {pressure}/s", diff --git a/core/src/main/resources/languages/ru_RU.json b/core/src/main/resources/languages/ru_RU.json index bfa2d4cea..1142e2d7c 100644 --- a/core/src/main/resources/languages/ru_RU.json +++ b/core/src/main/resources/languages/ru_RU.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eНет активных задач прегенерации для паузы / разрядки.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eНет активной задачи прегенерации.", "iris.bukkit.commandpregen.pregen": "§aпреген §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aСкорость: §6{value}/s§a ETA: §6{value2}§a Прошли: §6{value3}§a Метод: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aСкорость: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cНе удалось решить пакет для измерения {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aНаписал индекс структуры: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cНе удалось решить пакет для измерения {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " неудачный {failed}", "iris.runtime.pregen.status.context": "измерение {dimension} · Метод {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Куски {generated}/{total} · Скорость {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Куски {generated}/{total} · Скорость {speed}/s · Неудачный {failed}", + "iris.runtime.pregen.status.chunks": "Куски {generated}/{total} · Скорость overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Куски {generated}/{total} · Скорость overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · истек {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · истек {elapsed} · приостановлено", "iris.runtime.pregen.button.pause": "Пауза/резюме", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "приостановлено {generated} из {total} ({percent} полный)", "iris.desktop.pregen.progress_saving": "экономить... {generated} из {total} ({percent} полный)", "iris.desktop.pregen.progress_generating": "генерировать {generated} из {total} ({percent} полный)", - "iris.desktop.pregen.speed": "Скорость: {chunksPerSecond} чанки/s, {regionsPerMinute} области/м, {chunksPerMinute} чанки/м", - "iris.desktop.pregen.speed_cached": "Скорость: кэшировано {chunksPerSecond} чанки/s, {regionsPerMinute} области/м, {chunksPerMinute} чанки/м", + "iris.desktop.pregen.speed": "Скорость: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Скорость: кэшировано {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} оставшееся ({elapsed} истекший)", "iris.desktop.pregen.method": "Метод генерации: {method}", "iris.desktop.pregen.memory": "Память: {used} ({usage}) Давление: {pressure}/s", diff --git a/core/src/main/resources/languages/tr_TR.json b/core/src/main/resources/languages/tr_TR.json index ff958b22f..786db0c4c 100644 --- a/core/src/main/resources/languages/tr_TR.json +++ b/core/src/main/resources/languages/tr_TR.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eHiçbir aktif prejenerasyon görevi duraklama /unpause.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eAktif prejenerasyon görevi yok.", "iris.bukkit.commandpregen.pregen": "§aPrejen §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aHız: §6{value}/s§a ETA: §6{value2}§a Elapd: §6{value3}§a Yöntem: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aHız: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cpaketi boyut için çözemez {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§ayazıldı yapı indeksi: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cpaketi boyut için çözemez {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " Başarısız oldu {failed}", "iris.runtime.pregen.status.context": "Boyut {dimension} · Yöntem {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Chunk {generated}/{total} · Hız {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Chunk {generated}/{total} · Hız {speed}/s · Başarısızlık {failed}", + "iris.runtime.pregen.status.chunks": "Chunk {generated}/{total} · Hız overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Chunk {generated}/{total} · Hız overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · Elapd {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · Elapd {elapsed} · duraklatıldı", "iris.runtime.pregen.button.pause": "Pause /Resume", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "duraklatıldı {generated} Of {total} ({percent} Tamam)", "iris.desktop.pregen.progress_saving": "Tasarruf kurtarmak... {generated} Of {total} ({percent} Tamam)", "iris.desktop.pregen.progress_generating": "Genating {generated} Of {total} ({percent} Tamam)", - "iris.desktop.pregen.speed": "Hız: {chunksPerSecond} chunk/s, {regionsPerMinute} bölgeler/m, {chunksPerMinute} chunks /", - "iris.desktop.pregen.speed_cached": "Hız: Önbelli {chunksPerSecond} chunk/s, {regionsPerMinute} bölgeler/m, {chunksPerMinute} chunks /", + "iris.desktop.pregen.speed": "Hız: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Hız: Önbelli {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} kalan ({elapsed} elapd)", "iris.desktop.pregen.method": "Nesil yöntemi: {method}", "iris.desktop.pregen.memory": "bellek: {used} ({usage}Baskı:) {pressure}/s", diff --git a/core/src/main/resources/languages/vi_VI.json b/core/src/main/resources/languages/vi_VI.json index 6edd6ee2b..6551dfac2 100644 --- a/core/src/main/resources/languages/vi_VI.json +++ b/core/src/main/resources/languages/vi_VI.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§eKhông có tác vụ trước thế hệ hoạt động để tạm dừng/unpause.", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§eKhông có nhiệm vụ trước thế hệ.", "iris.bukkit.commandpregen.pregen": "§aBản quyền §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aTốc độ: §6{value}/s§a ETA: §6{value2}§a Phát triển: §6{value3}§a Phương pháp: §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§aTốc độ: §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§cKhông thể giải quyết gói cho kích thước {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§aChỉ mục cấu trúc ghi: §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§cKhông thể giải quyết gói cho kích thước {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " bị lỗi {failed}", "iris.runtime.pregen.status.context": "Kích thước {dimension} · Phương pháp {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "Chunnks {generated}/{total} * Tốc độ {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "Chunnks {generated}/{total} * Tốc độ {speed}/s Lỗi {failed}", + "iris.runtime.pregen.status.chunks": "Chunnks {generated}/{total} * Tốc độ overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "Chunnks {generated}/{total} * Tốc độ overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} Lập tắt {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} Lập tắt {elapsed} · đã tạm dừng", "iris.runtime.pregen.button.pause": "Tạm dừng/ Tiếp tục", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "đã tạm dừng {generated} Kho {total} ({percent} Hoàn tất)", "iris.desktop.pregen.progress_saving": "Đang lưu... {generated} Kho {total} ({percent} Hoàn tất)", "iris.desktop.pregen.progress_generating": "Đang tạo ra {generated} Kho {total} ({percent} Hoàn tất)", - "iris.desktop.pregen.speed": "Tốc độ: {chunksPerSecond} Chunk/s, {regionsPerMinute} Vùng/m, {chunksPerMinute} Chunk", - "iris.desktop.pregen.speed_cached": "Tốc độ: đã lưu tạm {chunksPerSecond} Chunk/s, {regionsPerMinute} Vùng/m, {chunksPerMinute} Chunk", + "iris.desktop.pregen.speed": "Tốc độ: {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "Tốc độ: đã lưu tạm {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} còn lại ({elapsed} Mở rộng)", "iris.desktop.pregen.method": "Phương pháp thế hệ: {method}", "iris.desktop.pregen.memory": "Bộ nhớ: {used} ({usage}) Áp lực: {pressure}/s", diff --git a/core/src/main/resources/languages/zh_CN.json b/core/src/main/resources/languages/zh_CN.json index 4a1812604..e0e5986f7 100644 --- a/core/src/main/resources/languages/zh_CN.json +++ b/core/src/main/resources/languages/zh_CN.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§e没有活动的生成前任务可以暂停/停止 。", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§e没有活动生成前任务 。", "iris.bukkit.commandpregen.pregen": "§a预览 §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a速度 : §6{value}/s§a ETA: §6{value2}§a 击落: §6{value3}§a 方法 : §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a速度 : §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§c无法解析大小包 {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§a写作结构索引 : §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§c无法解析大小包 {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " 失败 {failed}", "iris.runtime.pregen.status.context": "维度 {dimension} 方法 {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "块 {generated}/{total} 速度 {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "块 {generated}/{total} 速度 {speed}/s 失败 {failed}", + "iris.runtime.pregen.status.chunks": "块 {generated}/{total} 速度 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "块 {generated}/{total} 速度 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · 溃败 {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · 溃败 {elapsed} · 已暂停", "iris.runtime.pregen.button.pause": "暂停/恢复", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "已暂停 {generated} 页:1 {total} ({percent} 完成) 数据", "iris.desktop.pregen.progress_saving": "保存... {generated} 页:1 {total} ({percent} 完成) 数据", "iris.desktop.pregen.progress_generating": "正在生成 {generated} 页:1 {total} ({percent} 完成) 数据", - "iris.desktop.pregen.speed": "速度 : {chunksPerSecond} 块/s, {regionsPerMinute} 区域/米, {chunksPerMinute} 块/米", - "iris.desktop.pregen.speed_cached": "速度:已缓存 {chunksPerSecond} 块/s, {regionsPerMinute} 区域/米, {chunksPerMinute} 块/米", + "iris.desktop.pregen.speed": "速度 : {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "速度:已缓存 {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} 剩余({elapsed} 已过期)", "iris.desktop.pregen.method": "生成方法 : {method}", "iris.desktop.pregen.memory": "内存 : {used} ({usage})压力: {pressure}/s", diff --git a/core/src/main/resources/languages/zh_TW.json b/core/src/main/resources/languages/zh_TW.json index 70eaa3d29..4dccb0496 100644 --- a/core/src/main/resources/languages/zh_TW.json +++ b/core/src/main/resources/languages/zh_TW.json @@ -236,7 +236,7 @@ "iris.bukkit.commandpregen.no_active_pregeneration_tasks_pause_unpause": "§e沒有活動的生成前任務可以暫停/停止 。", "iris.bukkit.commandpregen.no_active_pregeneration_task": "§e沒有活動生成前任務 。", "iris.bukkit.commandpregen.pregen": "§a預覽 §6{world}§a: §6{value}/{value2}§a (§6{value3}%§a){value4}", - "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a速度 : §6{value}/s§a ETA: §6{value2}§a 擊落: §6{value3}§a 方法 : §6{value4}{value5}", + "iris.bukkit.commandpregen.speed_s_eta_elapsed_method": "§a速度 : §6overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s§a ETA: §6{eta}§a Elapsed: §6{elapsed}§a Method: §6{method}{failures}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension": "§c無法解析大小包 {value}", "iris.bukkit.commandstructure.wrote_structure_index": "§a寫作結構索引 : §f{value}", "iris.bukkit.commandstructure.could_not_resolve_pack_dimension_2": "§c無法解析大小包 {value}", @@ -1015,8 +1015,8 @@ "iris.runtime.pregen.failed_fragment": " 失敗 {failed}", "iris.runtime.pregen.status.context": "維度 {dimension} 方法 {method}", "iris.runtime.pregen.status.progress": "{percent}%", - "iris.runtime.pregen.status.chunks": "塊 {generated}/{total} 速度 {speed}/s", - "iris.runtime.pregen.status.chunks_failed": "塊 {generated}/{total} 速度 {speed}/s 失敗 {failed}", + "iris.runtime.pregen.status.chunks": "塊 {generated}/{total} 速度 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s", + "iris.runtime.pregen.status.chunks_failed": "塊 {generated}/{total} 速度 overall {overall}/s, 10s {tenSecond}/s, 30s {thirtySecond}/s, 60s {sixtySecond}/s · Failed {failed}", "iris.runtime.pregen.status.time": "ETA {eta} · 潰敗 {elapsed}", "iris.runtime.pregen.status.time_paused": "ETA {eta} · 潰敗 {elapsed} · 已暫停", "iris.runtime.pregen.button.pause": "暫停/恢復", @@ -1431,8 +1431,8 @@ "iris.desktop.pregen.progress_paused": "已暫停 {generated} 頁:1 {total} ({percent} 完成) 資料", "iris.desktop.pregen.progress_saving": "儲存... {generated} 頁:1 {total} ({percent} 完成) 資料", "iris.desktop.pregen.progress_generating": "正在生成 {generated} 頁:1 {total} ({percent} 完成) 資料", - "iris.desktop.pregen.speed": "速度 : {chunksPerSecond} 塊/s, {regionsPerMinute} 區域/米, {chunksPerMinute} 塊/米", - "iris.desktop.pregen.speed_cached": "速度:已快取 {chunksPerSecond} 塊/s, {regionsPerMinute} 區域/米, {chunksPerMinute} 塊/米", + "iris.desktop.pregen.speed": "速度 : {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", + "iris.desktop.pregen.speed_cached": "速度:已快取 {overall} overall, {tenSecond} 10s, {thirtySecond} 30s, {sixtySecond} 60s chunks/s", "iris.desktop.pregen.time": "{remaining} 剩餘({elapsed} 已過期)", "iris.desktop.pregen.method": "生成方法 : {method}", "iris.desktop.pregen.memory": "記憶體 : {used} ({usage})壓力: {pressure}/s", diff --git a/core/src/test/java/art/arcane/iris/core/gui/GuiHostTest.java b/core/src/test/java/art/arcane/iris/core/gui/GuiHostTest.java new file mode 100644 index 000000000..c36c948dc --- /dev/null +++ b/core/src/test/java/art/arcane/iris/core/gui/GuiHostTest.java @@ -0,0 +1,58 @@ +package art.arcane.iris.core.gui; + +import org.junit.Assume; +import org.junit.Test; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import java.awt.GraphicsEnvironment; +import java.awt.desktop.QuitResponse; +import java.awt.event.WindowEvent; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class GuiHostTest { + @Test + public void desktopQuitIsCancelledWithoutPerformingQuit() { + AtomicInteger cancelled = new AtomicInteger(); + AtomicInteger performed = new AtomicInteger(); + QuitResponse response = new QuitResponse() { + @Override + public void performQuit() { + performed.incrementAndGet(); + } + + @Override + public void cancelQuit() { + cancelled.incrementAndGet(); + } + }; + + GuiHost.cancelDesktopQuit(response); + + assertEquals(1, cancelled.get()); + assertEquals(0, performed.get()); + } + + @Test + public void preparedFramesDisposeWhenClosed() throws Exception { + Assume.assumeFalse(GraphicsEnvironment.isHeadless()); + AtomicReference frameReference = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + JFrame frame = new JFrame("Iris lifecycle test"); + GuiHost.prepareFrame(frame); + frame.setVisible(true); + frameReference.set(frame); + }); + + JFrame frame = frameReference.get(); + assertEquals(JFrame.DISPOSE_ON_CLOSE, frame.getDefaultCloseOperation()); + assertTrue(frame.isDisplayable()); + SwingUtilities.invokeAndWait(() -> frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING))); + assertFalse(frame.isDisplayable()); + } +} diff --git a/core/src/test/java/art/arcane/iris/core/pregenerator/PregenRateTrackerTest.java b/core/src/test/java/art/arcane/iris/core/pregenerator/PregenRateTrackerTest.java new file mode 100644 index 000000000..cb3c6de63 --- /dev/null +++ b/core/src/test/java/art/arcane/iris/core/pregenerator/PregenRateTrackerTest.java @@ -0,0 +1,73 @@ +package art.arcane.iris.core.pregenerator; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PregenRateTrackerTest { + @Test + public void shortRunIsNotDilutedByInitialZeroSample() { + PregenRateTracker tracker = new PregenRateTracker(0L, 0L); + + tracker.sample(0L, 0L); + for (int second = 1; second <= 5; second++) { + PregenRates rates = tracker.sample(second * 200L, second * 1_000L); + assertRates(200D, rates); + } + } + + @Test + public void rollingWindowsUseTheirActualElapsedTime() { + PregenRateTracker tracker = new PregenRateTracker(0L, 0L); + long completed = 0L; + PregenRates rates = PregenRates.ZERO; + + for (int second = 1; second <= 70; second++) { + completed += second <= 10 ? 500L : second <= 40 ? 200L : 100L; + rates = tracker.sample(completed, second * 1_000L); + } + + assertEquals(200D, rates.overall(), 0.001D); + assertEquals(100D, rates.tenSecond(), 0.001D); + assertEquals(100D, rates.thirtySecond(), 0.001D); + assertEquals(150D, rates.sixtySecond(), 0.001D); + } + + @Test + public void delayedSamplesDivideByWallClockTime() { + PregenRateTracker tracker = new PregenRateTracker(5_000L, 100L); + + PregenRates rates = tracker.sample(700L, 9_000L); + + assertRates(150D, rates); + } + + @Test + public void ringWrapRetainsSixtySecondWindow() { + PregenRateTracker tracker = new PregenRateTracker(0L, 0L); + PregenRates rates = PregenRates.ZERO; + + for (int second = 1; second <= 200; second++) { + rates = tracker.sample(second * 75L, second * 1_000L); + } + + assertRates(75D, rates); + } + + @Test + public void terminalSampleIncludesProgressAfterLastTickerTick() { + PregenRateTracker tracker = new PregenRateTracker(0L, 0L); + tracker.sample(800L, 4_000L); + + PregenRates rates = tracker.sample(1_000L, 5_000L); + + assertRates(200D, rates); + } + + private static void assertRates(double expected, PregenRates rates) { + assertEquals(expected, rates.overall(), 0.001D); + assertEquals(expected, rates.tenSecond(), 0.001D); + assertEquals(expected, rates.thirtySecond(), 0.001D); + assertEquals(expected, rates.sixtySecond(), 0.001D); + } +} diff --git a/core/src/test/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethodConcurrencyCapTest.java b/core/src/test/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethodConcurrencyCapTest.java index 02275805b..bebc72762 100644 --- a/core/src/test/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethodConcurrencyCapTest.java +++ b/core/src/test/java/art/arcane/iris/core/pregenerator/methods/AsyncPregenMethodConcurrencyCapTest.java @@ -28,12 +28,12 @@ public class AsyncPregenMethodConcurrencyCapTest { } @Test - public void paperLikeConcurrencyUsesDetectedWorkerPoolWhenAvailable() { - assertEquals(4, AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(4, 16, 32)); - assertEquals(4, AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(4, 16, 16)); + public void paperLikeConcurrencyUsesProvisionedWorkerPoolCapacity() { + assertEquals(32, AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(4, 16, 32)); + assertEquals(16, AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(4, 16, 16)); assertEquals(24, AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(-1, 16, 24)); assertEquals(16, AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(-1, 16, 8)); - assertEquals(32, AsyncPregenMethod.computePaperLikeRecommendedCap( + assertEquals(128, AsyncPregenMethod.computePaperLikeRecommendedCap( AsyncPregenMethod.resolvePaperLikeConcurrencyWorkerThreads(4, 16, 16))); } diff --git a/core/src/test/java/art/arcane/iris/util/project/noise/CloverNoiseParityTest.java b/core/src/test/java/art/arcane/iris/util/project/noise/CloverNoiseParityTest.java new file mode 100644 index 000000000..f7e1fda32 --- /dev/null +++ b/core/src/test/java/art/arcane/iris/util/project/noise/CloverNoiseParityTest.java @@ -0,0 +1,43 @@ +package art.arcane.iris.util.project.noise; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class CloverNoiseParityTest { + private static final long[] SEEDS = {0L, -1L, 1337L, Long.MIN_VALUE, Long.MAX_VALUE}; + private static final double[][] POINTS = { + {0.125D, -0.75D, 1.5D}, + {-1000.25D, 64.5D, 2048.75D}, + {29_999_984D, -64D, -29_999_984D}, + {Math.PI, Math.E, -Math.sqrt(2D)} + }; + private static final long[][] EXPECTED_3D = { + {4606295205971726443L, 4596584066878230492L, 4601072533138395306L, 4595465536009596573L}, + {4594559156169257303L, 4602986449390023959L, 4602157576770610768L, 4604264428473675137L}, + {4594287239476896260L, 4606819753250159891L, 4603131747488558437L, 4605050910998320058L}, + {4594574716919961912L, 4582369728393548057L, 4600712766107896080L, 4594781081233153808L}, + {4603622723932858649L, 4604886251804482757L, 4600180200303866897L, 4597047378643079682L} + }; + private static final long[][] EXPECTED_2D = { + {4600886466954977930L, 4603042301510796801L, 4605282822283219348L, 4603381024907987886L}, + {4604231235993958026L, 4603294413466771076L, 4606358936184576936L, 4605313173145937690L}, + {4602575096448892092L, 4600034591678710230L, 4603842817538381592L, 4604447254328254894L}, + {4602176302263458666L, 4592022086679349802L, 4605779333798454855L, 4603816542564903403L}, + {4603283241394868042L, 4601437833095430179L, 4606037056899058631L, 4604909992999588843L} + }; + + @Test + public void optimizedVectorMathPreservesExactNoiseBits() { + for (int seedIndex = 0; seedIndex < SEEDS.length; seedIndex++) { + CloverNoise noise = new CloverNoise(SEEDS[seedIndex]); + for (int pointIndex = 0; pointIndex < POINTS.length; pointIndex++) { + double[] point = POINTS[pointIndex]; + assertEquals(EXPECTED_3D[seedIndex][pointIndex], Double.doubleToRawLongBits( + noise.noise(point[0], point[1], point[2]))); + assertEquals(EXPECTED_2D[seedIndex][pointIndex], Double.doubleToRawLongBits( + noise.noise(point[0], point[2]))); + } + } + } +}