mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-11 19:14:11 +00:00
Added shared update notices
- Iris joins shared Volmit update checks and reports - The iris.update permission controls update visibility - general.updateNotifications defaults to enabled - Accepted settings changes reconfigure update checks - Shutdown removes the settings listener and closes update checks - Tests cover persisted opt-outs and notifier lifecycle
This commit is contained in:
@@ -37,6 +37,7 @@ import art.arcane.iris.world.PendingWorldDeleteQueue;
|
||||
import art.arcane.iris.world.PendingWorldReplacementManager;
|
||||
import art.arcane.iris.world.WorldRefusalReporter;
|
||||
import art.arcane.iris.configuration.SettingsHotloadWatch;
|
||||
import art.arcane.iris.update.IrisUpdateNotifier;
|
||||
import art.arcane.iris.pack.datapack.ServerConfigurator;
|
||||
import art.arcane.iris.pack.datapack.DatapackIngestService;
|
||||
import art.arcane.iris.pack.datapack.DatapackIngestService.StartupValidationOutcome;
|
||||
@@ -215,6 +216,7 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
private final PendingWorldDeleteQueue pendingWorldDeletes = new PendingWorldDeleteQueue(this);
|
||||
private final PendingWorldReplacementManager pendingWorldReplacements = new PendingWorldReplacementManager(this);
|
||||
private BukkitLanguageSwitcher languageSwitcher;
|
||||
private IrisUpdateNotifier updateNotifier;
|
||||
private BukkitDebugDump debugDump;
|
||||
private volatile SettingsHotloadWatch settingsHotloadWatch;
|
||||
private volatile Thread serverLifecycleThread;
|
||||
@@ -637,6 +639,7 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
languageSwitcher = BukkitLanguageSwitcher.register(this, IrisLanguage.selections(),
|
||||
new BukkitLanguageSwitcher.Options("iris", "iris.all",
|
||||
DirectorMiniMenu.Theme.irisGreen(), IrisLanguage.directorResolver(), IrisLanguage.editorOptions()));
|
||||
updateNotifier = new IrisUpdateNotifier(this);
|
||||
PaperLibBootstrap.install();
|
||||
SimdSupport.install();
|
||||
timings.mark("bootstrap");
|
||||
@@ -974,6 +977,10 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
if (updateNotifier != null) {
|
||||
updateNotifier.close();
|
||||
updateNotifier = null;
|
||||
}
|
||||
if (debugDump != null) {
|
||||
debugDump.close();
|
||||
debugDump = null;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package art.arcane.iris.update;
|
||||
|
||||
import art.arcane.iris.configuration.IrisSettings;
|
||||
import art.arcane.volmlib.util.update.BukkitUpdateService;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class IrisUpdateNotifier implements AutoCloseable {
|
||||
private final Consumer<IrisSettings> settingsListener = this::reconfigure;
|
||||
private final BukkitUpdateService updates;
|
||||
private volatile boolean enabled;
|
||||
private boolean closed;
|
||||
|
||||
public IrisUpdateNotifier(Plugin plugin) {
|
||||
enabled = IrisSettings.get().getGeneral().isUpdateNotifications();
|
||||
updates = BukkitUpdateService.register(plugin, new BukkitUpdateService.Options(
|
||||
"VolmitSoftware", "Iris", "iris.update", () -> enabled));
|
||||
IrisSettings.addSettingsListener(settingsListener);
|
||||
reconfigure(IrisSettings.get());
|
||||
}
|
||||
|
||||
private synchronized void reconfigure(IrisSettings settings) {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
enabled = settings.getGeneral().isUpdateNotifications();
|
||||
updates.reconfigure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
closed = true;
|
||||
IrisSettings.removeSettingsListener(settingsListener);
|
||||
updates.close();
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@ authors: [ cyberpwn, NextdoorPsycho, Vatuu ]
|
||||
website: VolmitSoftware.com
|
||||
description: More than a Dimension!
|
||||
permissions:
|
||||
iris.update:
|
||||
description: Allows viewing Iris updates in VolmLib's combined update reports.
|
||||
default: op
|
||||
iris.debugdump:
|
||||
description: Allows creating and optionally uploading diagnostic reports.
|
||||
default: op
|
||||
|
||||
@@ -23,6 +23,9 @@ commands:
|
||||
iris:
|
||||
aliases: [ ir, irs ]
|
||||
permissions:
|
||||
iris.update:
|
||||
description: Allows viewing Iris updates in VolmLib's combined update reports.
|
||||
default: op
|
||||
iris.debugdump:
|
||||
description: Allows creating and optionally uploading diagnostic reports.
|
||||
default: op
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package art.arcane.iris.update;
|
||||
|
||||
import art.arcane.iris.configuration.IrisSettings;
|
||||
import art.arcane.volmlib.util.update.BukkitUpdateService;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
public class IrisUpdateNotifierTest {
|
||||
@Test
|
||||
public void acceptedSettingsReconfigureChecksAndClosingRemovesTheListener() {
|
||||
IrisSettings previous = IrisSettings.settings;
|
||||
IrisSettings.settings = new IrisSettings();
|
||||
Plugin plugin = mock(Plugin.class);
|
||||
BukkitUpdateService service = mock(BukkitUpdateService.class);
|
||||
try (MockedStatic<BukkitUpdateService> registration = mockStatic(BukkitUpdateService.class)) {
|
||||
registration.when(() -> BukkitUpdateService.register(eq(plugin), any())).thenReturn(service);
|
||||
IrisUpdateNotifier notifier = new IrisUpdateNotifier(plugin);
|
||||
try {
|
||||
ArgumentCaptor<BukkitUpdateService.Options> options = ArgumentCaptor.forClass(BukkitUpdateService.Options.class);
|
||||
registration.verify(() -> BukkitUpdateService.register(eq(plugin), options.capture()));
|
||||
assertEquals("VolmitSoftware", options.getValue().owner());
|
||||
assertEquals("Iris", options.getValue().repository());
|
||||
assertEquals("iris.update", options.getValue().permission());
|
||||
assertTrue(options.getValue().enabled().getAsBoolean());
|
||||
|
||||
clearInvocations(service);
|
||||
assertFalse(IrisSettings.applyHotloadSnapshot(
|
||||
"{\"general\":{\"updateNotifications\":false}}", candidate -> false));
|
||||
assertTrue(options.getValue().enabled().getAsBoolean());
|
||||
verifyNoInteractions(service);
|
||||
|
||||
IrisSettings.installHotloadSnapshot("{\"general\":{\"updateNotifications\":false}}");
|
||||
assertFalse(options.getValue().enabled().getAsBoolean());
|
||||
verify(service).reconfigure();
|
||||
IrisSettings.settings.getGeneral().setUpdateNotifications(true);
|
||||
assertFalse(options.getValue().enabled().getAsBoolean());
|
||||
} finally {
|
||||
notifier.close();
|
||||
}
|
||||
verify(service).close();
|
||||
clearInvocations(service);
|
||||
IrisSettings.installHotloadSnapshot("{}");
|
||||
verifyNoInteractions(service);
|
||||
} finally {
|
||||
IrisSettings.settings = previous;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,11 +33,14 @@ import lombok.Data;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Data
|
||||
public class IrisSettings {
|
||||
private static final Object SETTINGS_LOCK = new Object();
|
||||
private static final CopyOnWriteArrayList<Consumer<IrisSettings>> LISTENERS = new CopyOnWriteArrayList<>();
|
||||
private static final IrisSettings BOOTSTRAP_DEFAULTS = new IrisSettings();
|
||||
public static volatile IrisSettings settings;
|
||||
private IrisSettingsGeneral general = new IrisSettingsGeneral();
|
||||
@@ -80,6 +83,7 @@ public class IrisSettings {
|
||||
|
||||
current = read();
|
||||
settings = current;
|
||||
notifySettingsChanged(current);
|
||||
return current;
|
||||
}
|
||||
}
|
||||
@@ -130,6 +134,7 @@ public class IrisSettings {
|
||||
IrisSettings parsed = parseHotloadSnapshot(rawJson);
|
||||
synchronized (SETTINGS_LOCK) {
|
||||
settings = parsed;
|
||||
notifySettingsChanged(parsed);
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
@@ -142,6 +147,7 @@ public class IrisSettings {
|
||||
}
|
||||
synchronized (SETTINGS_LOCK) {
|
||||
settings = parsed;
|
||||
notifySettingsChanged(parsed);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -165,6 +171,20 @@ public class IrisSettings {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
public static void addSettingsListener(Consumer<IrisSettings> listener) {
|
||||
LISTENERS.add(Objects.requireNonNull(listener));
|
||||
}
|
||||
|
||||
public static void removeSettingsListener(Consumer<IrisSettings> listener) {
|
||||
LISTENERS.remove(listener);
|
||||
}
|
||||
|
||||
private static void notifySettingsChanged(IrisSettings current) {
|
||||
for (Consumer<IrisSettings> listener : LISTENERS) {
|
||||
listener.accept(current);
|
||||
}
|
||||
}
|
||||
|
||||
public void forceSave() {
|
||||
File s = IrisPlatforms.get().dataFile("iris.json");
|
||||
|
||||
@@ -310,6 +330,7 @@ public class IrisSettings {
|
||||
public static class IrisSettingsGeneral {
|
||||
public String language = "en_US";
|
||||
public boolean metrics = true;
|
||||
public boolean updateNotifications = true;
|
||||
public boolean commandSounds = true;
|
||||
public boolean debug = false;
|
||||
public boolean dumpMantleOnError = false;
|
||||
|
||||
@@ -12,6 +12,16 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public class IrisSettingsDefaultsTest {
|
||||
@Test
|
||||
public void updateChecksDefaultOnAndPersistAnExplicitOptOut() {
|
||||
assertTrue(IrisSettings.parseHotloadSnapshot("{}").getGeneral().isUpdateNotifications());
|
||||
IrisSettings optedOut = IrisSettings.parseHotloadSnapshot(
|
||||
"{\"general\":{\"updateNotifications\":false}}");
|
||||
assertFalse(optedOut.getGeneral().isUpdateNotifications());
|
||||
assertFalse(new Gson().fromJson(new Gson().toJson(optedOut), IrisSettings.class)
|
||||
.getGeneral().isUpdateNotifications());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void regionBudgetLeavesHeapForHydrologyAndServerChunks() {
|
||||
IrisSettings.IrisSettingsPregen settings = new IrisSettings.IrisSettingsPregen();
|
||||
|
||||
Reference in New Issue
Block a user