mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 22:10:18 +00:00
Drop added code comments
- Remove the Javadoc and inline comment blocks the three runtime-safety commits added under src/main - Keep the GPL file header on the new spi type, matching every other file in that module - Leave the superseded stale-temp ordering comment deleted rather than restoring text the new boot path contradicts
This commit is contained in:
1 parent
486c6eeae9
commit
fd146de1ad
17 files changed
-140
No files matched your search
@@ -717,9 +717,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
|||||||
IrisServices.register(ManagedWorldLoader.class, (ManagedWorldLoader) this::loadManagedWorld);
|
IrisServices.register(ManagedWorldLoader.class, (ManagedWorldLoader) this::loadManagedWorld);
|
||||||
SettingsHotloadWatch watch = new SettingsHotloadWatch(getDataFile("iris.json"));
|
SettingsHotloadWatch watch = new SettingsHotloadWatch(getDataFile("iris.json"));
|
||||||
settingsHotloadWatch = watch;
|
settingsHotloadWatch = watch;
|
||||||
// Off the boot thread, because a stale cache/temp can hold a whole abandoned pack import and
|
|
||||||
// deleting it recursively is unbounded. Every pack import waits this sweep out instead, which is
|
|
||||||
// the invariant that mattered: a delete running underneath an import truncated it mid-copy.
|
|
||||||
StudioSVC.gateDownloadsOnStaleTempCleanup(MultiBurst.ioBurst.completeValueAsync(() -> {
|
StudioSVC.gateDownloadsOnStaleTempCleanup(MultiBurst.ioBurst.completeValueAsync(() -> {
|
||||||
IO.delete(getTemp());
|
IO.delete(getTemp());
|
||||||
return null;
|
return null;
|
||||||
@@ -793,11 +790,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Where the enable thread went, so a boot that got slower can be attributed to a phase rather than to
|
|
||||||
* Iris in general. The total is a lifecycle milestone and lands in logs/latest.log; the breakdown is
|
|
||||||
* for whoever is looking.
|
|
||||||
*/
|
|
||||||
private static final class EnableTimings {
|
private static final class EnableTimings {
|
||||||
private static final int REPORTED_SERVICES = 3;
|
private static final int REPORTED_SERVICES = 3;
|
||||||
|
|
||||||
@@ -946,11 +938,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
|||||||
reportLockedRuntime();
|
reportLockedRuntime();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* refuseVanillaFallback only ever runs when enable itself failed. A boot that enabled into Danger Mode
|
|
||||||
* keeps every configured Iris world bound to a generator that throws, and until now said so nowhere
|
|
||||||
* after the banner.
|
|
||||||
*/
|
|
||||||
private static void reportLockedRuntime() {
|
private static void reportLockedRuntime() {
|
||||||
String denial = IrisStartupValidation.denialReason().orElse(null);
|
String denial = IrisStartupValidation.denialReason().orElse(null);
|
||||||
if (denial == null) {
|
if (denial == null) {
|
||||||
@@ -1131,11 +1118,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A disabled plugin must not stay reachable through a static. Everything that reads these either runs
|
|
||||||
* while Iris is enabled or already handles their absence; the platform binding outlives them because
|
|
||||||
* core still logs through it until finishTerminalCleanup unbinds it.
|
|
||||||
*/
|
|
||||||
private static void releaseStatics() {
|
private static void releaseStatics() {
|
||||||
linkMultiverseCore = null;
|
linkMultiverseCore = null;
|
||||||
compat = null;
|
compat = null;
|
||||||
|
|||||||
-3
@@ -496,9 +496,6 @@ public final class IrisWorldGeneratorResolver {
|
|||||||
Iris.debug("Using staged runtime generator for " + worldName);
|
Iris.debug("Using staged runtime generator for " + worldName);
|
||||||
return stagedGenerator;
|
return stagedGenerator;
|
||||||
}
|
}
|
||||||
// A world Iris created staged its generator above and installed the injection on the way in. This
|
|
||||||
// is a world configured outside Iris, and Bukkit asks for its generator before it builds the level,
|
|
||||||
// so this is the last point at which the injection it needs can still be installed in time.
|
|
||||||
RuntimeInjection.installIfDeferred();
|
RuntimeInjection.installIfDeferred();
|
||||||
startupLock = startupLockedGenerator(worldName);
|
startupLock = startupLockedGenerator(worldName);
|
||||||
if (startupLock != null) {
|
if (startupLock != null) {
|
||||||
|
|||||||
@@ -378,8 +378,6 @@ public class WandSVC implements IrisService {
|
|||||||
activePlayers.clear();
|
activePlayers.clear();
|
||||||
ticksUntilPlayerRescan = 0;
|
ticksUntilPlayerRescan = 0;
|
||||||
taskId = J.ar(this::tickAll, 1);
|
taskId = J.ar(this::tickAll, 1);
|
||||||
// Building the templates reaches the item and enchantment registries, which costs more than the
|
|
||||||
// rest of this service's startup put together and is only needed to recognise a pre-marker wand.
|
|
||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
wand = createWand();
|
wand = createWand();
|
||||||
dust = createDust();
|
dust = createDust();
|
||||||
|
|||||||
@@ -308,12 +308,6 @@ public class IrisSettings {
|
|||||||
public boolean debug = false;
|
public boolean debug = false;
|
||||||
public boolean dumpMantleOnError = false;
|
public boolean dumpMantleOnError = false;
|
||||||
public boolean disableNMS = false;
|
public boolean disableNMS = false;
|
||||||
/**
|
|
||||||
* Attach the Java agent and install the server-code injection while Iris enables, instead of the
|
|
||||||
* first time a world Iris generates is about to load. Boot-time injection costs roughly a second
|
|
||||||
* on a server that may never load an Iris world; turn this on to pay it up front and have the
|
|
||||||
* startup safeguard verify it.
|
|
||||||
*/
|
|
||||||
public boolean eagerRuntimeInjection = false;
|
public boolean eagerRuntimeInjection = false;
|
||||||
public boolean splashLogoStartup = true;
|
public boolean splashLogoStartup = true;
|
||||||
public boolean useConsoleCustomColors = true;
|
public boolean useConsoleCustomColors = true;
|
||||||
|
|||||||
@@ -158,10 +158,6 @@ public class ServerConfigurator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Forgets what the previous boot loaded, so an enable in the same JVM recompiles and revalidates rather
|
|
||||||
* than trusting a fingerprint taken against a server that is gone.
|
|
||||||
*/
|
|
||||||
public static void resetLoadedDatapackRuntime() {
|
public static void resetLoadedDatapackRuntime() {
|
||||||
synchronized (DATAPACK_INSTALL_LOCK) {
|
synchronized (DATAPACK_INSTALL_LOCK) {
|
||||||
loadedDatapackRuntimeReady = false;
|
loadedDatapackRuntimeReady = false;
|
||||||
|
|||||||
@@ -6,15 +6,6 @@ import art.arcane.iris.core.runtime.RuntimeInjection;
|
|||||||
import art.arcane.iris.core.runtime.WorldRuntimeControlService;
|
import art.arcane.iris.core.runtime.WorldRuntimeControlService;
|
||||||
import art.arcane.iris.spi.IrisServices;
|
import art.arcane.iris.spi.IrisServices;
|
||||||
|
|
||||||
/**
|
|
||||||
* Drops every process-wide cache core keeps about the running server, so a disable leaves nothing an
|
|
||||||
* enable in the same JVM could answer from.
|
|
||||||
* <p>
|
|
||||||
* The capability singletons are the reason this exists: each holds reflective handles onto the live
|
|
||||||
* CraftServer and MinecraftServer, and a boot that reused them would be talking to the previous server's
|
|
||||||
* objects. The platform binding itself is not cleared here - core still logs through it while the adapter
|
|
||||||
* finishes its own teardown - and is unbound last by the adapter.
|
|
||||||
*/
|
|
||||||
public final class IrisRuntimeStatics {
|
public final class IrisRuntimeStatics {
|
||||||
private IrisRuntimeStatics() {
|
private IrisRuntimeStatics() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,6 @@ public final class WorldLifecycleService {
|
|||||||
this.worldBackendByKey = new ConcurrentHashMap<>();
|
this.worldBackendByKey = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Drops the cached snapshot so the next boot in this JVM builds one against the server it is running on.
|
|
||||||
*/
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
synchronized (WorldLifecycleService.class) {
|
synchronized (WorldLifecycleService.class) {
|
||||||
instance = null;
|
instance = null;
|
||||||
|
|||||||
@@ -6,15 +6,6 @@ import art.arcane.iris.core.nms.v1X.NMSBinding1X;
|
|||||||
import art.arcane.iris.spi.IrisLogging;
|
import art.arcane.iris.spi.IrisLogging;
|
||||||
import art.arcane.iris.util.project.agent.Agent;
|
import art.arcane.iris.util.project.agent.Agent;
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches the Java agent and installs the server-code injection Iris generation needs, once per boot.
|
|
||||||
* <p>
|
|
||||||
* Both steps are expensive - a self-attach to the running JVM, then three class retransformations - and
|
|
||||||
* neither is needed until a world that Iris generates is about to exist. A server that never loads an Iris
|
|
||||||
* world never pays for them. Whoever is about to produce such a world calls {@link #installIfDeferred()}
|
|
||||||
* first; it is idempotent, and a failure marks the runtime invalid so the same lock that guards a failed
|
|
||||||
* boot-time injection guards a failed deferred one.
|
|
||||||
*/
|
|
||||||
public final class RuntimeInjection {
|
public final class RuntimeInjection {
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
|
|
||||||
@@ -33,9 +24,6 @@ public final class RuntimeInjection {
|
|||||||
public record Outcome(boolean installed, Failure failure, String lockReason) {
|
public record Outcome(boolean installed, Failure failure, String lockReason) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the install if it has not run yet and reports what happened. Never throws.
|
|
||||||
*/
|
|
||||||
public static Outcome install() {
|
public static Outcome install() {
|
||||||
Outcome current = outcome;
|
Outcome current = outcome;
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
@@ -52,10 +40,6 @@ public final class RuntimeInjection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Installs on the deferred path and locks the runtime when that fails, so the caller's own readiness
|
|
||||||
* check refuses the world instead of loading it onto uninstrumented server code.
|
|
||||||
*/
|
|
||||||
public static void installIfDeferred() {
|
public static void installIfDeferred() {
|
||||||
Outcome resolved = install();
|
Outcome resolved = install();
|
||||||
if (resolved.installed()) {
|
if (resolved.installed()) {
|
||||||
@@ -71,9 +55,6 @@ public final class RuntimeInjection {
|
|||||||
return current != null && current.installed();
|
return current != null && current.installed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Forgets the result so the next boot in this JVM installs against the binding it is running with.
|
|
||||||
*/
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
outcome = null;
|
outcome = null;
|
||||||
|
|||||||
@@ -76,9 +76,6 @@ public final class WorldRuntimeControlService {
|
|||||||
+ ", " + backend.describeCapabilities();
|
+ ", " + backend.describeCapabilities();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Drops the cached snapshot so the next boot in this JVM builds one against the server it is running on.
|
|
||||||
*/
|
|
||||||
public static void reset() {
|
public static void reset() {
|
||||||
synchronized (WorldRuntimeControlService.class) {
|
synchronized (WorldRuntimeControlService.class) {
|
||||||
instance = null;
|
instance = null;
|
||||||
|
|||||||
@@ -74,8 +74,6 @@ public final class IrisSafeguard {
|
|||||||
mode = currentMode;
|
mode = currentMode;
|
||||||
count = issueCount;
|
count = issueCount;
|
||||||
|
|
||||||
// Danger is the lock. Recognising one check by its id and letting every other critical failure
|
|
||||||
// through was how a no-op NMS binding or a missing dimension type reached an open login queue.
|
|
||||||
if (currentMode == Mode.UNSTABLE) {
|
if (currentMode == Mode.UNSTABLE) {
|
||||||
IrisStartupValidation.markRuntimeInvalid(lockReason == null ? GENERIC_LOCK_REASON : lockReason);
|
IrisStartupValidation.markRuntimeInvalid(lockReason == null ? GENERIC_LOCK_REASON : lockReason);
|
||||||
return;
|
return;
|
||||||
@@ -96,10 +94,6 @@ public final class IrisSafeguard {
|
|||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The per-check record for {@code /iris debugdump}. Without it a support report carried the server and
|
|
||||||
* plugin state but not one word about which startup check put the server in the mode it is in.
|
|
||||||
*/
|
|
||||||
public static String debugReport() {
|
public static String debugReport() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("Startup safeguard: ").append(mode.getId())
|
builder.append("Startup safeguard: ").append(mode.getId())
|
||||||
|
|||||||
@@ -2,13 +2,6 @@ package art.arcane.iris.core.safeguard;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* The operator lines a boot prints when Iris enabled but its runtime is locked.
|
|
||||||
* <p>
|
|
||||||
* The Danger banner states the mode; this states the consequence. A locked runtime that still enabled is not
|
|
||||||
* covered by the vanilla-fallback refusal - that only runs when enable itself fails - so without this the
|
|
||||||
* only evidence is the first chunk request throwing hours later.
|
|
||||||
*/
|
|
||||||
public final class RuntimeLockNotice {
|
public final class RuntimeLockNotice {
|
||||||
private RuntimeLockNotice() {
|
private RuntimeLockNotice() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,6 @@ import art.arcane.iris.core.safeguard.Mode;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* What one startup check found: the severity it reached, the console lines it wants printed, and - for a
|
|
||||||
* Danger result only - the reason the runtime is locked.
|
|
||||||
* <p>
|
|
||||||
* The lock reason is mandatory on {@link #danger(String, Diagnostic...)} because Danger is what stops player
|
|
||||||
* login, world creation and generation, and an operator has to be told which check did that and what fixes
|
|
||||||
* it. A check cannot reach Danger without answering that.
|
|
||||||
*/
|
|
||||||
public record CheckResult(Mode mode, String lockReason, List<Diagnostic> diagnostics) {
|
public record CheckResult(Mode mode, String lockReason, List<Diagnostic> diagnostics) {
|
||||||
public CheckResult {
|
public CheckResult {
|
||||||
if (mode == null) {
|
if (mode == null) {
|
||||||
|
|||||||
@@ -4,14 +4,6 @@ import art.arcane.iris.core.safeguard.Mode;
|
|||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
|
||||||
* One startup check, plus the severity its own failure carries.
|
|
||||||
* <p>
|
|
||||||
* A check declares whether it is advisory or critical at the point it is written, so nothing downstream has
|
|
||||||
* to recognise a check by its id to decide what a failure means. An advisory check that throws is a Warning
|
|
||||||
* and leaves the runtime open; a critical one that throws is Danger and locks the runtime with the reason it
|
|
||||||
* carries here.
|
|
||||||
*/
|
|
||||||
public abstract class Task {
|
public abstract class Task {
|
||||||
private final String id;
|
private final String id;
|
||||||
private final Mode failureMode;
|
private final Mode failureMode;
|
||||||
@@ -37,9 +29,6 @@ public abstract class Task {
|
|||||||
|
|
||||||
public abstract CheckResult run();
|
public abstract CheckResult run();
|
||||||
|
|
||||||
/**
|
|
||||||
* A check whose failure degrades Iris but leaves it usable.
|
|
||||||
*/
|
|
||||||
public static Task advisory(String id, Supplier<CheckResult> action) {
|
public static Task advisory(String id, Supplier<CheckResult> action) {
|
||||||
return new Task(id, Mode.WARNING, null) {
|
return new Task(id, Mode.WARNING, null) {
|
||||||
@Override
|
@Override
|
||||||
@@ -49,10 +38,6 @@ public abstract class Task {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A check whose failure means Iris cannot safely run. {@code throwLockReason} is what an operator is told
|
|
||||||
* when the check itself throws rather than returning a result.
|
|
||||||
*/
|
|
||||||
public static Task critical(String id, String throwLockReason, Supplier<CheckResult> action) {
|
public static Task critical(String id, String throwLockReason, Supplier<CheckResult> action) {
|
||||||
return new Task(id, Mode.UNSTABLE, throwLockReason) {
|
return new Task(id, Mode.UNSTABLE, throwLockReason) {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -229,10 +229,6 @@ public final class Tasks {
|
|||||||
return Bukkit.getServer();
|
return Bukkit.getServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Matched against every registered plugin rather than asked for by exact name: a plugin.yml decides its
|
|
||||||
* own capitalization, and asking the plugin manager for "dynmap" misses a build that registers "Dynmap".
|
|
||||||
*/
|
|
||||||
private static Set<String> installedIncompatiblePlugins() {
|
private static Set<String> installedIncompatiblePlugins() {
|
||||||
Set<String> found = new LinkedHashSet<>();
|
Set<String> found = new LinkedHashSet<>();
|
||||||
Plugin[] plugins = server().getPluginManager().getPlugins();
|
Plugin[] plugins = server().getPluginManager().getPlugins();
|
||||||
|
|||||||
@@ -117,11 +117,6 @@ public class StudioSVC implements IrisService {
|
|||||||
private PackDownloadExecution activeDownload;
|
private PackDownloadExecution activeDownload;
|
||||||
private boolean downloadAdmissionOpen;
|
private boolean downloadAdmissionOpen;
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the stale cache/temp sweep a boot starts in the background. Pack imports stage through that
|
|
||||||
* folder, so a delete running underneath one truncates it; the import waits the sweep out instead of
|
|
||||||
* the boot waiting for the sweep.
|
|
||||||
*/
|
|
||||||
public static void gateDownloadsOnStaleTempCleanup(CompletableFuture<Void> cleanup) {
|
public static void gateDownloadsOnStaleTempCleanup(CompletableFuture<Void> cleanup) {
|
||||||
staleTempCleanup = cleanup == null ? CompletableFuture.completedFuture(null) : cleanup;
|
staleTempCleanup = cleanup == null ? CompletableFuture.completedFuture(null) : cleanup;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,11 +103,6 @@ public final class BukkitPlatform implements IrisPlatform {
|
|||||||
PLUGIN = plugin;
|
PLUGIN = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Drops every reference this class holds to the disabled plugin. Called last in the adapter's teardown,
|
|
||||||
* after core has stopped logging through the host bridge, so a disabled plugin instance is not reachable
|
|
||||||
* from a static for the life of the JVM.
|
|
||||||
*/
|
|
||||||
public static void releaseHost() {
|
public static void releaseHost() {
|
||||||
PLUGIN = null;
|
PLUGIN = null;
|
||||||
HUD_BAR = null;
|
HUD_BAR = null;
|
||||||
|
|||||||
@@ -18,30 +18,10 @@
|
|||||||
|
|
||||||
package art.arcane.iris.spi;
|
package art.arcane.iris.spi;
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a lookup whose failure means "this optional API, plugin or server capability is not here" and answers
|
|
||||||
* with a fallback instead of throwing.
|
|
||||||
* <p>
|
|
||||||
* This is the only sanctioned form of a quiet catch in Iris. A probe states the capability it was looking
|
|
||||||
* for, and a miss is recorded at {@link LogLevel#DEBUG} with the failure's class and message, so an operator
|
|
||||||
* running with debug on can tell a genuinely absent API apart from one that broke while being reached. Every
|
|
||||||
* other catch - world lifecycle, world replacement, runtime control, safeguard, service enable and disable,
|
|
||||||
* generation - reports through {@link IrisLogging#reportError(String, Throwable)} with the full trace.
|
|
||||||
* <p>
|
|
||||||
* Internal to Iris; not a published integration surface.
|
|
||||||
*/
|
|
||||||
public final class CapabilityProbe {
|
public final class CapabilityProbe {
|
||||||
private CapabilityProbe() {
|
private CapabilityProbe() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves {@code probe}, or returns {@code unavailable} when it throws.
|
|
||||||
*
|
|
||||||
* @param capability what was being looked for, for the debug record - for example
|
|
||||||
* {@code "world#getChunkAtAsync"}
|
|
||||||
* @param probe the lookup; any {@link Throwable} it raises means the capability is absent
|
|
||||||
* @param unavailable the value that stands for an absent capability
|
|
||||||
*/
|
|
||||||
public static <T> T attempt(String capability, Probe<T> probe, T unavailable) {
|
public static <T> T attempt(String capability, Probe<T> probe, T unavailable) {
|
||||||
try {
|
try {
|
||||||
return probe.resolve();
|
return probe.resolve();
|
||||||
@@ -51,9 +31,6 @@ public final class CapabilityProbe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs {@code attempt} and reports whether it completed, for a probe whose only result is that it worked.
|
|
||||||
*/
|
|
||||||
public static boolean succeeds(String capability, Attempt attempt) {
|
public static boolean succeeds(String capability, Attempt attempt) {
|
||||||
try {
|
try {
|
||||||
attempt.run();
|
attempt.run();
|
||||||
|
|||||||
Reference in new issue
Block a user