Refreshed pregeneration runtime

- Generation router reads avoid the attachment monitor after publication
- Desktop pregeneration uses a proportional map with distinct controls and metrics
- Preview updates remain bounded through large targets and window state changes
- Pause controls stay bound to their owning job
- Startup failures retain a readable error window
- Bundled language catalogs cover the revised window
This commit is contained in:
Brian Neumann-Fopiano
2026-09-06 14:48:37 -04:00
28 changed files with 1530 additions and 376 deletions
@@ -0,0 +1,113 @@
package art.arcane.iris.core.gui;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.util.Arrays;
import java.util.BitSet;
import java.util.concurrent.locks.ReentrantLock;
final class PregenMapPanel extends JPanel {
private static final int MAX_RASTER_SIZE = 1024;
static final Color WAITING = new Color(29, 35, 46);
private final PregenRenderSnapshot.Bounds bounds;
private final BufferedImage image;
private final int[] imagePixels;
private final int[] pendingPixels;
private final BitSet dirtyPixels;
private final ReentrantLock lock = new ReentrantLock();
private volatile boolean pendingChanges;
private volatile boolean disposed;
PregenMapPanel(PregenRenderSnapshot.Bounds bounds) {
this.bounds = bounds;
int width = (int) Math.min(MAX_RASTER_SIZE, bounds.width());
int height = (int) Math.min(MAX_RASTER_SIZE, bounds.height());
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
imagePixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
pendingPixels = new int[imagePixels.length];
dirtyPixels = new BitSet(imagePixels.length);
Arrays.fill(imagePixels, WAITING.getRGB());
Arrays.fill(pendingPixels, WAITING.getRGB());
setBackground(PregenRenderer.BACKGROUND);
}
void submit(int chunkX, int chunkZ, Color color) {
if (disposed || !bounds.contains(chunkX, chunkZ)) {
return;
}
int x = (int) (((long) chunkX - bounds.minX()) * image.getWidth() / bounds.width());
int z = (int) (((long) chunkZ - bounds.minZ()) * image.getHeight() / bounds.height());
int index = z * image.getWidth() + x;
int rgb = color.getRGB();
lock.lock();
try {
if (disposed || pendingPixels[index] == rgb) {
return;
}
pendingPixels[index] = rgb;
dirtyPixels.set(index);
pendingChanges = true;
} finally {
lock.unlock();
}
}
boolean flush() {
if (!pendingChanges || disposed) {
return false;
}
lock.lock();
try {
for (int index = dirtyPixels.nextSetBit(0); index >= 0; index = dirtyPixels.nextSetBit(index + 1)) {
imagePixels[index] = pendingPixels[index];
}
dirtyPixels.clear();
pendingChanges = false;
} finally {
lock.unlock();
}
return true;
}
void disposeMap() {
lock.lock();
try {
disposed = true;
dirtyPixels.clear();
pendingChanges = false;
} finally {
lock.unlock();
}
}
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D canvas = (Graphics2D) graphics.create();
try {
Rectangle area = fit(bounds, getWidth(), getHeight());
canvas.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
canvas.drawImage(image, area.x, area.y, area.width, area.height, null);
canvas.setColor(PregenRenderer.BORDER);
canvas.drawRect(area.x, area.y, area.width - 1, area.height - 1);
} finally {
canvas.dispose();
}
}
static Rectangle fit(PregenRenderSnapshot.Bounds bounds, int width, int height) {
int availableWidth = Math.max(1, width - 2);
int availableHeight = Math.max(1, height - 2);
double scale = Math.min((double) availableWidth / bounds.width(), (double) availableHeight / bounds.height());
int mapWidth = Math.max(1, (int) Math.floor(bounds.width() * scale));
int mapHeight = Math.max(1, (int) Math.floor(bounds.height() * scale));
return new Rectangle((width - mapWidth) / 2, (height - mapHeight) / 2, mapWidth, mapHeight);
}
}
@@ -0,0 +1,50 @@
package art.arcane.iris.core.gui;
import java.util.Objects;
public record PregenRenderSnapshot(
Bounds bounds,
PregeneratorJob.PregenProgress progress,
Phase phase,
boolean cached,
long usedMemoryBytes,
double memoryUsage,
long allocationBytesPerSecond,
String failure
) {
public PregenRenderSnapshot {
Objects.requireNonNull(bounds, "Map bounds");
Objects.requireNonNull(progress, "Generation progress");
Objects.requireNonNull(phase, "Generation phase");
}
public enum Phase {
INITIALIZING,
GENERATING,
PAUSED,
SAVING,
STOPPING,
COMPLETED,
ERROR
}
public record Bounds(int minX, int minZ, int maxX, int maxZ) {
public Bounds {
if (maxX < minX || maxZ < minZ) {
throw new IllegalArgumentException("Map bounds must contain at least one chunk");
}
}
public long width() {
return (long) maxX - minX + 1;
}
public long height() {
return (long) maxZ - minZ + 1;
}
public boolean contains(int x, int z) {
return x >= minX && x <= maxX && z >= minZ && z <= maxZ;
}
}
}
@@ -18,14 +18,6 @@
package art.arcane.iris.core.gui;
import art.arcane.volmlib.util.math.Position2;
public interface PregenRenderSource {
Position2 min();
Position2 max();
String[] progress();
boolean paused();
PregenRenderSnapshot renderSnapshot();
}
@@ -18,92 +18,138 @@
package art.arcane.iris.core.gui;
import art.arcane.iris.core.IrisSettings;
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.math.M;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import art.arcane.volmlib.util.format.Form;
import art.arcane.volmlib.util.localization.MessageArgument;
import art.arcane.volmlib.util.localization.TextKey;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import javax.swing.plaf.basic.BasicProgressBarUI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Graphics;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
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;
import java.util.Objects;
public final class PregenRenderer extends JPanel implements KeyListener {
public final class PregenRenderer extends JPanel {
private static final long serialVersionUID = 2094606939770332040L;
static final Color BACKGROUND = new Color(12, 15, 22);
static final Color BORDER = new Color(105, 119, 139);
private static final Color SURFACE = new Color(17, 20, 29);
private static final Color FIELD = new Color(29, 34, 47);
private static final Color TEXT = new Color(230, 234, 242);
private static final Color MUTED = new Color(163, 173, 191);
private static final Color ACCENT = new Color(101, 194, 149);
private static final Color ERROR = new Color(255, 139, 139);
static final Color GENERATING = new Color(204, 168, 107);
static final Color GENERATED = ACCENT;
static final Color EXISTS = new Color(93, 133, 112);
static final Color NETWORK = new Color(157, 138, 176);
static final Color NETWORK_GENERATING = new Color(129, 112, 145);
private static final Font BODY_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 13);
private static final Font LABEL_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 11);
private static final Font VALUE_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private static final int MAX_PENDING_DRAWS = 16_384;
private Long2ObjectLinkedOpenHashMap<Color> 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 final PregenMapPanel map;
private final Timer repaintTimer;
private final JLabel worldLabel = label("", new Font(Font.SANS_SERIF, Font.BOLD, 21), TEXT);
private final JLabel phaseLabel = label("", BODY_FONT, MUTED);
private final JLabel countLabel = label("", BODY_FONT, TEXT);
private final JLabel percentLabel = label("", BODY_FONT, MUTED);
private final JLabel currentValue = label("", VALUE_FONT, TEXT);
private final JLabel overallValue = label("", VALUE_FONT, TEXT);
private final JLabel thirtyValue = label("", VALUE_FONT, TEXT);
private final JLabel sixtyValue = label("", VALUE_FONT, TEXT);
private final JLabel etaValue = label("", VALUE_FONT, TEXT);
private final JLabel elapsedValue = label("", VALUE_FONT, TEXT);
private final JLabel memoryValue = label("", VALUE_FONT, TEXT);
private final JLabel pressureValue = label("", VALUE_FONT, TEXT);
private final JLabel methodLabel = label("", LABEL_FONT, MUTED);
private final JLabel failureLabel = label("", LABEL_FONT, ERROR);
private final JButton pauseButton = new JButton();
private final JProgressBar progressBar = new JProgressBar(0, 10_000);
private volatile boolean renderingEnabled;
private boolean disposed;
private volatile boolean disposed;
private volatile JFrame frame;
private PregenRenderSnapshot displayedSnapshot;
private PregenRenderer(PregenRenderSource source, Runnable onPause) {
this.source = source;
this.source = Objects.requireNonNull(source, "Generation view source");
this.onPause = onPause;
repaintTimer = new Timer(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250, event -> repaint());
PregenRenderSnapshot initial = source.renderSnapshot();
map = new PregenMapPanel(initial.bounds());
setLayout(new BorderLayout(0, 18));
setBackground(BACKGROUND);
setBorder(BorderFactory.createEmptyBorder(20, 24, 18, 24));
add(header(), BorderLayout.NORTH);
add(mapArea(initial.bounds()), BorderLayout.CENTER);
add(statusArea(), BorderLayout.SOUTH);
installPauseControl();
repaintTimer = new Timer(IrisSettings.get().getGui().isMaximumPregenGuiFPS() ? 4 : 250,
event -> refresh());
refresh();
}
public static PregenRenderer open(String title, PregenRenderSource source, Runnable onPause) {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("The pregeneration window must open on the Swing event thread");
}
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.setContentPane(renderer);
frame.setSize(1040, 900);
frame.setMinimumSize(new Dimension(760, 660));
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent event) {
renderer.disposeRenderer();
}
});
frame.addWindowStateListener(event -> renderer.renderingEnabled = (event.getNewState() & Frame.ICONIFIED) == 0);
frame.addWindowStateListener(event -> renderer.setRenderingEnabled((event.getNewState() & Frame.ICONIFIED) == 0));
frame.setVisible(true);
renderer.repaintTimer.start();
return renderer;
}
public void submit(int x, int z, Color 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();
}
map.submit(x, z, color);
}
public boolean isVisibleFrame() {
return renderingEnabled;
return renderingEnabled && !disposed;
}
public void close() {
@@ -119,6 +165,234 @@ public final class PregenRenderer extends JPanel implements KeyListener {
}
}
private JPanel header() {
JPanel heading = panel(new BorderLayout(16, 0), BACKGROUND);
JPanel identity = panel(new GridLayout(2, 1, 0, 4), BACKGROUND);
identity.add(worldLabel);
identity.add(phaseLabel);
heading.add(identity, BorderLayout.CENTER);
heading.add(pauseButton, BorderLayout.EAST);
JPanel counts = panel(new BorderLayout(), BACKGROUND);
counts.add(countLabel, BorderLayout.WEST);
counts.add(percentLabel, BorderLayout.EAST);
progressBar.setUI(new BasicProgressBarUI());
progressBar.setForeground(ACCENT);
progressBar.setBackground(FIELD);
progressBar.setBorderPainted(false);
progressBar.setPreferredSize(new Dimension(1, 6));
progressBar.setFocusable(false);
JPanel progress = panel(new BorderLayout(0, 9), BACKGROUND);
progress.add(counts, BorderLayout.NORTH);
progress.add(progressBar, BorderLayout.SOUTH);
JPanel header = panel(new BorderLayout(0, 18), BACKGROUND);
header.add(heading, BorderLayout.NORTH);
header.add(progress, BorderLayout.SOUTH);
return header;
}
private JPanel mapArea(PregenRenderSnapshot.Bounds bounds) {
JPanel area = panel(new BorderLayout(0, 8), BACKGROUND);
map.getAccessibleContext().setAccessibleName(text(DesktopUiMessages.PREGEN_MAP));
area.add(map, BorderLayout.CENTER);
JLabel coordinates = label(text(DesktopUiMessages.PREGEN_BOUNDS,
MessageArgument.trusted("minX", Form.f(bounds.minX())),
MessageArgument.trusted("maxX", Form.f(bounds.maxX())),
MessageArgument.trusted("minZ", Form.f(bounds.minZ())),
MessageArgument.trusted("maxZ", Form.f(bounds.maxZ()))), LABEL_FONT, MUTED);
area.add(coordinates, BorderLayout.SOUTH);
return area;
}
private JPanel statusArea() {
JPanel metrics = panel(new GridLayout(2, 4, 24, 20), SURFACE);
metrics.add(metric(DesktopUiMessages.PREGEN_CURRENT, currentValue));
metrics.add(metric(DesktopUiMessages.PREGEN_OVERALL, overallValue));
metrics.add(metric(DesktopUiMessages.PREGEN_THIRTY, thirtyValue));
metrics.add(metric(DesktopUiMessages.PREGEN_SIXTY, sixtyValue));
metrics.add(metric(DesktopUiMessages.PREGEN_ETA, etaValue));
metrics.add(metric(DesktopUiMessages.PREGEN_ELAPSED, elapsedValue));
metrics.add(metric(DesktopUiMessages.PREGEN_MEMORY_LABEL, memoryValue));
metrics.add(metric(DesktopUiMessages.PREGEN_PRESSURE, pressureValue));
JPanel method = panel(new BorderLayout(16, 0), SURFACE);
method.add(methodLabel, BorderLayout.CENTER);
method.add(failureLabel, BorderLayout.EAST);
JPanel status = panel(new BorderLayout(0, 18), SURFACE);
status.setBorder(BorderFactory.createEmptyBorder(18, 18, 16, 18));
status.add(metrics, BorderLayout.CENTER);
status.add(method, BorderLayout.SOUTH);
JPanel footer = panel(new BorderLayout(0, 12), BACKGROUND);
footer.add(legend(), BorderLayout.NORTH);
footer.add(status, BorderLayout.CENTER);
return footer;
}
private JPanel legend() {
JPanel legend = panel(new FlowLayout(FlowLayout.LEFT, 0, 0), BACKGROUND);
legend.add(legendItem(DesktopUiMessages.PREGEN_WAITING, PregenMapPanel.WAITING));
legend.add(legendItem(DesktopUiMessages.PREGEN_GENERATING, GENERATING));
legend.add(legendItem(DesktopUiMessages.PREGEN_READY, GENERATED));
legend.add(legendItem(DesktopUiMessages.PREGEN_EXISTING, EXISTS));
legend.add(legendItem(DesktopUiMessages.PREGEN_NETWORK, NETWORK));
legend.setToolTipText(text(DesktopUiMessages.PREGEN_TERRAIN_HINT));
return legend;
}
private JPanel legendItem(TextKey key, Color color) {
JPanel item = panel(new FlowLayout(FlowLayout.LEFT, 6, 0), BACKGROUND);
JPanel swatch = new JPanel();
swatch.setBackground(color);
swatch.setPreferredSize(new Dimension(10, 10));
swatch.setBorder(BorderFactory.createLineBorder(BORDER));
item.add(swatch);
item.add(label(text(key), LABEL_FONT, MUTED));
item.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 13));
return item;
}
private JPanel metric(TextKey title, JLabel value) {
JPanel metric = panel(new BorderLayout(0, 5), SURFACE);
metric.add(label(text(title), LABEL_FONT, MUTED), BorderLayout.NORTH);
metric.add(value, BorderLayout.CENTER);
return metric;
}
private void installPauseControl() {
pauseButton.setUI(new BasicButtonUI() {
@Override
protected void paintText(Graphics graphics, AbstractButton button, Rectangle bounds, String text) {
if (button.isEnabled()) {
super.paintText(graphics, button, bounds, text);
return;
}
graphics.setColor(MUTED);
BasicGraphicsUtils.drawStringUnderlineCharAt(graphics, text, button.getDisplayedMnemonicIndex(),
bounds.x, bounds.y + graphics.getFontMetrics().getAscent());
}
});
pauseButton.setBackground(FIELD);
pauseButton.setForeground(TEXT);
pauseButton.setFont(BODY_FONT);
pauseButton.putClientProperty("html.disable", Boolean.TRUE);
pauseButton.setFocusPainted(false);
pauseButton.setPreferredSize(new Dimension(108, 46));
setPauseBorder(false);
pauseButton.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent event) {
setPauseBorder(true);
}
@Override
public void focusLost(FocusEvent event) {
setPauseBorder(false);
}
});
pauseButton.addActionListener(event -> togglePause());
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_P, 0, true), "pause");
getActionMap().put("pause", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent event) {
togglePause();
}
});
}
private void setPauseBorder(boolean focused) {
pauseButton.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(focused ? ACCENT : BORDER, 2),
BorderFactory.createEmptyBorder(8, 14, 8, 14)));
}
private void togglePause() {
if (onPause == null || !pauseButton.isEnabled()) {
return;
}
try {
onPause.run();
refresh();
} catch (RuntimeException failure) {
IrisLogging.reportError("Unable to change pregeneration pause state.", failure);
failureLabel.setText(text(DesktopUiMessages.PREGEN_CONTROL_FAILED));
}
}
private void refresh() {
if (disposed) {
return;
}
PregenRenderSnapshot snapshot = source.renderSnapshot();
if (!snapshot.equals(displayedSnapshot)) {
updateStatus(snapshot);
displayedSnapshot = snapshot;
}
if (map.flush()) {
map.repaint();
}
}
private void updateStatus(PregenRenderSnapshot snapshot) {
PregeneratorJob.PregenProgress progress = snapshot.progress();
boolean initializing = snapshot.phase() == PregenRenderSnapshot.Phase.INITIALIZING;
boolean paused = snapshot.phase() == PregenRenderSnapshot.Phase.PAUSED;
worldLabel.setText(progress.worldName() == null ? text(DesktopUiMessages.PREGEN_TITLE) : progress.worldName());
phaseLabel.setText(text(switch (snapshot.phase()) {
case INITIALIZING -> DesktopUiMessages.PREGEN_INITIALIZING;
case GENERATING -> DesktopUiMessages.PREGEN_GENERATING;
case PAUSED -> DesktopUiMessages.PREGEN_PAUSED;
case SAVING -> DesktopUiMessages.PREGEN_SAVING;
case STOPPING -> DesktopUiMessages.PREGEN_STOPPING;
case COMPLETED -> DesktopUiMessages.PREGEN_COMPLETED;
case ERROR -> DesktopUiMessages.PREGEN_ERROR;
}));
phaseLabel.setForeground(snapshot.phase() == PregenRenderSnapshot.Phase.ERROR ? ERROR : MUTED);
countLabel.setText(text(DesktopUiMessages.PREGEN_PROGRESS,
MessageArgument.trusted("generated", Form.f(progress.generated())),
MessageArgument.trusted("total", Form.f(progress.totalChunks()))));
percentLabel.setText(text(DesktopUiMessages.PREGEN_PERCENT,
MessageArgument.trusted("percent", Form.pc(Math.max(0D, Math.min(1D, progress.percent() / 100D)), 1))));
progressBar.setValue((int) Math.max(0D, Math.min(10_000D, progress.percent() * 100D)));
pauseButton.setText(text(paused ? DesktopUiMessages.PREGEN_RESUME : DesktopUiMessages.PREGEN_PAUSE));
pauseButton.setToolTipText(text(paused ? DesktopUiMessages.PREGEN_RESUME_HINT : DesktopUiMessages.PREGEN_PAUSE_HINT));
pauseButton.setEnabled(onPause != null && switch (snapshot.phase()) {
case GENERATING, PAUSED, SAVING -> true;
default -> false;
});
currentValue.setText(initializing ? pending() : rate(progress.chunksPerSecond()));
overallValue.setText(initializing ? pending() : rate(progress.overallChunksPerSecond()));
thirtyValue.setText(initializing ? pending() : rate(progress.thirtySecondChunksPerSecond()));
sixtyValue.setText(initializing ? pending() : rate(progress.sixtySecondChunksPerSecond()));
etaValue.setText(initializing || paused || progress.eta() < 0
|| (progress.eta() == 0 && progress.chunksRemaining() > 0)
? pending() : Form.duration(progress.eta(), 2));
elapsedValue.setText(initializing ? pending() : Form.duration(progress.elapsed(), 2));
memoryValue.setText(snapshot.usedMemoryBytes() < 0 ? pending() : text(DesktopUiMessages.PREGEN_MEMORY_USAGE,
MessageArgument.trusted("used", Form.memSize(snapshot.usedMemoryBytes(), 1)),
MessageArgument.trusted("usage", Form.pc(snapshot.memoryUsage(), 0))));
pressureValue.setText(text(DesktopUiMessages.PREGEN_PRESSURE_VALUE,
MessageArgument.trusted("rate", Form.memSize(snapshot.allocationBytesPerSecond(), 0))));
String method = progress.method() == null ? pending() : progress.method();
if (snapshot.cached()) {
method = text(DesktopUiMessages.PREGEN_CACHED, MessageArgument.untrusted("method", method));
}
methodLabel.setText(text(DesktopUiMessages.PREGEN_METHOD, MessageArgument.untrusted("method", method)));
failureLabel.setText(progress.failed() > 0 ? text(DesktopUiMessages.PREGEN_FAILED,
MessageArgument.trusted("count", Form.f(progress.failed()))) : "");
failureLabel.setToolTipText(snapshot.failure());
if (snapshot.failure() != null) {
failureLabel.setText(text(DesktopUiMessages.PREGEN_ERROR_DETAILS));
}
}
private void setRenderingEnabled(boolean enabled) {
renderingEnabled = enabled && !disposed;
if (renderingEnabled) {
refresh();
repaintTimer.start();
} else {
repaintTimer.stop();
}
}
private void disposeRenderer() {
if (disposed) {
return;
@@ -127,79 +401,32 @@ public final class PregenRenderer extends JPanel implements KeyListener {
renderingEnabled = false;
frame = null;
repaintTimer.stop();
lock.lock();
try {
pending.clear();
} finally {
lock.unlock();
}
imageGraphics.dispose();
map.disposeMap();
}
@Override
public void paint(Graphics gx) {
Graphics2D g = (Graphics2D) gx;
Long2ObjectLinkedOpenHashMap<Color> batch;
lock.lock();
try {
batch = pending;
pending = new Long2ObjectLinkedOpenHashMap<>();
} finally {
lock.unlock();
}
for (Long2ObjectMap.Entry<Color> entry : batch.long2ObjectEntrySet()) {
try {
long key = entry.getLongKey();
draw((int) (key >> 32), (int) key, entry.getValue(), imageGraphics);
} catch (Throwable e) {
IrisLogging.reportError(e);
}
}
g.drawImage(image, 0, 0, getParent().getWidth(), getParent().getHeight(), (img, infoflags, x, y, width, height) -> true);
g.setColor(Color.WHITE);
g.setFont(new Font("Hevetica", Font.BOLD, 13));
String[] prog = source.progress();
int h = g.getFontMetrics().getHeight() + 5;
int hh = 20;
if (source.paused()) {
g.drawString(IrisLanguage.plain(DesktopUiMessages.PREGEN_PAUSED), 20, hh += h);
g.drawString(IrisLanguage.plain(DesktopUiMessages.PREGEN_RESUME_HINT), 20, hh += h);
} else {
for (String i : prog) {
g.drawString(i, 20, hh += h);
}
g.drawString(IrisLanguage.plain(DesktopUiMessages.PREGEN_PAUSE_HINT), 20, hh += h);
}
private static JPanel panel(LayoutManager layout, Color background) {
JPanel panel = new JPanel(layout);
panel.setBackground(background);
return panel;
}
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);
int za = (int) M.lerp(0, res, pha);
bg.setColor(c);
bg.fillRect(x, z, xa - x, za - z);
private static JLabel label(String text, Font font, Color foreground) {
JLabel label = new JLabel(text);
label.putClientProperty("html.disable", Boolean.TRUE);
label.setFont(font);
label.setForeground(foreground);
return label;
}
@Override
public void keyTyped(KeyEvent e) {
private static String pending() {
return text(DesktopUiMessages.PREGEN_METHOD_PENDING);
}
@Override
public void keyPressed(KeyEvent e) {
private static String rate(double rate) {
return text(DesktopUiMessages.PREGEN_RATE, MessageArgument.trusted("rate", Form.f(rate, 1)));
}
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_P && onPause != null) {
onPause.run();
}
private static String text(TextKey key, MessageArgument... arguments) {
return IrisLanguage.plain(key, arguments);
}
}
@@ -34,11 +34,8 @@ import art.arcane.iris.core.pregenerator.PregenTask;
import art.arcane.iris.core.pregenerator.PregeneratorMethod;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.history.SavedBiomeUnavailableException;
import art.arcane.volmlib.util.format.Form;
import art.arcane.volmlib.util.format.MemoryMonitor;
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;
@@ -59,14 +56,6 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
// 60s permit drain + 120s flush + plate reclaim), or a routine drain trips the deadline
// and aborts the engine shutdown sequence mid-teardown.
private static final long WORLD_SHUTDOWN_TIMEOUT_MILLIS = 200_000L;
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
private static final Color COLOR_BLACK = parseColor("#4d7d5b");
private static final Color COLOR_MANTLE = parseColor("#3c2773");
private static final Color COLOR_GENERATING = parseColor("#66967f");
private static final Color COLOR_NETWORK = parseColor("#a863c2");
private static final Color COLOR_NETWORK_GENERATING = parseColor("#836b8c");
private static final Color COLOR_GENERATED = parseColor("#65c295");
private static final Color COLOR_CLEANED = parseColor("#34eb93");
private static final AtomicReference<PregeneratorJob> instance = new AtomicReference<>();
private final MemoryMonitor monitor;
private final PregenTask task;
@@ -75,14 +64,17 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
private final List<Consumer<Double>> onProgress = new CopyOnWriteArrayList<>();
private final List<Runnable> whenDone = new CopyOnWriteArrayList<>();
private final IrisPregenerator pregenerator;
private final Position2 min;
private final Position2 max;
private final PregenRenderSnapshot.Bounds bounds;
private final Engine engine;
private final ExecutorService service;
private final Thread worker;
private final PregenPhaseTracker apiPhases = new PregenPhaseTracker();
private PregenRenderer renderer;
private String[] info;
private volatile PregenRenderer renderer;
private volatile PregenRenderSnapshot renderSnapshot;
private volatile boolean closed;
private volatile boolean finished;
private volatile String failure;
private boolean lastCached;
private volatile double lastChunksPerSecond = 0D;
private volatile double lastOverallChunksPerSecond = 0D;
private volatile double lastThirtySecondChunksPerSecond = 0D;
@@ -102,11 +94,13 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
monitor = new MemoryMonitor(50);
saving = new AtomicBoolean(false);
stopRequested = 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);
int[] chunkBounds = task.chunkBounds();
bounds = new PregenRenderSnapshot.Bounds(chunkBounds[0], chunkBounds[1], chunkBounds[2], chunkBounds[3]);
lastTotalChunks = task.chunkCount();
lastChunksRemaining = lastTotalChunks;
publishView(PregenRenderSnapshot.Phase.INITIALIZING);
service = new ThreadPoolExecutor(
1,
1,
@@ -142,7 +136,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
// teardown with the new job's generation. Replacement goes through
// shutdownAndWait first, matching the modded adapter's rejection contract.
if (!instance.compareAndSet(null, this)) {
monitor.close();
close();
service.shutdown();
throw new IllegalStateException("An Iris pregeneration job is already running; stop it first.");
}
@@ -152,7 +146,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
// Un-publish: a worker that never started can never run onClose(), so nothing
// else would ever clear this instance via the normal path.
instance.compareAndSet(this, null);
monitor.close();
close();
service.shutdown();
throw startFailure;
}
@@ -170,23 +164,14 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
onClose();
return;
}
computeBounds();
pregenerator.start();
} catch (Throwable failure) {
this.failure = failure.toString();
IrisLogging.reportError("Pregen startup failed.", failure);
onClose();
}
}
private void computeBounds() {
task.iterateAllChunks((xx, zz) -> {
min.setX(Math.min(xx, min.getX()));
min.setZ(Math.min(zz, min.getZ()));
max.setX(Math.max(xx, max.getX()));
max.setZ(Math.max(zz, max.getZ()));
});
}
public static boolean shutdownInstance() {
PregeneratorJob inst = instance.get();
if (inst == null) {
@@ -245,15 +230,20 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
public static boolean pauseResume() {
PregeneratorJob inst = instance.get();
if (inst == null) {
return inst != null && inst.togglePause();
}
synchronized boolean togglePause() {
if (finished || stopRequested.get() || failure != null) {
return false;
}
if (isPaused()) {
inst.pregenerator.resume();
if (paused()) {
pregenerator.resume();
} else {
inst.pregenerator.pause();
pregenerator.pause();
}
publishView(paused() ? PregenRenderSnapshot.Phase.PAUSED : PregenRenderSnapshot.Phase.GENERATING);
return true;
}
@@ -287,7 +277,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
return inst == null ? null : inst.snapshot();
}
public PregenProgress snapshot() {
public synchronized PregenProgress snapshot() {
double percent = lastTotalChunks <= 0 ? 0D : ((double) lastGenerated / (double) lastTotalChunks) * 100D;
return new PregenProgress(
percent,
@@ -330,18 +320,6 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
return worldIdentity.equals(engine.getWorld().identity());
}
private static Color parseColor(String c) {
String v = (c.startsWith("#") ? c : "#" + c).trim();
try {
return Color.decode(v);
} catch (Throwable e) {
IrisLogging.reportError(e);
IrisLogging.error("Error Parsing 'color', (" + c + ")");
}
return Color.RED;
}
public Mantle getMantle() {
return pregenerator.getMantle();
}
@@ -357,16 +335,17 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
}
public void drawRegion(int x, int z, Color color) {
J.a(() -> task.iterateChunks(x, z, (xx, zz) -> {
draw(xx, zz, color);
J.sleep(3);
}));
PregenRenderer activeRenderer = renderer;
if (activeRenderer == null || closed) {
return;
}
task.iterateChunks(x, z, (chunkX, chunkZ) -> activeRenderer.submit(chunkX, chunkZ, color));
}
public void draw(int x, int z, Color color) {
try {
PregenRenderer activeRenderer = renderer;
if (activeRenderer != null && activeRenderer.isVisibleFrame()) {
if (activeRenderer != null) {
activeRenderer.submit(x, z, color);
}
} catch (Throwable error) {
@@ -384,11 +363,13 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
if (!stopRequested.compareAndSet(false, true)) {
return;
}
publishView(PregenRenderSnapshot.Phase.STOPPING);
pregenerator.close();
worker.interrupt();
}
public void close() {
closed = true;
try {
monitor.close();
PregenRenderer activeRenderer = renderer;
@@ -403,8 +384,15 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
public void open() {
EventQueue.invokeLater(() -> {
if (closed) {
return;
}
try {
renderer = PregenRenderer.open(IrisLanguage.plain(DesktopUiMessages.PREGEN_TITLE), this, PregeneratorJob::pauseResume);
PregenRenderer opened = PregenRenderer.open(IrisLanguage.plain(DesktopUiMessages.PREGEN_TITLE), this, this::togglePause);
renderer = opened;
if (closed) {
opened.close();
}
} catch (Throwable error) {
IrisLogging.reportError(error);
IrisLogging.error("Error opening pregen gui");
@@ -415,45 +403,21 @@ 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;
lastEta = eta;
lastElapsed = elapsed;
lastMethod = method;
info = new String[]{
IrisLanguage.plain(
paused() ? DesktopUiMessages.PREGEN_PROGRESS_PAUSED
: 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("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,
MessageArgument.trusted("remaining", Form.duration(eta, 2)),
MessageArgument.trusted("elapsed", Form.duration(elapsed, 2))
),
IrisLanguage.plain(DesktopUiMessages.PREGEN_METHOD, MessageArgument.untrusted("method", String.valueOf(method))),
IrisLanguage.plain(
DesktopUiMessages.PREGEN_MEMORY,
MessageArgument.trusted("used", Form.memSize(monitor.getUsedBytes(), 2)),
MessageArgument.trusted("usage", Form.pc(monitor.getUsagePercent(), 0)),
MessageArgument.trusted("pressure", Form.memSize(monitor.getPressure(), 0))
)
};
synchronized (this) {
lastChunksPerSecond = chunksPerSecond;
lastOverallChunksPerSecond = rateSnapshot.overall();
lastThirtySecondChunksPerSecond = rateSnapshot.thirtySecond();
lastSixtySecondChunksPerSecond = rateSnapshot.sixtySecond();
lastChunksRemaining = chunksRemaining;
lastGenerated = generated;
lastTotalChunks = totalChunks;
lastEta = eta;
lastElapsed = elapsed;
lastMethod = method;
lastCached = cached;
publishView(paused() ? PregenRenderSnapshot.Phase.PAUSED
: saving.getAndSet(false) ? PregenRenderSnapshot.Phase.SAVING : PregenRenderSnapshot.Phase.GENERATING);
}
for (Consumer<Double> i : onProgress) {
i.accept(percent);
@@ -488,12 +452,12 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
@Override
public void onChunkGenerating(int x, int z) {
draw(x, z, COLOR_GENERATING);
draw(x, z, PregenRenderer.GENERATING);
}
@Override
public void onChunkGenerated(int x, int z, boolean cached) {
drawChunkPreview(x, z, COLOR_GENERATED);
drawChunkPreview(x, z, PregenRenderer.GENERATED);
}
@Override
@@ -528,7 +492,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
@Override
public void onNetworkStarted(int x, int z) {
drawRegion(x, z, COLOR_NETWORK);
drawRegion(x, z, PregenRenderer.NETWORK);
}
@Override
@@ -543,18 +507,25 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
@Override
public void onNetworkGeneratedChunk(int x, int z) {
draw(x, z, COLOR_NETWORK_GENERATING);
draw(x, z, PregenRenderer.NETWORK_GENERATING);
}
@Override
public void onNetworkDownloaded(int x, int z) {
drawRegion(x, z, COLOR_NETWORK);
drawRegion(x, z, PregenRenderer.NETWORK);
}
@Override
public void onClose() {
finished = true;
dispatchApiPhases(apiPhases.onClose(reachedTotal()));
close();
publishView(failure != null ? PregenRenderSnapshot.Phase.ERROR
: reachedTotal() ? PregenRenderSnapshot.Phase.COMPLETED : PregenRenderSnapshot.Phase.STOPPING);
if (failure == null) {
close();
} else {
monitor.close();
}
instance.compareAndSet(this, null);
whenDone.forEach(Runnable::run);
service.shutdownNow();
@@ -563,40 +534,47 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
@Override
public void onSaving() {
saving.set(true);
publishView(PregenRenderSnapshot.Phase.SAVING);
dispatchApiPhases(apiPhases.onSaving());
}
@Override
public void onChunkExistsInRegionGen(int x, int z) {
drawChunkPreview(x, z, COLOR_EXISTS);
drawChunkPreview(x, z, PregenRenderer.EXISTS);
}
@Override
public Position2 max() {
return max;
}
@Override
public Position2 min() {
return min;
}
@Override
public boolean paused() {
return pregenerator.paused();
}
@Override
public String[] progress() {
return info;
public PregenRenderSnapshot renderSnapshot() {
return renderSnapshot;
}
private synchronized void publishView(PregenRenderSnapshot.Phase phase) {
if (failure != null) {
phase = PregenRenderSnapshot.Phase.ERROR;
} else if (finished) {
phase = reachedTotal() ? PregenRenderSnapshot.Phase.COMPLETED : PregenRenderSnapshot.Phase.STOPPING;
} else if (stopRequested.get()) {
phase = PregenRenderSnapshot.Phase.STOPPING;
} else if (paused()) {
phase = PregenRenderSnapshot.Phase.PAUSED;
}
renderSnapshot = new PregenRenderSnapshot(bounds, snapshot(), phase, lastCached,
monitor.getUsedBytes(), monitor.getUsagePercent(), monitor.getPressure(), failure);
}
private void drawChunkPreview(int x, int z, Color statusColor) {
PregenRenderer activeRenderer = renderer;
if (activeRenderer == null || !activeRenderer.isVisibleFrame() || service.isShutdown()) {
if (activeRenderer == null) {
return;
}
draw(x, z, statusColor);
if (!activeRenderer.isVisibleFrame() || service.isShutdown()) {
return;
}
if (engine != null) {
service.execute(() -> renderChunkPreview(x, z));
}
@@ -79,20 +79,44 @@ public final class DesktopUiMessages {
public static final TextKey NOISE_CATEGORY_SIERPINSKI = TextKey.of("iris.desktop.noise.category.sierpinski", "Sierpinski");
public static final TextKey NOISE_CATEGORY_UTILITY = TextKey.of("iris.desktop.noise.category.utility", "Utility");
public static final TextKey NOISE_CATEGORY_OTHER = TextKey.of("iris.desktop.noise.category.other", "Other");
public static final TextKey PREGEN_INITIALIZING = TextKey.of("iris.desktop.pregen.initializing", "Initializing...");
public static final TextKey PREGEN_TITLE = TextKey.of("iris.desktop.pregen.title", "Pregen View");
public static final TextKey PREGEN_INITIALIZING = TextKey.of("iris.desktop.pregen.initializing", "Preparing generation");
public static final TextKey PREGEN_TITLE = TextKey.of("iris.desktop.pregen.title", "Pregeneration");
public static final TextKey PREGEN_METHOD_PENDING = TextKey.of("iris.desktop.pregen.method_pending", "Pending");
public static final TextKey PREGEN_PAUSED = TextKey.of("iris.desktop.pregen.paused", "PAUSED");
public static final TextKey PREGEN_PAUSED = TextKey.of("iris.desktop.pregen.paused", "Paused");
public static final TextKey PREGEN_RESUME_HINT = TextKey.of("iris.desktop.pregen.resume_hint", "Press P to resume");
public static final TextKey PREGEN_PAUSE_HINT = TextKey.of("iris.desktop.pregen.pause_hint", "Press P to pause");
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: 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");
public static final TextKey PREGEN_PAUSE = TextKey.of("iris.desktop.pregen.pause", "Pause");
public static final TextKey PREGEN_RESUME = TextKey.of("iris.desktop.pregen.resume", "Resume");
public static final TextKey PREGEN_GENERATING = TextKey.of("iris.desktop.pregen.generating", "Generating");
public static final TextKey PREGEN_SAVING = TextKey.of("iris.desktop.pregen.saving", "Saving");
public static final TextKey PREGEN_STOPPING = TextKey.of("iris.desktop.pregen.stopping", "Stopping");
public static final TextKey PREGEN_COMPLETED = TextKey.of("iris.desktop.pregen.completed", "Complete");
public static final TextKey PREGEN_ERROR = TextKey.of("iris.desktop.pregen.error", "Generation failed");
public static final TextKey PREGEN_CONTROL_FAILED = TextKey.of("iris.desktop.pregen.control_failed", "Pause control failed · see server log");
public static final TextKey PREGEN_ERROR_DETAILS = TextKey.of("iris.desktop.pregen.error_details", "See server log for details");
public static final TextKey PREGEN_PROGRESS = TextKey.of("iris.desktop.pregen.progress", "{generated} / {total} chunks");
public static final TextKey PREGEN_PERCENT = TextKey.of("iris.desktop.pregen.percent", "{percent} complete");
public static final TextKey PREGEN_CURRENT = TextKey.of("iris.desktop.pregen.current", "Current · 10 s");
public static final TextKey PREGEN_OVERALL = TextKey.of("iris.desktop.pregen.overall", "Overall");
public static final TextKey PREGEN_THIRTY = TextKey.of("iris.desktop.pregen.thirty", "30 s average");
public static final TextKey PREGEN_SIXTY = TextKey.of("iris.desktop.pregen.sixty", "60 s average");
public static final TextKey PREGEN_RATE = TextKey.of("iris.desktop.pregen.rate", "{rate} chunks/s");
public static final TextKey PREGEN_ETA = TextKey.of("iris.desktop.pregen.eta", "Remaining");
public static final TextKey PREGEN_ELAPSED = TextKey.of("iris.desktop.pregen.elapsed", "Elapsed");
public static final TextKey PREGEN_MEMORY_LABEL = TextKey.of("iris.desktop.pregen.memory_label", "Memory");
public static final TextKey PREGEN_MEMORY_USAGE = TextKey.of("iris.desktop.pregen.memory_usage", "{used} · {usage}");
public static final TextKey PREGEN_PRESSURE = TextKey.of("iris.desktop.pregen.pressure", "Allocation");
public static final TextKey PREGEN_PRESSURE_VALUE = TextKey.of("iris.desktop.pregen.pressure_value", "{rate}/s");
public static final TextKey PREGEN_METHOD = TextKey.of("iris.desktop.pregen.method", "Method: {method}");
public static final TextKey PREGEN_CACHED = TextKey.of("iris.desktop.pregen.cached", "{method} · cached");
public static final TextKey PREGEN_FAILED = TextKey.of("iris.desktop.pregen.failed", "{count} failed · see server log");
public static final TextKey PREGEN_MAP = TextKey.of("iris.desktop.pregen.map", "Generation map");
public static final TextKey PREGEN_BOUNDS = TextKey.of("iris.desktop.pregen.bounds", "Chunks X {minX} to {maxX} · Z {minZ} to {maxZ}");
public static final TextKey PREGEN_WAITING = TextKey.of("iris.desktop.pregen.waiting", "Waiting");
public static final TextKey PREGEN_READY = TextKey.of("iris.desktop.pregen.ready", "Ready");
public static final TextKey PREGEN_EXISTING = TextKey.of("iris.desktop.pregen.existing", "Existing");
public static final TextKey PREGEN_NETWORK = TextKey.of("iris.desktop.pregen.network", "Network");
public static final TextKey PREGEN_TERRAIN_HINT = TextKey.of("iris.desktop.pregen.terrain_hint", "Finished chunks show terrain colors");
public static final TextKey IMAGEMAP_TITLE = TextKey.of("iris.desktop.imagemap.title", "Image Map Studio");
public static final TextKey IMAGEMAP_PRESET = TextKey.of("iris.desktop.imagemap.preset", "Preset:");
public static final TextKey IMAGEMAP_LOAD = TextKey.of("iris.desktop.imagemap.load", "Load");
@@ -179,10 +203,17 @@ public final class DesktopUiMessages {
NOISE_CATEGORY_CELLULAR, NOISE_CATEGORY_IRIS, NOISE_CATEGORY_CLOVER, NOISE_CATEGORY_HEXAGON,
NOISE_CATEGORY_VASCULAR, NOISE_CATEGORY_GLOBE, NOISE_CATEGORY_CUBIC, NOISE_CATEGORY_FRACTAL,
NOISE_CATEGORY_STATIC, NOISE_CATEGORY_NOWHERE, NOISE_CATEGORY_SIERPINSKI,
NOISE_CATEGORY_UTILITY, NOISE_CATEGORY_OTHER, PREGEN_INITIALIZING, PREGEN_TITLE,
PREGEN_METHOD_PENDING, PREGEN_PAUSED, PREGEN_RESUME_HINT, PREGEN_PAUSE_HINT,
PREGEN_PROGRESS_PAUSED, PREGEN_PROGRESS_SAVING, PREGEN_PROGRESS_GENERATING, PREGEN_SPEED,
PREGEN_SPEED_CACHED, PREGEN_TIME, PREGEN_METHOD, PREGEN_MEMORY,
NOISE_CATEGORY_UTILITY, NOISE_CATEGORY_OTHER,
PREGEN_INITIALIZING, PREGEN_TITLE, PREGEN_METHOD_PENDING, PREGEN_PAUSED,
PREGEN_RESUME_HINT, PREGEN_PAUSE_HINT, PREGEN_PAUSE, PREGEN_RESUME,
PREGEN_GENERATING, PREGEN_SAVING, PREGEN_STOPPING, PREGEN_COMPLETED,
PREGEN_ERROR, PREGEN_CONTROL_FAILED, PREGEN_ERROR_DETAILS, PREGEN_PROGRESS,
PREGEN_PERCENT, PREGEN_CURRENT, PREGEN_OVERALL, PREGEN_THIRTY,
PREGEN_SIXTY, PREGEN_RATE, PREGEN_ETA, PREGEN_ELAPSED,
PREGEN_MEMORY_LABEL, PREGEN_MEMORY_USAGE, PREGEN_PRESSURE, PREGEN_PRESSURE_VALUE,
PREGEN_METHOD, PREGEN_CACHED, PREGEN_FAILED, PREGEN_MAP,
PREGEN_BOUNDS, PREGEN_WAITING, PREGEN_READY, PREGEN_EXISTING,
PREGEN_NETWORK, PREGEN_TERRAIN_HINT,
IMAGEMAP_TITLE, IMAGEMAP_PRESET, IMAGEMAP_LOAD, IMAGEMAP_IMPORT_PNG,
IMAGEMAP_REPLACE_PNG, IMAGEMAP_PREVIEW, IMAGEMAP_EXPORT, IMAGEMAP_METADATA,
IMAGEMAP_RESOURCE, IMAGEMAP_COORDINATES, IMAGEMAP_BINDING_KEY, IMAGEMAP_MAP_KEY,
@@ -215,6 +215,11 @@ public class PregenTask {
return new int[]{bound.minX(), bound.minZ(), bound.maxX(), bound.maxZ()};
}
public int[] chunkBounds() {
Bound bound = bounds.chunk();
return new int[]{bound.minX(), bound.minZ(), bound.maxX(), bound.maxZ()};
}
public long chunkCount() {
Bound bound = bounds.chunk();
return (long) bound.sizeX() * bound.sizeZ();
@@ -992,6 +992,10 @@ public class IrisEngine implements Engine {
}
public Optional<GenerationHistoryRuntimeRouter> getGenerationHistoryRuntimeRouter() {
GenerationHistoryRuntimeRouter router = generationHistoryRuntimeRouter;
if (router != null) {
return Optional.of(router);
}
synchronized (generationHistoryRuntimeRouterLock) {
return Optional.ofNullable(generationHistoryRuntimeRouter);
}
@@ -1001,7 +1005,10 @@ public class IrisEngine implements Engine {
int blockX,
int blockZ
) throws IOException {
GenerationHistoryRuntimeRouter router;
GenerationHistoryRuntimeRouter router = generationHistoryRuntimeRouter;
if (router != null) {
return router.openCoordinateScope(blockX, blockZ);
}
synchronized (generationHistoryRuntimeRouterLock) {
router = generationHistoryRuntimeRouter;
if (router == null && generationHistoryRoutingRequired) {
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "pausiert",
"iris.desktop.pregen.resume_hint": "P drücken, um wieder aufzunehmen",
"iris.desktop.pregen.pause_hint": "P drücken, um zu pausieren",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Pack '{pack}': Inhalte in Minecraft {version} nicht verfügbar",
"iris.modded.moddedpackcommands.compat_none": "Pack '{pack}' verwendet keine Inhalte, die in Minecraft {version} fehlen.",
"iris.modded.moddedpackcommands.compat_remedy": "Aktualisiere den Server auf ein neueres Minecraft, um diese Inhalte wiederherzustellen, oder deklariere Ersatzwerte (Dimension blockFallbacks, Block backup).",
"iris.modded.help.entry.command.compat_content": "Inhalte anzeigen, die in dieser Minecraft-Version nicht generiert werden können"
"iris.modded.help.entry.command.compat_content": "Inhalte anzeigen, die in dieser Minecraft-Version nicht generiert werden können",
"iris.desktop.pregen.pause": "Pausieren",
"iris.desktop.pregen.resume": "Fortsetzen",
"iris.desktop.pregen.generating": "Generierung",
"iris.desktop.pregen.saving": "Speichern",
"iris.desktop.pregen.stopping": "Wird beendet",
"iris.desktop.pregen.completed": "Abgeschlossen",
"iris.desktop.pregen.error": "Generierung fehlgeschlagen",
"iris.desktop.pregen.control_failed": "Pause fehlgeschlagen · siehe Serverprotokoll",
"iris.desktop.pregen.error_details": "Details im Serverprotokoll",
"iris.desktop.pregen.progress": "{generated} / {total} Chunks",
"iris.desktop.pregen.percent": "{percent} abgeschlossen",
"iris.desktop.pregen.current": "Aktuell · 10 s",
"iris.desktop.pregen.overall": "Gesamt",
"iris.desktop.pregen.thirty": "30-s-Mittel",
"iris.desktop.pregen.sixty": "60-s-Mittel",
"iris.desktop.pregen.rate": "{rate} Chunks/s",
"iris.desktop.pregen.eta": "Verbleibend",
"iris.desktop.pregen.elapsed": "Verstrichen",
"iris.desktop.pregen.memory_label": "Speicher",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Speicherzuweisung",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · zwischengespeichert",
"iris.desktop.pregen.failed": "{count} fehlgeschlagen · siehe Serverprotokoll",
"iris.desktop.pregen.map": "Generierungskarte",
"iris.desktop.pregen.bounds": "Chunks X {minX} bis {maxX} · Z {minZ} bis {maxZ}",
"iris.desktop.pregen.waiting": "Wartend",
"iris.desktop.pregen.ready": "Bereit",
"iris.desktop.pregen.existing": "Vorhanden",
"iris.desktop.pregen.network": "Netzwerk",
"iris.desktop.pregen.terrain_hint": "Fertige Chunks zeigen Geländefarben"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "PAUSADO",
"iris.desktop.pregen.resume_hint": "Pulsa P para reanudar",
"iris.desktop.pregen.pause_hint": "Pulsa P para pausar",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Pack '{pack}': contenido no disponible en Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "El pack '{pack}' no usa contenido que falte en Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Actualiza el servidor a un Minecraft más reciente para recuperar este contenido, o declara alternativas (blockFallbacks de la dimensión, backup del bloque).",
"iris.modded.help.entry.command.compat_content": "Muestra el contenido que no puede generarse en esta versión de Minecraft"
"iris.modded.help.entry.command.compat_content": "Muestra el contenido que no puede generarse en esta versión de Minecraft",
"iris.desktop.pregen.pause": "Pausar",
"iris.desktop.pregen.resume": "Reanudar",
"iris.desktop.pregen.generating": "Generando",
"iris.desktop.pregen.saving": "Guardando",
"iris.desktop.pregen.stopping": "Deteniendo",
"iris.desktop.pregen.completed": "Completado",
"iris.desktop.pregen.error": "Error de generación",
"iris.desktop.pregen.control_failed": "Error al pausar · consulta el registro del servidor",
"iris.desktop.pregen.error_details": "Detalles en el registro del servidor",
"iris.desktop.pregen.progress": "{generated} / {total} chunks",
"iris.desktop.pregen.percent": "{percent} completado",
"iris.desktop.pregen.current": "Actual · 10 s",
"iris.desktop.pregen.overall": "Global",
"iris.desktop.pregen.thirty": "Media de 30 s",
"iris.desktop.pregen.sixty": "Media de 60 s",
"iris.desktop.pregen.rate": "{rate} chunks/s",
"iris.desktop.pregen.eta": "Restante",
"iris.desktop.pregen.elapsed": "Transcurrido",
"iris.desktop.pregen.memory_label": "Memoria",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Asignación",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · en caché",
"iris.desktop.pregen.failed": "{count} fallidos · consulta el registro del servidor",
"iris.desktop.pregen.map": "Mapa de generación",
"iris.desktop.pregen.bounds": "Chunks X de {minX} a {maxX} · Z de {minZ} a {maxZ}",
"iris.desktop.pregen.waiting": "En espera",
"iris.desktop.pregen.ready": "Listo",
"iris.desktop.pregen.existing": "Existente",
"iris.desktop.pregen.network": "Red",
"iris.desktop.pregen.terrain_hint": "Los chunks terminados muestran los colores del terreno"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "keskeytetty",
"iris.desktop.pregen.resume_hint": "Paina P jatkaaksesi",
"iris.desktop.pregen.pause_hint": "Paina P taukoa varten",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Paketti '{pack}': sisältö ei ole käytettävissä Minecraft {version} -versiossa",
"iris.modded.moddedpackcommands.compat_none": "Paketti '{pack}' ei käytä sisältöä, joka puuttuisi Minecraft {version} -versiosta.",
"iris.modded.moddedpackcommands.compat_remedy": "Päivitä palvelin uudempaan Minecraft-versioon palauttaaksesi tämän sisällön tai määritä varasisältö (ulottuvuuden blockFallbacks, lohkon backup).",
"iris.modded.help.entry.command.compat_content": "Näytä sisältö, jota ei voi luoda tässä Minecraft-versiossa"
"iris.modded.help.entry.command.compat_content": "Näytä sisältö, jota ei voi luoda tässä Minecraft-versiossa",
"iris.desktop.pregen.pause": "Keskeytä",
"iris.desktop.pregen.resume": "Jatka",
"iris.desktop.pregen.generating": "Luodaan",
"iris.desktop.pregen.saving": "Tallennetaan",
"iris.desktop.pregen.stopping": "Pysäytetään",
"iris.desktop.pregen.completed": "Valmis",
"iris.desktop.pregen.error": "Luonti epäonnistui",
"iris.desktop.pregen.control_failed": "Keskeytys epäonnistui · katso palvelinloki",
"iris.desktop.pregen.error_details": "Lisätiedot palvelinlokissa",
"iris.desktop.pregen.progress": "{generated} / {total} lohkoa",
"iris.desktop.pregen.percent": "{percent} valmiina",
"iris.desktop.pregen.current": "Nykyinen · 10 s",
"iris.desktop.pregen.overall": "Kokonaiskeskiarvo",
"iris.desktop.pregen.thirty": "30 s keskiarvo",
"iris.desktop.pregen.sixty": "60 s keskiarvo",
"iris.desktop.pregen.rate": "{rate} lohkoa/s",
"iris.desktop.pregen.eta": "Jäljellä",
"iris.desktop.pregen.elapsed": "Kulunut",
"iris.desktop.pregen.memory_label": "Muisti",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Muistivaraus",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · välimuistissa",
"iris.desktop.pregen.failed": "{count} epäonnistui · katso palvelinloki",
"iris.desktop.pregen.map": "Luontikartta",
"iris.desktop.pregen.bounds": "Lohkot X {minX}–{maxX} · Z {minZ}–{maxZ}",
"iris.desktop.pregen.waiting": "Odottaa",
"iris.desktop.pregen.ready": "Valmis",
"iris.desktop.pregen.existing": "Olemassa",
"iris.desktop.pregen.network": "Verkko",
"iris.desktop.pregen.terrain_hint": "Valmiit lohkot näyttävät maaston värit"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "EN PAUSE",
"iris.desktop.pregen.resume_hint": "Appuyez sur P pour reprendre",
"iris.desktop.pregen.pause_hint": "Appuyez sur P pour mettre en pause",
"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 : {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",
"iris.modded.help.entry.command.what.here": "Inspecter le biome Iris, la région, le biome souterrain, la surface et le chunk à votre position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Pack '{pack}' : contenu indisponible sur Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Le pack '{pack}' n'utilise aucun contenu absent de Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Mettez le serveur à jour vers un Minecraft plus récent pour restaurer ce contenu, ou déclarez des replis (blockFallbacks de la dimension, backup du bloc).",
"iris.modded.help.entry.command.compat_content": "Afficher le contenu qui ne peut pas être généré sur cette version de Minecraft"
"iris.modded.help.entry.command.compat_content": "Afficher le contenu qui ne peut pas être généré sur cette version de Minecraft",
"iris.desktop.pregen.pause": "Pause",
"iris.desktop.pregen.resume": "Reprendre",
"iris.desktop.pregen.generating": "Génération",
"iris.desktop.pregen.saving": "Enregistrement",
"iris.desktop.pregen.stopping": "Arrêt en cours",
"iris.desktop.pregen.completed": "Terminé",
"iris.desktop.pregen.error": "Échec de la génération",
"iris.desktop.pregen.control_failed": "Échec de la pause · voir le journal serveur",
"iris.desktop.pregen.error_details": "Détails dans le journal serveur",
"iris.desktop.pregen.progress": "{generated} / {total} chunks",
"iris.desktop.pregen.percent": "{percent} terminé",
"iris.desktop.pregen.current": "Actuel · 10 s",
"iris.desktop.pregen.overall": "Global",
"iris.desktop.pregen.thirty": "Moyenne sur 30 s",
"iris.desktop.pregen.sixty": "Moyenne sur 60 s",
"iris.desktop.pregen.rate": "{rate} chunks/s",
"iris.desktop.pregen.eta": "Restant",
"iris.desktop.pregen.elapsed": "Écoulé",
"iris.desktop.pregen.memory_label": "Mémoire",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Allocation",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · en cache",
"iris.desktop.pregen.failed": "{count} échecs · voir le journal serveur",
"iris.desktop.pregen.map": "Carte de génération",
"iris.desktop.pregen.bounds": "Chunks X de {minX} à {maxX} · Z de {minZ} à {maxZ}",
"iris.desktop.pregen.waiting": "En attente",
"iris.desktop.pregen.ready": "Prêt",
"iris.desktop.pregen.existing": "Existant",
"iris.desktop.pregen.network": "Réseau",
"iris.desktop.pregen.terrain_hint": "Les chunks terminés affichent les couleurs du terrain"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "מושהה",
"iris.desktop.pregen.resume_hint": "לחץ על P לחדש",
"iris.desktop.pregen.pause_hint": "הקש P כדי לעצור",
"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": "מהירות: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "חבילה '{pack}': תוכן לא זמין ב-Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "החבילה '{pack}' אינה משתמשת בתוכן שחסר ב-Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "עדכן את השרת ל-Minecraft חדש יותר כדי לשחזר את התוכן הזה, או הגדר חלופות (blockFallbacks של הממד, backup של הבלוק).",
"iris.modded.help.entry.command.compat_content": "הצג תוכן שלא ניתן ליצור בגרסת Minecraft הזו"
"iris.modded.help.entry.command.compat_content": "הצג תוכן שלא ניתן ליצור בגרסת Minecraft הזו",
"iris.desktop.pregen.pause": "השהיה",
"iris.desktop.pregen.resume": "המשך",
"iris.desktop.pregen.generating": "יצירה",
"iris.desktop.pregen.saving": "שמירה",
"iris.desktop.pregen.stopping": "עצירה",
"iris.desktop.pregen.completed": "הושלם",
"iris.desktop.pregen.error": "היצירה נכשלה",
"iris.desktop.pregen.control_failed": "ההשהיה נכשלה · פרטים ביומן השרת",
"iris.desktop.pregen.error_details": "פרטים ביומן השרת",
"iris.desktop.pregen.progress": "{generated} / {total} צ׳אנקים",
"iris.desktop.pregen.percent": "{percent} הושלמו",
"iris.desktop.pregen.current": "נוכחי · 10 שנ׳",
"iris.desktop.pregen.overall": "כולל",
"iris.desktop.pregen.thirty": "ממוצע 30 שנ׳",
"iris.desktop.pregen.sixty": "ממוצע 60 שנ׳",
"iris.desktop.pregen.rate": "{rate} צ׳אנקים/שנ׳",
"iris.desktop.pregen.eta": "נותר",
"iris.desktop.pregen.elapsed": "חלף",
"iris.desktop.pregen.memory_label": "זיכרון",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "הקצאה",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · מהמטמון",
"iris.desktop.pregen.failed": "{count} נכשלו · פרטים ביומן השרת",
"iris.desktop.pregen.map": "מפת יצירה",
"iris.desktop.pregen.bounds": "צ׳אנקים X מ־{minX} עד {maxX} · Z מ־{minZ} עד {maxZ}",
"iris.desktop.pregen.waiting": "בהמתנה",
"iris.desktop.pregen.ready": "מוכן",
"iris.desktop.pregen.existing": "קיים",
"iris.desktop.pregen.network": "רשת",
"iris.desktop.pregen.terrain_hint": "צ׳אנקים שהושלמו מציגים את צבעי השטח"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "in pausa",
"iris.desktop.pregen.resume_hint": "Premere P per riprendere",
"iris.desktop.pregen.pause_hint": "Premere P per mettere in pausa",
"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à: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Pack '{pack}': contenuti non disponibili su Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Il pack '{pack}' non usa contenuti assenti da Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Aggiorna il server a un Minecraft più recente per ripristinare questi contenuti, oppure dichiara delle alternative (blockFallbacks della dimensione, backup del blocco).",
"iris.modded.help.entry.command.compat_content": "Mostra i contenuti che non possono essere generati su questa versione di Minecraft"
"iris.modded.help.entry.command.compat_content": "Mostra i contenuti che non possono essere generati su questa versione di Minecraft",
"iris.desktop.pregen.pause": "Pausa",
"iris.desktop.pregen.resume": "Riprendi",
"iris.desktop.pregen.generating": "Generazione",
"iris.desktop.pregen.saving": "Salvataggio",
"iris.desktop.pregen.stopping": "Arresto in corso",
"iris.desktop.pregen.completed": "Completato",
"iris.desktop.pregen.error": "Generazione fallita",
"iris.desktop.pregen.control_failed": "Pausa fallita · consulta il log del server",
"iris.desktop.pregen.error_details": "Dettagli nel log del server",
"iris.desktop.pregen.progress": "{generated} / {total} chunk",
"iris.desktop.pregen.percent": "{percent} completato",
"iris.desktop.pregen.current": "Attuale · 10 s",
"iris.desktop.pregen.overall": "Complessivo",
"iris.desktop.pregen.thirty": "Media su 30 s",
"iris.desktop.pregen.sixty": "Media su 60 s",
"iris.desktop.pregen.rate": "{rate} chunk/s",
"iris.desktop.pregen.eta": "Rimanente",
"iris.desktop.pregen.elapsed": "Trascorso",
"iris.desktop.pregen.memory_label": "Memoria",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Allocazione",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · in cache",
"iris.desktop.pregen.failed": "{count} falliti · consulta il log del server",
"iris.desktop.pregen.map": "Mappa di generazione",
"iris.desktop.pregen.bounds": "Chunk X da {minX} a {maxX} · Z da {minZ} a {maxZ}",
"iris.desktop.pregen.waiting": "In attesa",
"iris.desktop.pregen.ready": "Pronto",
"iris.desktop.pregen.existing": "Esistente",
"iris.desktop.pregen.network": "Rete",
"iris.desktop.pregen.terrain_hint": "I chunk completati mostrano i colori del terreno"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "一時停止中",
"iris.desktop.pregen.resume_hint": "P を押して再開",
"iris.desktop.pregen.pause_hint": "P を押して一時停止",
"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": "速度: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "パック '{pack}': Minecraft {version} では利用できない内容があります",
"iris.modded.moddedpackcommands.compat_none": "パック '{pack}' に Minecraft {version} で欠けている内容はありません。",
"iris.modded.moddedpackcommands.compat_remedy": "この内容を復元するにはサーバーを新しい Minecraft に更新するか、代替を宣言してください (ディメンションの blockFallbacks、ブロックの backup)。",
"iris.modded.help.entry.command.compat_content": "この Minecraft バージョンでは生成できない内容を表示します"
"iris.modded.help.entry.command.compat_content": "この Minecraft バージョンでは生成できない内容を表示します",
"iris.desktop.pregen.pause": "一時停止",
"iris.desktop.pregen.resume": "再開",
"iris.desktop.pregen.generating": "生成中",
"iris.desktop.pregen.saving": "保存中",
"iris.desktop.pregen.stopping": "停止中",
"iris.desktop.pregen.completed": "完了",
"iris.desktop.pregen.error": "生成に失敗",
"iris.desktop.pregen.control_failed": "一時停止に失敗 · サーバーログを確認",
"iris.desktop.pregen.error_details": "詳細はサーバーログを確認",
"iris.desktop.pregen.progress": "{generated} / {total} チャンク",
"iris.desktop.pregen.percent": "{percent} 完了",
"iris.desktop.pregen.current": "現在 · 10秒",
"iris.desktop.pregen.overall": "全体",
"iris.desktop.pregen.thirty": "30秒平均",
"iris.desktop.pregen.sixty": "60秒平均",
"iris.desktop.pregen.rate": "{rate} チャンク/秒",
"iris.desktop.pregen.eta": "残り",
"iris.desktop.pregen.elapsed": "経過",
"iris.desktop.pregen.memory_label": "メモリ",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "メモリ割り当て",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · キャッシュ済み",
"iris.desktop.pregen.failed": "{count} 件失敗 · サーバーログを確認",
"iris.desktop.pregen.map": "生成マップ",
"iris.desktop.pregen.bounds": "チャンク X {minX} ~ {maxX} · Z {minZ} ~ {maxZ}",
"iris.desktop.pregen.waiting": "待機中",
"iris.desktop.pregen.ready": "準備完了",
"iris.desktop.pregen.existing": "既存",
"iris.desktop.pregen.network": "ネットワーク",
"iris.desktop.pregen.terrain_hint": "完了したチャンクは地形の色で表示されます"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "일시 중지",
"iris.desktop.pregen.resume_hint": "재개하려면 P를 누르세요",
"iris.desktop.pregen.pause_hint": "일시 중지하려면 P를 누르세요",
"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": "속도: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "팩 '{pack}': Minecraft {version} 에서 사용할 수 없는 콘텐츠",
"iris.modded.moddedpackcommands.compat_none": "팩 '{pack}' 은 Minecraft {version} 에 없는 콘텐츠를 사용하지 않습니다.",
"iris.modded.moddedpackcommands.compat_remedy": "이 콘텐츠를 복원하려면 서버를 최신 Minecraft 로 업데이트하거나 대체를 선언하세요 (차원의 blockFallbacks, 블록의 backup).",
"iris.modded.help.entry.command.compat_content": "이 Minecraft 버전에서 생성할 수 없는 콘텐츠를 표시합니다"
"iris.modded.help.entry.command.compat_content": "이 Minecraft 버전에서 생성할 수 없는 콘텐츠를 표시합니다",
"iris.desktop.pregen.pause": "일시 중지",
"iris.desktop.pregen.resume": "계속",
"iris.desktop.pregen.generating": "생성 중",
"iris.desktop.pregen.saving": "저장 중",
"iris.desktop.pregen.stopping": "중지 중",
"iris.desktop.pregen.completed": "완료",
"iris.desktop.pregen.error": "생성 실패",
"iris.desktop.pregen.control_failed": "일시 중지 실패 · 서버 로그 확인",
"iris.desktop.pregen.error_details": "자세한 내용은 서버 로그 확인",
"iris.desktop.pregen.progress": "{generated} / {total} 청크",
"iris.desktop.pregen.percent": "{percent} 완료",
"iris.desktop.pregen.current": "현재 · 10초",
"iris.desktop.pregen.overall": "전체",
"iris.desktop.pregen.thirty": "30초 평균",
"iris.desktop.pregen.sixty": "60초 평균",
"iris.desktop.pregen.rate": "{rate} 청크/초",
"iris.desktop.pregen.eta": "남은 시간",
"iris.desktop.pregen.elapsed": "경과 시간",
"iris.desktop.pregen.memory_label": "메모리",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "메모리 할당",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · 캐시됨",
"iris.desktop.pregen.failed": "{count}개 실패 · 서버 로그 확인",
"iris.desktop.pregen.map": "생성 지도",
"iris.desktop.pregen.bounds": "청크 X {minX} ~ {maxX} · Z {minZ} ~ {maxZ}",
"iris.desktop.pregen.waiting": "대기 중",
"iris.desktop.pregen.ready": "준비됨",
"iris.desktop.pregen.existing": "기존",
"iris.desktop.pregen.network": "네트워크",
"iris.desktop.pregen.terrain_hint": "완료된 청크는 지형 색상으로 표시됩니다"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "pristabdyta",
"iris.desktop.pregen.resume_hint": "Paspauskite P norėdami atnaujinti",
"iris.desktop.pregen.pause_hint": "Paspauskite P pristabdyti",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Paketas '{pack}': turinys nepasiekiamas Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Paketas '{pack}' nenaudoja turinio, kurio trūksta Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Atnaujinkite serverį į naujesnį Minecraft, kad atkurtumėte šį turinį, arba paskelbkite atsargas (dimensijos blockFallbacks, bloko backup).",
"iris.modded.help.entry.command.compat_content": "Rodyti turinį, kurio negalima sugeneruoti šioje Minecraft versijoje"
"iris.modded.help.entry.command.compat_content": "Rodyti turinį, kurio negalima sugeneruoti šioje Minecraft versijoje",
"iris.desktop.pregen.pause": "Pristabdyti",
"iris.desktop.pregen.resume": "Tęsti",
"iris.desktop.pregen.generating": "Generuojama",
"iris.desktop.pregen.saving": "Išsaugoma",
"iris.desktop.pregen.stopping": "Stabdoma",
"iris.desktop.pregen.completed": "Baigta",
"iris.desktop.pregen.error": "Generavimas nepavyko",
"iris.desktop.pregen.control_failed": "Pristabdyti nepavyko · žr. serverio žurnalą",
"iris.desktop.pregen.error_details": "Išsamiau serverio žurnale",
"iris.desktop.pregen.progress": "{generated} / {total} sričių",
"iris.desktop.pregen.percent": "Baigta {percent}",
"iris.desktop.pregen.current": "Dabartinis · 10 s",
"iris.desktop.pregen.overall": "Bendras",
"iris.desktop.pregen.thirty": "30 s vidurkis",
"iris.desktop.pregen.sixty": "60 s vidurkis",
"iris.desktop.pregen.rate": "{rate} sričių/s",
"iris.desktop.pregen.eta": "Liko",
"iris.desktop.pregen.elapsed": "Praėjo",
"iris.desktop.pregen.memory_label": "Atmintis",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Atminties skyrimas",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · iš podėlio",
"iris.desktop.pregen.failed": "{count} klaidų · žr. serverio žurnalą",
"iris.desktop.pregen.map": "Generavimo žemėlapis",
"iris.desktop.pregen.bounds": "Sritys X nuo {minX} iki {maxX} · Z nuo {minZ} iki {maxZ}",
"iris.desktop.pregen.waiting": "Laukiama",
"iris.desktop.pregen.ready": "Paruošta",
"iris.desktop.pregen.existing": "Esamos",
"iris.desktop.pregen.network": "Tinklas",
"iris.desktop.pregen.terrain_hint": "Baigtos sritys rodo reljefo spalvas"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "gepauzeerd",
"iris.desktop.pregen.resume_hint": "Druk op P om te hervatten",
"iris.desktop.pregen.pause_hint": "Druk op P om te pauzeren",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Pack '{pack}': inhoud niet beschikbaar op Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Pack '{pack}' gebruikt geen inhoud die ontbreekt in Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Werk de server bij naar een nieuwere Minecraft om deze inhoud te herstellen, of declareer terugvallen (blockFallbacks van de dimensie, backup van het blok).",
"iris.modded.help.entry.command.compat_content": "Toon inhoud die niet kan worden gegenereerd op deze Minecraft-versie"
"iris.modded.help.entry.command.compat_content": "Toon inhoud die niet kan worden gegenereerd op deze Minecraft-versie",
"iris.desktop.pregen.pause": "Pauzeren",
"iris.desktop.pregen.resume": "Hervatten",
"iris.desktop.pregen.generating": "Genereren",
"iris.desktop.pregen.saving": "Opslaan",
"iris.desktop.pregen.stopping": "Stoppen",
"iris.desktop.pregen.completed": "Voltooid",
"iris.desktop.pregen.error": "Generatie mislukt",
"iris.desktop.pregen.control_failed": "Pauzeren mislukt · zie serverlog",
"iris.desktop.pregen.error_details": "Details in serverlog",
"iris.desktop.pregen.progress": "{generated} / {total} chunks",
"iris.desktop.pregen.percent": "{percent} voltooid",
"iris.desktop.pregen.current": "Huidig · 10 s",
"iris.desktop.pregen.overall": "Totaal",
"iris.desktop.pregen.thirty": "Gemiddelde 30 s",
"iris.desktop.pregen.sixty": "Gemiddelde 60 s",
"iris.desktop.pregen.rate": "{rate} chunks/s",
"iris.desktop.pregen.eta": "Resterend",
"iris.desktop.pregen.elapsed": "Verstreken",
"iris.desktop.pregen.memory_label": "Geheugen",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Toewijzing",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · gecachet",
"iris.desktop.pregen.failed": "{count} mislukt · zie serverlog",
"iris.desktop.pregen.map": "Generatiekaart",
"iris.desktop.pregen.bounds": "Chunks X {minX} tot {maxX} · Z {minZ} tot {maxZ}",
"iris.desktop.pregen.waiting": "Wachtend",
"iris.desktop.pregen.ready": "Gereed",
"iris.desktop.pregen.existing": "Bestaand",
"iris.desktop.pregen.network": "Netwerk",
"iris.desktop.pregen.terrain_hint": "Voltooide chunks tonen terreinkleuren"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "wstrzymano",
"iris.desktop.pregen.resume_hint": "Naciśnij P, aby wznowić",
"iris.desktop.pregen.pause_hint": "Naciśnij P, aby zatrzymać",
"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ść: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Paczka '{pack}': zawartość niedostępna w Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Paczka '{pack}' nie używa zawartości brakującej w Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Zaktualizuj serwer do nowszego Minecraft, aby przywrócić tę zawartość, albo zadeklaruj zamienniki (blockFallbacks wymiaru, backup bloku).",
"iris.modded.help.entry.command.compat_content": "Pokaż zawartość, której nie można wygenerować w tej wersji Minecraft"
"iris.modded.help.entry.command.compat_content": "Pokaż zawartość, której nie można wygenerować w tej wersji Minecraft",
"iris.desktop.pregen.pause": "Wstrzymaj",
"iris.desktop.pregen.resume": "Wznów",
"iris.desktop.pregen.generating": "Generowanie",
"iris.desktop.pregen.saving": "Zapisywanie",
"iris.desktop.pregen.stopping": "Zatrzymywanie",
"iris.desktop.pregen.completed": "Ukończono",
"iris.desktop.pregen.error": "Generowanie nie powiodło się",
"iris.desktop.pregen.control_failed": "Błąd wstrzymania · zobacz log serwera",
"iris.desktop.pregen.error_details": "Szczegóły w logu serwera",
"iris.desktop.pregen.progress": "{generated} / {total} chunków",
"iris.desktop.pregen.percent": "Ukończono {percent}",
"iris.desktop.pregen.current": "Bieżąca · 10 s",
"iris.desktop.pregen.overall": "Ogółem",
"iris.desktop.pregen.thirty": "Średnia z 30 s",
"iris.desktop.pregen.sixty": "Średnia z 60 s",
"iris.desktop.pregen.rate": "{rate} chunków/s",
"iris.desktop.pregen.eta": "Pozostało",
"iris.desktop.pregen.elapsed": "Upłynęło",
"iris.desktop.pregen.memory_label": "Pamięć",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Alokacja",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · w pamięci podręcznej",
"iris.desktop.pregen.failed": "{count} błędów · zobacz log serwera",
"iris.desktop.pregen.map": "Mapa generowania",
"iris.desktop.pregen.bounds": "Chunki X od {minX} do {maxX} · Z od {minZ} do {maxZ}",
"iris.desktop.pregen.waiting": "Oczekuje",
"iris.desktop.pregen.ready": "Gotowe",
"iris.desktop.pregen.existing": "Istniejące",
"iris.desktop.pregen.network": "Sieć",
"iris.desktop.pregen.terrain_hint": "Gotowe chunki pokazują kolory terenu"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "pausado",
"iris.desktop.pregen.resume_hint": "Pressione P para retomar",
"iris.desktop.pregen.pause_hint": "Pressione P para pausar",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Pack '{pack}': conteúdo indisponível no Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "O pack '{pack}' não usa conteúdo em falta no Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Atualize o servidor para um Minecraft mais recente para restaurar este conteúdo, ou declare alternativas (blockFallbacks da dimensão, backup do bloco).",
"iris.modded.help.entry.command.compat_content": "Mostrar o conteúdo que não pode ser gerado nesta versão do Minecraft"
"iris.modded.help.entry.command.compat_content": "Mostrar o conteúdo que não pode ser gerado nesta versão do Minecraft",
"iris.desktop.pregen.pause": "Pausar",
"iris.desktop.pregen.resume": "Retomar",
"iris.desktop.pregen.generating": "A gerar",
"iris.desktop.pregen.saving": "A guardar",
"iris.desktop.pregen.stopping": "A parar",
"iris.desktop.pregen.completed": "Concluído",
"iris.desktop.pregen.error": "Falha na geração",
"iris.desktop.pregen.control_failed": "Falha ao pausar · consultar registo do servidor",
"iris.desktop.pregen.error_details": "Detalhes no registo do servidor",
"iris.desktop.pregen.progress": "{generated} / {total} chunks",
"iris.desktop.pregen.percent": "{percent} concluído",
"iris.desktop.pregen.current": "Atual · 10 s",
"iris.desktop.pregen.overall": "Global",
"iris.desktop.pregen.thirty": "Média de 30 s",
"iris.desktop.pregen.sixty": "Média de 60 s",
"iris.desktop.pregen.rate": "{rate} chunks/s",
"iris.desktop.pregen.eta": "Restante",
"iris.desktop.pregen.elapsed": "Decorrido",
"iris.desktop.pregen.memory_label": "Memória",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Alocação",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · em cache",
"iris.desktop.pregen.failed": "{count} falhas · consultar registo do servidor",
"iris.desktop.pregen.map": "Mapa de geração",
"iris.desktop.pregen.bounds": "Chunks X de {minX} a {maxX} · Z de {minZ} a {maxZ}",
"iris.desktop.pregen.waiting": "Em espera",
"iris.desktop.pregen.ready": "Pronto",
"iris.desktop.pregen.existing": "Existente",
"iris.desktop.pregen.network": "Rede",
"iris.desktop.pregen.terrain_hint": "Os chunks concluídos mostram as cores do terreno"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "приостановлено",
"iris.desktop.pregen.resume_hint": "Нажмите P, чтобы возобновить",
"iris.desktop.pregen.pause_hint": "Нажмите P, чтобы остановиться",
"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": "Скорость: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Пак '{pack}': содержимое недоступно в Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Пак '{pack}' не использует содержимое, которого нет в Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Обновите сервер до более новой версии Minecraft, чтобы вернуть это содержимое, или объявите замены (blockFallbacks измерения, backup блока).",
"iris.modded.help.entry.command.compat_content": "Показать содержимое, которое нельзя сгенерировать в этой версии Minecraft"
"iris.modded.help.entry.command.compat_content": "Показать содержимое, которое нельзя сгенерировать в этой версии Minecraft",
"iris.desktop.pregen.pause": "Пауза",
"iris.desktop.pregen.resume": "Продолжить",
"iris.desktop.pregen.generating": "Генерация",
"iris.desktop.pregen.saving": "Сохранение",
"iris.desktop.pregen.stopping": "Остановка",
"iris.desktop.pregen.completed": "Завершено",
"iris.desktop.pregen.error": "Ошибка генерации",
"iris.desktop.pregen.control_failed": "Ошибка паузы · см. журнал сервера",
"iris.desktop.pregen.error_details": "Подробности в журнале сервера",
"iris.desktop.pregen.progress": "{generated} / {total} чанков",
"iris.desktop.pregen.percent": "Завершено {percent}",
"iris.desktop.pregen.current": "Текущая · 10 с",
"iris.desktop.pregen.overall": "Общая",
"iris.desktop.pregen.thirty": "Средняя за 30 с",
"iris.desktop.pregen.sixty": "Средняя за 60 с",
"iris.desktop.pregen.rate": "{rate} чанков/с",
"iris.desktop.pregen.eta": "Осталось",
"iris.desktop.pregen.elapsed": "Прошло",
"iris.desktop.pregen.memory_label": "Память",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Выделение памяти",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · из кеша",
"iris.desktop.pregen.failed": "Ошибок: {count} · см. журнал сервера",
"iris.desktop.pregen.map": "Карта генерации",
"iris.desktop.pregen.bounds": "Чанки X от {minX} до {maxX} · Z от {minZ} до {maxZ}",
"iris.desktop.pregen.waiting": "Ожидание",
"iris.desktop.pregen.ready": "Готово",
"iris.desktop.pregen.existing": "Существующие",
"iris.desktop.pregen.network": "Сеть",
"iris.desktop.pregen.terrain_hint": "Готовые чанки отображают цвета ландшафта"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "duraklatıldı",
"iris.desktop.pregen.resume_hint": "Devam etmek için P'ye basın",
"iris.desktop.pregen.pause_hint": "Duraklatmak için P'ye basın",
"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: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Paket '{pack}': içerik Minecraft {version} sürümünde yok",
"iris.modded.moddedpackcommands.compat_none": "Paket '{pack}' Minecraft {version} sürümünde eksik olan içerik kullanmıyor.",
"iris.modded.moddedpackcommands.compat_remedy": "Bu içeriği geri kazanmak için sunucuyu daha yeni bir Minecraft sürümüne güncelleyin veya yedekler tanımlayın (boyutun blockFallbacks, bloğun backup).",
"iris.modded.help.entry.command.compat_content": "Bu Minecraft sürümünde üretilemeyen içeriği göster"
"iris.modded.help.entry.command.compat_content": "Bu Minecraft sürümünde üretilemeyen içeriği göster",
"iris.desktop.pregen.pause": "Duraklat",
"iris.desktop.pregen.resume": "Devam et",
"iris.desktop.pregen.generating": "Oluşturuluyor",
"iris.desktop.pregen.saving": "Kaydediliyor",
"iris.desktop.pregen.stopping": "Durduruluyor",
"iris.desktop.pregen.completed": "Tamamlandı",
"iris.desktop.pregen.error": "Oluşturma başarısız",
"iris.desktop.pregen.control_failed": "Duraklatma başarısız · sunucu günlüğüne bakın",
"iris.desktop.pregen.error_details": "Ayrıntılar için sunucu günlüğüne bakın",
"iris.desktop.pregen.progress": "{generated} / {total} chunk",
"iris.desktop.pregen.percent": "{percent} tamamlandı",
"iris.desktop.pregen.current": "Güncel · 10 sn",
"iris.desktop.pregen.overall": "Genel",
"iris.desktop.pregen.thirty": "30 sn ortalama",
"iris.desktop.pregen.sixty": "60 sn ortalama",
"iris.desktop.pregen.rate": "{rate} chunk/sn",
"iris.desktop.pregen.eta": "Kalan",
"iris.desktop.pregen.elapsed": "Geçen",
"iris.desktop.pregen.memory_label": "Bellek",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Bellek ayırma",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · önbellekten",
"iris.desktop.pregen.failed": "{count} başarısız · sunucu günlüğüne bakın",
"iris.desktop.pregen.map": "Oluşturma haritası",
"iris.desktop.pregen.bounds": "Chunk X {minX} – {maxX} · Z {minZ} – {maxZ}",
"iris.desktop.pregen.waiting": "Bekliyor",
"iris.desktop.pregen.ready": "Hazır",
"iris.desktop.pregen.existing": "Mevcut",
"iris.desktop.pregen.network": "Ağ",
"iris.desktop.pregen.terrain_hint": "Tamamlanan chunklar arazi renklerini gösterir"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "đã tạm dừng",
"iris.desktop.pregen.resume_hint": "Nhấn P để tiếp tục",
"iris.desktop.pregen.pause_hint": "Nhấn nút P để tạm dừng",
"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 độ: {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "Gói '{pack}': nội dung không có trên Minecraft {version}",
"iris.modded.moddedpackcommands.compat_none": "Gói '{pack}' không dùng nội dung nào thiếu trên Minecraft {version}.",
"iris.modded.moddedpackcommands.compat_remedy": "Cập nhật máy chủ lên Minecraft mới hơn để khôi phục nội dung này, hoặc khai báo phương án dự phòng (blockFallbacks của chiều, backup của khối).",
"iris.modded.help.entry.command.compat_content": "Hiển thị nội dung không thể tạo trên phiên bản Minecraft này"
"iris.modded.help.entry.command.compat_content": "Hiển thị nội dung không thể tạo trên phiên bản Minecraft này",
"iris.desktop.pregen.pause": "Tạm dừng",
"iris.desktop.pregen.resume": "Tiếp tục",
"iris.desktop.pregen.generating": "Đang tạo",
"iris.desktop.pregen.saving": "Đang lưu",
"iris.desktop.pregen.stopping": "Đang dừng",
"iris.desktop.pregen.completed": "Hoàn tất",
"iris.desktop.pregen.error": "Tạo thất bại",
"iris.desktop.pregen.control_failed": "Tạm dừng thất bại · xem nhật ký máy chủ",
"iris.desktop.pregen.error_details": "Xem chi tiết trong nhật ký máy chủ",
"iris.desktop.pregen.progress": "{generated} / {total} chunk",
"iris.desktop.pregen.percent": "Hoàn tất {percent}",
"iris.desktop.pregen.current": "Hiện tại · 10 giây",
"iris.desktop.pregen.overall": "Tổng thể",
"iris.desktop.pregen.thirty": "Trung bình 30 giây",
"iris.desktop.pregen.sixty": "Trung bình 60 giây",
"iris.desktop.pregen.rate": "{rate} chunk/giây",
"iris.desktop.pregen.eta": "Còn lại",
"iris.desktop.pregen.elapsed": "Đã qua",
"iris.desktop.pregen.memory_label": "Bộ nhớ",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "Cấp phát",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · đã lưu đệm",
"iris.desktop.pregen.failed": "{count} thất bại · xem nhật ký máy chủ",
"iris.desktop.pregen.map": "Bản đồ tạo địa hình",
"iris.desktop.pregen.bounds": "Chunk X từ {minX} đến {maxX} · Z từ {minZ} đến {maxZ}",
"iris.desktop.pregen.waiting": "Đang chờ",
"iris.desktop.pregen.ready": "Sẵn sàng",
"iris.desktop.pregen.existing": "Có sẵn",
"iris.desktop.pregen.network": "Mạng",
"iris.desktop.pregen.terrain_hint": "Chunk hoàn tất hiển thị màu địa hình"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "已暂停",
"iris.desktop.pregen.resume_hint": "按 P 键恢复",
"iris.desktop.pregen.pause_hint": "按 P 暂停",
"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": "速度 : {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "资源包 '{pack}': 内容在 Minecraft {version} 中不可用",
"iris.modded.moddedpackcommands.compat_none": "资源包 '{pack}' 未使用 Minecraft {version} 中缺失的内容。",
"iris.modded.moddedpackcommands.compat_remedy": "将服务器升级到更新的 Minecraft 以恢复这些内容,或声明回退 (维度的 blockFallbacks、方块的 backup)。",
"iris.modded.help.entry.command.compat_content": "显示在当前 Minecraft 版本中无法生成的内容"
"iris.modded.help.entry.command.compat_content": "显示在当前 Minecraft 版本中无法生成的内容",
"iris.desktop.pregen.pause": "暂停",
"iris.desktop.pregen.resume": "继续",
"iris.desktop.pregen.generating": "生成中",
"iris.desktop.pregen.saving": "保存中",
"iris.desktop.pregen.stopping": "停止中",
"iris.desktop.pregen.completed": "已完成",
"iris.desktop.pregen.error": "生成失败",
"iris.desktop.pregen.control_failed": "暂停失败 · 请查看服务器日志",
"iris.desktop.pregen.error_details": "详情请查看服务器日志",
"iris.desktop.pregen.progress": "{generated} / {total} 区块",
"iris.desktop.pregen.percent": "已完成 {percent}",
"iris.desktop.pregen.current": "当前 · 10秒",
"iris.desktop.pregen.overall": "总体",
"iris.desktop.pregen.thirty": "30秒平均",
"iris.desktop.pregen.sixty": "60秒平均",
"iris.desktop.pregen.rate": "{rate} 区块/秒",
"iris.desktop.pregen.eta": "剩余时间",
"iris.desktop.pregen.elapsed": "已用时间",
"iris.desktop.pregen.memory_label": "内存",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "内存分配",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · 已缓存",
"iris.desktop.pregen.failed": "{count} 个失败 · 请查看服务器日志",
"iris.desktop.pregen.map": "生成地图",
"iris.desktop.pregen.bounds": "区块 X {minX} 至 {maxX} · Z {minZ} 至 {maxZ}",
"iris.desktop.pregen.waiting": "等待中",
"iris.desktop.pregen.ready": "就绪",
"iris.desktop.pregen.existing": "已有",
"iris.desktop.pregen.network": "网络",
"iris.desktop.pregen.terrain_hint": "已完成的区块显示地形颜色"
}
}
+32 -8
View File
@@ -1442,14 +1442,7 @@
"iris.desktop.pregen.paused": "已暫停",
"iris.desktop.pregen.resume_hint": "按 P 鍵恢復",
"iris.desktop.pregen.pause_hint": "按 P 暫停",
"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": "速度 : {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",
"iris.modded.help.entry.command.what.here": "Inspect the Iris biome, region, cave biome, surface and chunk at your position",
"iris.modded.help.entry.command.what.biome": "Inspect the Iris biome, configured derivative and registered native biome",
"iris.modded.help.entry.command.what.region": "Inspect the Iris region at your current chunk",
@@ -1570,6 +1563,37 @@
"iris.modded.moddedpackcommands.compat_header": "資源包 '{pack}': 內容在 Minecraft {version} 中無法使用",
"iris.modded.moddedpackcommands.compat_none": "資源包 '{pack}' 未使用 Minecraft {version} 中缺少的內容。",
"iris.modded.moddedpackcommands.compat_remedy": "將伺服器升級到較新的 Minecraft 以還原這些內容,或宣告備援 (維度的 blockFallbacks、方塊的 backup)。",
"iris.modded.help.entry.command.compat_content": "顯示在目前 Minecraft 版本中無法生成的內容"
"iris.modded.help.entry.command.compat_content": "顯示在目前 Minecraft 版本中無法生成的內容",
"iris.desktop.pregen.pause": "暫停",
"iris.desktop.pregen.resume": "繼續",
"iris.desktop.pregen.generating": "生成中",
"iris.desktop.pregen.saving": "儲存中",
"iris.desktop.pregen.stopping": "停止中",
"iris.desktop.pregen.completed": "已完成",
"iris.desktop.pregen.error": "生成失敗",
"iris.desktop.pregen.control_failed": "暫停失敗 · 請查看伺服器日誌",
"iris.desktop.pregen.error_details": "詳情請查看伺服器日誌",
"iris.desktop.pregen.progress": "{generated} / {total} 區塊",
"iris.desktop.pregen.percent": "已完成 {percent}",
"iris.desktop.pregen.current": "目前 · 10秒",
"iris.desktop.pregen.overall": "整體",
"iris.desktop.pregen.thirty": "30秒平均",
"iris.desktop.pregen.sixty": "60秒平均",
"iris.desktop.pregen.rate": "{rate} 區塊/秒",
"iris.desktop.pregen.eta": "剩餘時間",
"iris.desktop.pregen.elapsed": "已用時間",
"iris.desktop.pregen.memory_label": "記憶體",
"iris.desktop.pregen.memory_usage": "{used} · {usage}",
"iris.desktop.pregen.pressure": "記憶體配置",
"iris.desktop.pregen.pressure_value": "{rate}/s",
"iris.desktop.pregen.cached": "{method} · 已快取",
"iris.desktop.pregen.failed": "{count} 個失敗 · 請查看伺服器日誌",
"iris.desktop.pregen.map": "生成地圖",
"iris.desktop.pregen.bounds": "區塊 X {minX} 至 {maxX} · Z {minZ} 至 {maxZ}",
"iris.desktop.pregen.waiting": "等待中",
"iris.desktop.pregen.ready": "就緒",
"iris.desktop.pregen.existing": "既有",
"iris.desktop.pregen.network": "網路",
"iris.desktop.pregen.terrain_hint": "已完成的區塊顯示地形顏色"
}
}
@@ -0,0 +1,109 @@
package art.arcane.iris.core.gui;
import art.arcane.iris.core.pregenerator.PregenTask;
import art.arcane.volmlib.util.math.Position2;
import org.junit.Test;
import javax.swing.SwingUtilities;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.lang.reflect.Field;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class PregenMapPanelTest {
@Test
public void singleChunkAndInclusiveFinalEdgesReceivePixels() throws Exception {
PregenMapPanel single = panel(new PregenRenderSnapshot.Bounds(5, -9, 5, -9));
single.submit(5, -9, Color.GREEN);
flush(single);
assertEquals(Color.GREEN.getRGB(), image(single).getRGB(0, 0));
PregenMapPanel rectangle = panel(new PregenRenderSnapshot.Bounds(-2, -3, 1, -1));
rectangle.submit(1, -1, Color.RED);
rectangle.submit(-2, -3, Color.BLUE);
flush(rectangle);
assertEquals(Color.RED.getRGB(), image(rectangle).getRGB(3, 2));
assertEquals(Color.BLUE.getRGB(), image(rectangle).getRGB(0, 0));
}
@Test
public void largeMapsStayBoundedAndEverySubmittedChunkCanReachAPixel() throws Exception {
PregenMapPanel panel = panel(new PregenRenderSnapshot.Bounds(Integer.MIN_VALUE, -10, Integer.MAX_VALUE, 10));
panel.submit(Integer.MAX_VALUE, 10, Color.GREEN);
panel.submit(0, 0, Color.RED);
flush(panel);
assertEquals(1024, image(panel).getWidth());
assertEquals(21, image(panel).getHeight());
assertEquals(Color.GREEN.getRGB(), image(panel).getRGB(1023, 20));
assertEquals(Color.RED.getRGB(), image(panel).getRGB(512, 10));
}
@Test
public void duplicateAndOutOfBoundsSubmissionsDoNotRequestAnotherFrame() throws Exception {
PregenMapPanel panel = panel(new PregenRenderSnapshot.Bounds(0, 0, 1, 1));
panel.submit(2, 0, Color.GREEN);
SwingUtilities.invokeAndWait(() -> assertFalse(panel.flush()));
panel.submit(0, 0, Color.GREEN);
SwingUtilities.invokeAndWait(() -> assertTrue(panel.flush()));
panel.submit(0, 0, Color.GREEN);
SwingUtilities.invokeAndWait(() -> assertFalse(panel.flush()));
SwingUtilities.invokeAndWait(panel::disposeMap);
panel.submit(0, 0, Color.RED);
SwingUtilities.invokeAndWait(() -> assertFalse(panel.flush()));
}
@Test
public void pixelUpdatesRetainTheirLatestValueUntilTheViewFlushes() throws Exception {
PregenMapPanel panel = panel(new PregenRenderSnapshot.Bounds(0, 0, 10_000, 0));
for (int index = 0; index < 100_000; index++) {
panel.submit(index % 10_001, 0, Color.RED);
}
panel.submit(10_000, 0, Color.GREEN);
flush(panel);
assertEquals(Color.GREEN.getRGB(), image(panel).getRGB(1023, 0));
assertEquals(1024, image(panel).getWidth());
}
@Test
public void mapFitPreservesRectangularChunkAspect() {
Rectangle wide = PregenMapPanel.fit(new PregenRenderSnapshot.Bounds(0, 0, 3, 1), 802, 602);
assertEquals(new Rectangle(1, 101, 800, 400), wide);
Rectangle tall = PregenMapPanel.fit(new PregenRenderSnapshot.Bounds(0, 0, 1, 3), 802, 602);
assertEquals(new Rectangle(251, 1, 300, 600), tall);
}
@Test
public void arithmeticTaskBoundsMatchActualRectangularTraversal() {
PregenTask task = PregenTask.builder().center(new Position2(-17, 35)).radiusX(9).radiusZ(37).build();
int[] actual = {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE};
task.iterateAllChunks((x, z) -> {
actual[0] = Math.min(actual[0], x);
actual[1] = Math.min(actual[1], z);
actual[2] = Math.max(actual[2], x);
actual[3] = Math.max(actual[3], z);
});
assertArrayEquals(actual, task.chunkBounds());
}
private static PregenMapPanel panel(PregenRenderSnapshot.Bounds bounds) throws Exception {
PregenMapPanel[] result = new PregenMapPanel[1];
SwingUtilities.invokeAndWait(() -> result[0] = new PregenMapPanel(bounds));
return result[0];
}
private static void flush(PregenMapPanel panel) throws Exception {
SwingUtilities.invokeAndWait(panel::flush);
}
private static BufferedImage image(PregenMapPanel panel) throws Exception {
Field field = PregenMapPanel.class.getDeclaredField("image");
field.setAccessible(true);
return (BufferedImage) field.get(panel);
}
}
@@ -0,0 +1,120 @@
package art.arcane.iris.core.gui;
import art.arcane.iris.core.pregenerator.IrisPregenerator;
import art.arcane.iris.core.pregenerator.PregenPhaseTracker;
import art.arcane.iris.core.pregenerator.PregenRates;
import art.arcane.volmlib.util.format.MemoryMonitor;
import org.junit.Test;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verifyNoInteractions;
public class PregeneratorJobRenderSnapshotTest {
@Test
public void viewSnapshotPublishesAllRatesMemoryAndFailedCountsTogether() throws Exception {
Fixture fixture = new Fixture();
when(fixture.pregenerator.getFailedChunks()).thenReturn(2L);
fixture.tick();
PregenRenderSnapshot view = fixture.job.renderSnapshot();
assertEquals(PregenRenderSnapshot.Phase.GENERATING, view.phase());
assertEquals(12D, view.progress().chunksPerSecond(), 0D);
assertEquals(7D, view.progress().overallChunksPerSecond(), 0D);
assertEquals(18D, view.progress().thirtySecondChunksPerSecond(), 0D);
assertEquals(24D, view.progress().sixtySecondChunksPerSecond(), 0D);
assertEquals(2L, view.progress().failed());
assertEquals(1234L, view.usedMemoryBytes());
assertEquals(0.25D, view.memoryUsage(), 0D);
assertEquals(256L, view.allocationBytesPerSecond());
assertTrue(view.cached());
assertSame(view, fixture.job.renderSnapshot());
}
@Test
public void stoppingAndFinishedPhasesCannotBeOverwrittenByTickOrSave() throws Exception {
Fixture fixture = new Fixture();
fixture.stopping.set(true);
fixture.tick();
assertEquals(PregenRenderSnapshot.Phase.STOPPING, fixture.job.renderSnapshot().phase());
fixture.job.onSaving();
assertEquals(PregenRenderSnapshot.Phase.STOPPING, fixture.job.renderSnapshot().phase());
fixture.stopping.set(false);
fixture.set("finished", true);
fixture.tick();
assertEquals(PregenRenderSnapshot.Phase.STOPPING, fixture.job.renderSnapshot().phase());
}
@Test
public void pausedAndErrorStateKeepTheirPrecedence() throws Exception {
Fixture fixture = new Fixture();
when(fixture.pregenerator.paused()).thenReturn(true);
fixture.job.onSaving();
assertEquals(PregenRenderSnapshot.Phase.PAUSED, fixture.job.renderSnapshot().phase());
assertTrue(fixture.job.renderSnapshot().progress().paused());
fixture.set("failure", "Preparation failed");
fixture.tick();
assertEquals(PregenRenderSnapshot.Phase.ERROR, fixture.job.renderSnapshot().phase());
assertEquals("Preparation failed", fixture.job.renderSnapshot().failure());
}
@Test
public void finishedWindowCannotPauseItsReplacementJob() throws Exception {
Fixture previous = new Fixture();
Fixture replacement = new Fixture();
Runnable queuedPause = previous.job::togglePause;
previous.set("finished", true);
Field field = PregeneratorJob.class.getDeclaredField("instance");
field.setAccessible(true);
@SuppressWarnings("unchecked")
AtomicReference<PregeneratorJob> instance = (AtomicReference<PregeneratorJob>) field.get(null);
PregeneratorJob original = instance.getAndSet(replacement.job);
try {
queuedPause.run();
verifyNoInteractions(previous.pregenerator, replacement.pregenerator);
} finally {
instance.set(original);
}
}
private static final class Fixture {
private final PregeneratorJob job = mock(PregeneratorJob.class, CALLS_REAL_METHODS);
private final IrisPregenerator pregenerator = mock(IrisPregenerator.class);
private final AtomicBoolean stopping = new AtomicBoolean();
private Fixture() throws Exception {
MemoryMonitor monitor = mock(MemoryMonitor.class);
when(monitor.getUsedBytes()).thenReturn(1234L);
when(monitor.getUsagePercent()).thenReturn(0.25D);
when(monitor.getPressure()).thenReturn(256L);
when(pregenerator.getRates()).thenReturn(new PregenRates(7D, 12D, 18D, 24D));
set("bounds", new PregenRenderSnapshot.Bounds(-5, 2, 8, 12));
set("pregenerator", pregenerator);
set("monitor", monitor);
set("stopRequested", stopping);
set("saving", new AtomicBoolean());
set("onProgress", List.of());
set("apiPhases", new PregenPhaseTracker());
}
private void tick() {
job.onTick(12D, 720D, 1D, 0.5D, 5L, 10L, 3L, 1000L, 2500L, "Async", true);
}
private void set(String name, Object value) throws Exception {
Field field = PregeneratorJob.class.getDeclaredField(name);
field.setAccessible(true);
field.set(job, value);
}
}
}
@@ -45,7 +45,10 @@ import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -554,6 +557,109 @@ public class IrisEngineGenerationRuntimeScopeTest {
assertThrows(IllegalStateException.class, () -> engine.getHeight(0, 0));
}
@Test
public void publishedRouterLookupDoesNotWaitForTheAttachmentMonitor() throws Exception {
RuntimeFixture active = runtime(1, 1D, 1D, 1D);
IrisEngine engine = engine(active.runtime, mock(EngineEffects.class), mock(EngineWorldManager.class));
GenerationHistoryRuntimeRouter router = historyRouter(engine);
engine.attachGenerationHistoryRuntimeRouter(router);
FutureTask<Optional<GenerationHistoryRuntimeRouter>> read = new FutureTask<>(engine::getGenerationHistoryRuntimeRouter);
Thread reader = new Thread(read, "History router lookup");
try {
synchronized (engine.generationHistoryRuntimeRouterLock) {
reader.start();
assertSame(router, read.get(5, TimeUnit.SECONDS).orElseThrow());
}
} finally {
reader.join(5_000L);
assertTrue("Router lookup did not finish", !reader.isAlive());
}
}
@Test
public void publishedCoordinateReadDoesNotWaitForTheAttachmentMonitor() throws Exception {
RuntimeFixture active = runtime(1, 1D, 1D, 1D);
IrisEngine engine = engine(active.runtime, mock(EngineEffects.class), mock(EngineWorldManager.class));
GenerationHistoryRuntimeRouter router = historyRouter(engine);
engine.attachGenerationHistoryRuntimeRouter(router);
GenerationHistoryRuntimeRouter.CoordinateScope scope = mock(GenerationHistoryRuntimeRouter.CoordinateScope.class);
when(router.openCoordinateScope(-17, 32)).thenReturn(scope);
FutureTask<GenerationHistoryRuntimeRouter.CoordinateScope> read =
new FutureTask<>(() -> engine.openGenerationHistoryCoordinateScope(-17, 32));
Thread reader = new Thread(read, "History coordinate read");
try {
synchronized (engine.generationHistoryRuntimeRouterLock) {
reader.start();
assertSame(scope, read.get(5, TimeUnit.SECONDS));
}
} finally {
reader.join(5_000L);
assertTrue("Coordinate read did not finish", !reader.isAlive());
}
verify(router).openCoordinateScope(-17, 32);
}
@Test
public void missingRouterReadWaitsForAttachmentPublication() throws Exception {
RuntimeFixture active = runtime(1, 1D, 1D, 1D);
IrisEngine engine = engine(active.runtime, mock(EngineEffects.class), mock(EngineWorldManager.class));
GenerationHistoryRuntimeRouter router = historyRouter(engine);
GenerationHistoryRuntimeRouter.CoordinateScope scope = mock(GenerationHistoryRuntimeRouter.CoordinateScope.class);
when(router.openCoordinateScope(-17, 32)).thenReturn(scope);
CountDownLatch started = new CountDownLatch(1);
FutureTask<GenerationHistoryRuntimeRouter.CoordinateScope> read = new FutureTask<>(() -> {
started.countDown();
return engine.openGenerationHistoryCoordinateScope(-17, 32);
});
Thread reader = new Thread(read, "Pending history attachment");
try {
synchronized (engine.generationHistoryRuntimeRouterLock) {
reader.start();
assertTrue(started.await(5, TimeUnit.SECONDS));
awaitBlocked(reader);
engine.attachGenerationHistoryRuntimeRouter(router);
}
assertSame(scope, read.get(5, TimeUnit.SECONDS));
} finally {
reader.join(5_000L);
assertTrue("Pending router read did not finish", !reader.isAlive());
}
}
@Test
public void detachedRouterReadRemainsFailClosedAcrossThreads() throws Exception {
RuntimeFixture active = runtime(1, 1D, 1D, 1D);
IrisEngine engine = engine(active.runtime, mock(EngineEffects.class), mock(EngineWorldManager.class));
GenerationHistoryRuntimeRouter router = historyRouter(engine);
engine.attachGenerationHistoryRuntimeRouter(router);
CountDownLatch started = new CountDownLatch(1);
FutureTask<GenerationHistoryRuntimeRouter.CoordinateScope> read = new FutureTask<>(() -> {
started.countDown();
return engine.openGenerationHistoryCoordinateScope(-17, 32);
});
Thread reader = new Thread(read, "Detached history read");
try {
synchronized (engine.generationHistoryRuntimeRouterLock) {
engine.detachGenerationHistoryRuntimeRouter(router);
reader.start();
assertTrue(started.await(5, TimeUnit.SECONDS));
awaitBlocked(reader);
}
ExecutionException failure = assertThrows(ExecutionException.class, () -> read.get(5, TimeUnit.SECONDS));
assertTrue(failure.getCause() instanceof IllegalStateException);
assertEquals("Iris generation-history runtime router is detached.", failure.getCause().getMessage());
assertTrue(engine.getGenerationHistoryRuntimeRouter().isEmpty());
} finally {
reader.join(5_000L);
assertTrue("Detached router read did not finish", !reader.isAlive());
}
verify(router, never()).openCoordinateScope(anyInt(), anyInt());
}
@Test
public void transferredMantleIsNotClosedWithTheRetiredRuntime() throws Exception {
RuntimeFixture active = runtime(1, 1D, 1D, 1D);
@@ -717,6 +823,14 @@ public class IrisEngineGenerationRuntimeScopeTest {
return router;
}
private static void awaitBlocked(Thread thread) throws InterruptedException {
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(5L);
while (thread.getState() != Thread.State.BLOCKED && thread.isAlive() && System.nanoTime() < deadline) {
Thread.sleep(1L);
}
assertEquals(Thread.State.BLOCKED, thread.getState());
}
private static IrisEngine engine(
GenerationRuntime generationRuntime,
EngineEffects effects,