mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 04:37:47 +00:00
API
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
art/arcane/iris/core/IrisRuntimeSchedulerMode.java
|
||||
art/arcane/iris/core/IrisWorldStorage.java
|
||||
art/arcane/iris/core/IrisWorlds.java
|
||||
art/arcane/iris/core/ServerConfigurator.java
|
||||
art/arcane/iris/core/datapack/DatapackIngestService.java
|
||||
@@ -18,7 +19,6 @@ art/arcane/iris/core/lifecycle/WorldLifecycleStaging.java
|
||||
art/arcane/iris/core/lifecycle/WorldLifecycleSupport.java
|
||||
art/arcane/iris/core/lifecycle/WorldsProviderBackend.java
|
||||
art/arcane/iris/core/link/ExternalDataProvider.java
|
||||
art/arcane/iris/core/link/Identifier.java
|
||||
art/arcane/iris/core/link/MultiverseCoreLink.java
|
||||
art/arcane/iris/core/link/WorldEditLink.java
|
||||
art/arcane/iris/core/link/data/CraftEngineDataProvider.java
|
||||
@@ -52,6 +52,7 @@ art/arcane/iris/core/runtime/WorldRuntimeControlService.java
|
||||
art/arcane/iris/core/safeguard/Mode.java
|
||||
art/arcane/iris/core/safeguard/task/Tasks.java
|
||||
art/arcane/iris/core/service/BoardSVC.java
|
||||
art/arcane/iris/core/service/EntityRiseSVC.java
|
||||
art/arcane/iris/core/service/ExternalDataSVC.java
|
||||
art/arcane/iris/core/service/GlobalCacheSVC.java
|
||||
art/arcane/iris/core/service/ObjectSVC.java
|
||||
@@ -69,15 +70,14 @@ art/arcane/iris/core/tools/IrisPackBenchmarking.java
|
||||
art/arcane/iris/core/tools/IrisReflectiveAPI.java
|
||||
art/arcane/iris/core/tools/IrisToolbelt.java
|
||||
art/arcane/iris/core/tools/IrisWorldCreator.java
|
||||
art/arcane/iris/core/tools/TreePlausibilizer.java
|
||||
art/arcane/iris/engine/IrisEngineEffects.java
|
||||
art/arcane/iris/engine/IrisWorldManager.java
|
||||
art/arcane/iris/engine/data/chunk/LinkedTerrainChunk.java
|
||||
art/arcane/iris/engine/data/chunk/TerrainChunk.java
|
||||
art/arcane/iris/engine/decorator/DecoratorCore.java
|
||||
art/arcane/iris/engine/framework/BukkitEngineWorldManager.java
|
||||
art/arcane/iris/engine/framework/EngineAssignedWorldManager.java
|
||||
art/arcane/iris/engine/framework/EnginePlayer.java
|
||||
art/arcane/iris/engine/framework/EngineWorldManager.java
|
||||
art/arcane/iris/engine/framework/placer/WorldObjectPlacer.java
|
||||
art/arcane/iris/engine/mantle/MantleWriter.java
|
||||
art/arcane/iris/engine/object/BlockDataMergeSupport.java
|
||||
@@ -91,7 +91,6 @@ art/arcane/iris/engine/object/IrisCommandRegistry.java
|
||||
art/arcane/iris/engine/object/IrisCompat.java
|
||||
art/arcane/iris/engine/object/IrisCompatabilityBlockFilter.java
|
||||
art/arcane/iris/engine/object/IrisCompatabilityItemFilter.java
|
||||
art/arcane/iris/engine/object/IrisDimension.java
|
||||
art/arcane/iris/engine/object/IrisDirection.java
|
||||
art/arcane/iris/engine/object/IrisEffect.java
|
||||
art/arcane/iris/engine/object/IrisEnchantment.java
|
||||
@@ -108,7 +107,6 @@ art/arcane/iris/engine/object/IrisTree.java
|
||||
art/arcane/iris/engine/object/IrisVanillaLootTable.java
|
||||
art/arcane/iris/engine/object/IrisVillagerOverride.java
|
||||
art/arcane/iris/engine/object/IrisVillagerTrade.java
|
||||
art/arcane/iris/engine/object/IrisWorld.java
|
||||
art/arcane/iris/engine/object/LegacyTileData.java
|
||||
art/arcane/iris/engine/object/PotionEffectTypes.java
|
||||
art/arcane/iris/engine/object/TileData.java
|
||||
@@ -122,11 +120,13 @@ art/arcane/iris/platform/bukkit/BukkitBiome.java
|
||||
art/arcane/iris/platform/bukkit/BukkitBlockResolution.java
|
||||
art/arcane/iris/platform/bukkit/BukkitBlockState.java
|
||||
art/arcane/iris/platform/bukkit/BukkitEntityType.java
|
||||
art/arcane/iris/platform/bukkit/BukkitEnvironment.java
|
||||
art/arcane/iris/platform/bukkit/BukkitItem.java
|
||||
art/arcane/iris/platform/bukkit/BukkitPlatform.java
|
||||
art/arcane/iris/platform/bukkit/BukkitRegistries.java
|
||||
art/arcane/iris/platform/bukkit/BukkitScheduler.java
|
||||
art/arcane/iris/platform/bukkit/BukkitWorld.java
|
||||
art/arcane/iris/platform/bukkit/BukkitWorldBinding.java
|
||||
art/arcane/iris/util/common/data/IrisCustomData.java
|
||||
art/arcane/iris/util/common/data/registry/Attributes.java
|
||||
art/arcane/iris/util/common/data/registry/KeyedRegistry.java
|
||||
|
||||
@@ -26,7 +26,10 @@ import art.arcane.iris.spi.protocol.IrisMessage;
|
||||
import art.arcane.iris.core.IrisSettings;
|
||||
import art.arcane.iris.core.protocol.IrisProtocolServer;
|
||||
import art.arcane.iris.core.pregenerator.IrisPregenerator;
|
||||
import art.arcane.iris.core.pregenerator.PregenApiPhase;
|
||||
import art.arcane.iris.core.pregenerator.PregenApiSink;
|
||||
import art.arcane.iris.core.pregenerator.PregenListener;
|
||||
import art.arcane.iris.core.pregenerator.PregenPhaseTracker;
|
||||
import art.arcane.iris.core.pregenerator.PregenTask;
|
||||
import art.arcane.iris.core.pregenerator.PregeneratorMethod;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
@@ -41,6 +44,7 @@ import art.arcane.volmlib.util.scheduling.ChronoLatch;
|
||||
import art.arcane.iris.util.common.scheduling.J;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -70,6 +74,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
private final Engine engine;
|
||||
private final ExecutorService service;
|
||||
private final Thread worker;
|
||||
private final PregenPhaseTracker apiPhases = new PregenPhaseTracker();
|
||||
private PregenRenderer renderer;
|
||||
private Consumer2<Position2, Color> drawFunction;
|
||||
private int rgc = 0;
|
||||
@@ -211,24 +216,24 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
|
||||
public static PregenProgress progressSnapshot() {
|
||||
PregeneratorJob inst = instance.get();
|
||||
if (inst == null) {
|
||||
return null;
|
||||
}
|
||||
return inst == null ? null : inst.snapshot();
|
||||
}
|
||||
|
||||
double percent = inst.lastTotalChunks <= 0 ? 0D : ((double) inst.lastGenerated / (double) inst.lastTotalChunks) * 100D;
|
||||
public PregenProgress snapshot() {
|
||||
double percent = lastTotalChunks <= 0 ? 0D : ((double) lastGenerated / (double) lastTotalChunks) * 100D;
|
||||
return new PregenProgress(
|
||||
percent,
|
||||
inst.lastGenerated,
|
||||
inst.lastTotalChunks,
|
||||
Math.max(0D, inst.lastChunksPerSecond),
|
||||
Math.max(0L, inst.lastChunksRemaining),
|
||||
inst.lastEta,
|
||||
inst.lastElapsed,
|
||||
inst.lastMethod,
|
||||
inst.paused(),
|
||||
inst.pregenerator.getFailedChunks(),
|
||||
inst.worldName(),
|
||||
inst.worldIdentity());
|
||||
lastGenerated,
|
||||
lastTotalChunks,
|
||||
Math.max(0D, lastChunksPerSecond),
|
||||
Math.max(0L, lastChunksRemaining),
|
||||
lastEta,
|
||||
lastElapsed,
|
||||
lastMethod,
|
||||
paused(),
|
||||
pregenerator.getFailedChunks(),
|
||||
worldName(),
|
||||
worldIdentity());
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
@@ -372,6 +377,32 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
for (Consumer<Double> i : onProgress) {
|
||||
i.accept(percent);
|
||||
}
|
||||
|
||||
dispatchApiPhases(apiPhases.onTick(paused()));
|
||||
}
|
||||
|
||||
private void dispatchApiPhases(List<PregenApiPhase> phases) {
|
||||
if (phases.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PregenApiSink sink = IrisServices.getOrNull(PregenApiSink.class);
|
||||
if (sink == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PregenProgress progress = snapshot();
|
||||
for (PregenApiPhase phase : phases) {
|
||||
try {
|
||||
sink.pregen(phase, progress);
|
||||
} catch (Throwable error) {
|
||||
IrisLogging.reportError("Iris pregeneration API dispatch failed for phase " + phase + ".", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean reachedTotal() {
|
||||
return lastTotalChunks > 0L && lastGenerated >= lastTotalChunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -455,6 +486,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
dispatchApiPhases(apiPhases.onClose(reachedTotal()));
|
||||
close();
|
||||
instance.compareAndSet(this, null);
|
||||
whenDone.forEach(Runnable::run);
|
||||
@@ -463,7 +495,7 @@ public class PregeneratorJob implements PregenListener, PregenRenderSource {
|
||||
|
||||
@Override
|
||||
public void onSaving() {
|
||||
|
||||
dispatchApiPhases(apiPhases.onSaving());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.pregenerator;
|
||||
|
||||
public enum PregenApiPhase {
|
||||
STARTED,
|
||||
TICK,
|
||||
PAUSED,
|
||||
RESUMED,
|
||||
SAVING,
|
||||
COMPLETED,
|
||||
CANCELLED
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.pregenerator;
|
||||
|
||||
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||
|
||||
public interface PregenApiSink {
|
||||
void pregen(PregenApiPhase phase, PregeneratorJob.PregenProgress progress);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2026 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.core.pregenerator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public final class PregenPhaseTracker {
|
||||
private final AtomicReference<State> state = new AtomicReference<>(new State(false, false, false, false));
|
||||
|
||||
public List<PregenApiPhase> onTick(boolean pausedNow) {
|
||||
while (true) {
|
||||
State current = state.get();
|
||||
if (current.finished()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
State next = new State(true, pausedNow, false, false);
|
||||
List<PregenApiPhase> phases;
|
||||
if (!current.started()) {
|
||||
phases = List.of(PregenApiPhase.STARTED, PregenApiPhase.TICK);
|
||||
} else if (pausedNow != current.paused()) {
|
||||
phases = List.of(pausedNow ? PregenApiPhase.PAUSED : PregenApiPhase.RESUMED, PregenApiPhase.TICK);
|
||||
} else {
|
||||
phases = List.of(PregenApiPhase.TICK);
|
||||
}
|
||||
|
||||
if (state.compareAndSet(current, next)) {
|
||||
return phases;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<PregenApiPhase> onSaving() {
|
||||
while (true) {
|
||||
State current = state.get();
|
||||
if (current.finished() || current.saving()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
State next = new State(current.started(), current.paused(), true, false);
|
||||
if (state.compareAndSet(current, next)) {
|
||||
return List.of(PregenApiPhase.SAVING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<PregenApiPhase> onClose(boolean completed) {
|
||||
while (true) {
|
||||
State current = state.get();
|
||||
if (current.finished()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
State next = new State(current.started(), current.paused(), current.saving(), true);
|
||||
if (state.compareAndSet(current, next)) {
|
||||
return List.of(completed ? PregenApiPhase.COMPLETED : PregenApiPhase.CANCELLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record State(boolean started, boolean paused, boolean saving, boolean finished) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package art.arcane.iris.core.pregenerator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class PregenPhaseTrackerTest {
|
||||
@Test
|
||||
public void theFirstTickAnnouncesTheJobAndStillReportsProgress() {
|
||||
PregenPhaseTracker tracker = new PregenPhaseTracker();
|
||||
|
||||
assertEquals(List.of(PregenApiPhase.STARTED, PregenApiPhase.TICK), tracker.onTick(false));
|
||||
assertEquals(List.of(PregenApiPhase.TICK), tracker.onTick(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pauseAndResumeAreEmittedOnTransitionOnly() {
|
||||
PregenPhaseTracker tracker = new PregenPhaseTracker();
|
||||
tracker.onTick(false);
|
||||
|
||||
assertEquals(List.of(PregenApiPhase.PAUSED, PregenApiPhase.TICK), tracker.onTick(true));
|
||||
assertEquals(List.of(PregenApiPhase.TICK), tracker.onTick(true));
|
||||
assertEquals(List.of(PregenApiPhase.RESUMED, PregenApiPhase.TICK), tracker.onTick(false));
|
||||
assertEquals(List.of(PregenApiPhase.TICK), tracker.onTick(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aJobThatStartsPausedDoesNotAlsoEmitPaused() {
|
||||
PregenPhaseTracker tracker = new PregenPhaseTracker();
|
||||
|
||||
assertEquals(List.of(PregenApiPhase.STARTED, PregenApiPhase.TICK), tracker.onTick(true));
|
||||
assertEquals(List.of(PregenApiPhase.TICK), tracker.onTick(true));
|
||||
assertEquals(List.of(PregenApiPhase.RESUMED, PregenApiPhase.TICK), tracker.onTick(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void savingIsAStateNotAPulse() {
|
||||
PregenPhaseTracker tracker = new PregenPhaseTracker();
|
||||
tracker.onTick(false);
|
||||
|
||||
assertEquals(List.of(PregenApiPhase.SAVING), tracker.onSaving());
|
||||
assertEquals(List.of(), tracker.onSaving());
|
||||
assertEquals(List.of(PregenApiPhase.TICK), tracker.onTick(false));
|
||||
assertEquals(List.of(PregenApiPhase.SAVING), tracker.onSaving());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeIsTerminalAndDistinguishesCompletionFromCancellation() {
|
||||
PregenPhaseTracker completed = new PregenPhaseTracker();
|
||||
completed.onTick(false);
|
||||
assertEquals(List.of(PregenApiPhase.COMPLETED), completed.onClose(true));
|
||||
assertEquals(List.of(), completed.onClose(true));
|
||||
assertEquals(List.of(), completed.onClose(false));
|
||||
assertEquals(List.of(), completed.onTick(false));
|
||||
assertEquals(List.of(), completed.onSaving());
|
||||
|
||||
PregenPhaseTracker cancelled = new PregenPhaseTracker();
|
||||
cancelled.onTick(false);
|
||||
assertEquals(List.of(PregenApiPhase.CANCELLED), cancelled.onClose(false));
|
||||
assertEquals(List.of(), cancelled.onClose(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aJobThatNeverTickedStillReportsItsOutcomeExactlyOnce() {
|
||||
PregenPhaseTracker tracker = new PregenPhaseTracker();
|
||||
|
||||
assertEquals(List.of(PregenApiPhase.CANCELLED), tracker.onClose(false));
|
||||
assertEquals(List.of(), tracker.onClose(false));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user