diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7c4f89bc..3fe7fd56 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -36,7 +36,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: dist
- path: ./target/OpenInv.jar
+ path: ./target/*.jar
- name: Upload API Jar
id: upload-api
uses: actions/upload-artifact@v4
diff --git a/addon/togglepersist/pom.xml b/addon/togglepersist/pom.xml
new file mode 100644
index 00000000..8d59bea6
--- /dev/null
+++ b/addon/togglepersist/pom.xml
@@ -0,0 +1,72 @@
+
+
+ 4.0.0
+
+
+ openinvparent
+ com.lishid
+ ../../pom.xml
+ 5.1.0-SNAPSHOT
+
+
+ openinvtogglepersist
+
+
+
+ annotations
+ org.jetbrains
+
+
+ org.spigotmc
+ spigot-api
+
+
+ openinvapi
+ com.lishid
+ provided
+
+
+
+
+ OITogglePersist
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ maven-compiler-plugin
+
+
+ maven-resources-plugin
+
+
+ copy-final-jar
+ package
+
+ copy-resources
+
+
+ ${project.parent.build.directory}
+
+
+ ${project.build.directory}
+
+ ${project.build.finalName}.jar
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addon/togglepersist/src/main/java/com/github/jikoo/openinv/togglepersist/TogglePersist.java b/addon/togglepersist/src/main/java/com/github/jikoo/openinv/togglepersist/TogglePersist.java
new file mode 100644
index 00000000..070ff081
--- /dev/null
+++ b/addon/togglepersist/src/main/java/com/github/jikoo/openinv/togglepersist/TogglePersist.java
@@ -0,0 +1,143 @@
+package com.github.jikoo.openinv.togglepersist;
+
+import com.google.errorprone.annotations.Keep;
+import com.lishid.openinv.event.PlayerToggledEvent;
+import com.lishid.openinv.util.setting.PlayerToggle;
+import com.lishid.openinv.util.setting.PlayerToggles;
+import org.bukkit.configuration.Configuration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.logging.Level;
+
+public class TogglePersist extends JavaPlugin implements Listener {
+
+ private final Map> enabledToggles = new HashMap<>();
+
+ @Override
+ public void onEnable() {
+ getServer().getPluginManager().registerEvents(this, this);
+
+ File file = new File(getDataFolder(), "toggles.yml");
+
+ // If there's no save file, there's nothing to load.
+ if (!file.exists()) {
+ return;
+ }
+
+ Configuration loaded = YamlConfiguration.loadConfiguration(file);
+
+ // For each toggle, enable loaded players.
+ for (String toggleName : loaded.getKeys(false)) {
+ PlayerToggle toggle = PlayerToggles.get(toggleName);
+ // Ensure toggle exists.
+ if (toggle == null) {
+ continue;
+ }
+
+ for (String idString : loaded.getStringList(toggleName)) {
+ // Ensure valid UUID.
+ UUID uuid;
+ try {
+ uuid = UUID.fromString(idString);
+ } catch (IllegalArgumentException e) {
+ continue;
+ }
+
+ // Track that toggle is enabled.
+ set(uuid, toggleName);
+ }
+ }
+ }
+
+ private void set(UUID playerId, String toggleName) {
+ enabledToggles.compute(playerId, (uuid, toggles) -> {
+ if (toggles == null) {
+ toggles = new HashSet<>();
+ }
+ toggles.add(toggleName);
+ return toggles;
+ });
+ }
+
+ @Override
+ public void onDisable() {
+ Map> converted = getSaveData();
+
+ YamlConfiguration data = new YamlConfiguration();
+ for (Map.Entry> playerToggle : converted.entrySet()) {
+ data.set(playerToggle.getKey(), playerToggle.getValue());
+ }
+
+ File file = new File(getDataFolder(), "toggles.yml");
+ try {
+ data.save(file);
+ } catch (IOException e) {
+ getLogger().log(Level.SEVERE, "Unable to save player toggle states", e);
+ }
+ }
+
+ private @NotNull Map> getSaveData() {
+ Map> converted = new HashMap<>();
+
+ for (Map.Entry> playerToggles : enabledToggles.entrySet()) {
+ String idString = playerToggles.getKey().toString();
+ for (String toggleName : playerToggles.getValue()) {
+ // Add player ID to listing for each enabled toggle.
+ converted.compute(toggleName, (name, ids) -> {
+ if (ids == null) {
+ ids = new ArrayList<>();
+ }
+ ids.add(idString);
+ return ids;
+ });
+ }
+ }
+ return converted;
+ }
+
+ @Keep
+ @EventHandler
+ private void onPlayerJoin(@NotNull PlayerJoinEvent event) {
+ UUID playerId = event.getPlayer().getUniqueId();
+ Set toggleNames = enabledToggles.get(playerId);
+
+ if (toggleNames == null) {
+ return;
+ }
+
+ for (String toggleName : toggleNames) {
+ PlayerToggle toggle = PlayerToggles.get(toggleName);
+ if (toggle != null) {
+ toggle.set(playerId, true);
+ }
+ }
+ }
+
+ @Keep
+ @EventHandler
+ private void onToggleSet(@NotNull PlayerToggledEvent event) {
+ if (event.isEnabled()) {
+ set(event.getPlayerId(), event.getToggle().getName());
+ } else {
+ enabledToggles.computeIfPresent(event.getPlayerId(), (uuid, toggles) -> {
+ toggles.remove(event.getToggle().getName());
+ return toggles.isEmpty() ? null : toggles;
+ });
+ }
+ }
+
+}
diff --git a/addon/togglepersist/src/main/resources/plugin.yml b/addon/togglepersist/src/main/resources/plugin.yml
new file mode 100644
index 00000000..cf84916e
--- /dev/null
+++ b/addon/togglepersist/src/main/resources/plugin.yml
@@ -0,0 +1,6 @@
+name: OITogglePersist
+main: com.github.jikoo.openinv.togglepersist.TogglePersist
+version: ${project.version}
+author: Jikoo
+description: An OpenInv addon allowing /anycontainer and /silentcontainer to persist across sessions.
+depend: [ OpenInv ]
diff --git a/api/pom.xml b/api/pom.xml
index b22bcca8..6469a94b 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -21,7 +21,7 @@
openinvparent
com.lishid
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
openinvapi
diff --git a/api/src/main/java/com/lishid/openinv/event/PlayerToggledEvent.java b/api/src/main/java/com/lishid/openinv/event/PlayerToggledEvent.java
new file mode 100644
index 00000000..82f23228
--- /dev/null
+++ b/api/src/main/java/com/lishid/openinv/event/PlayerToggledEvent.java
@@ -0,0 +1,71 @@
+package com.lishid.openinv.event;
+
+import com.google.errorprone.annotations.RestrictedApi;
+import com.lishid.openinv.util.setting.PlayerToggle;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
+/**
+ * Event fired after OpenInv modifies a toggleable setting for a player.
+ */
+public class PlayerToggledEvent extends Event {
+
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ private final @NotNull PlayerToggle toggle;
+ private final @NotNull UUID uuid;
+ private final boolean enabled;
+
+ @RestrictedApi(
+ explanation = "Constructor is not considered part of the API and may be subject to change.",
+ link = "",
+ allowedOnPath = ".*/com/lishid/openinv/event/OpenEvents.java")
+ @ApiStatus.Internal
+ PlayerToggledEvent(@NotNull PlayerToggle toggle, @NotNull UUID uuid, boolean enabled) {
+ this.toggle = toggle;
+ this.uuid = uuid;
+ this.enabled = enabled;
+ }
+
+ /**
+ * Get the {@link PlayerToggle} affected.
+ *
+ * @return the toggle
+ */
+ public @NotNull PlayerToggle getToggle() {
+ return toggle;
+ }
+
+ /**
+ * Get the {@link UUID} of the player whose setting was changed.
+ *
+ * @return the player ID
+ */
+ public @NotNull UUID getPlayerId() {
+ return uuid;
+ }
+
+ /**
+ * Get whether the toggle is enabled.
+ *
+ * @return true if the toggle is enabled
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+
+}
diff --git a/api/src/main/java/com/lishid/openinv/util/setting/PlayerToggle.java b/api/src/main/java/com/lishid/openinv/util/setting/PlayerToggle.java
new file mode 100644
index 00000000..6e8dc880
--- /dev/null
+++ b/api/src/main/java/com/lishid/openinv/util/setting/PlayerToggle.java
@@ -0,0 +1,36 @@
+package com.lishid.openinv.util.setting;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
+/**
+ * A per-player setting that may be enabled or disabled.
+ */
+public interface PlayerToggle {
+
+ /**
+ * Get the name of the setting.
+ *
+ * @return the setting name
+ */
+ @NotNull String getName();
+
+ /**
+ * Get the state of the toggle for a particular player ID.
+ *
+ * @param uuid the player ID
+ * @return true if the setting is enabled
+ */
+ boolean is(@NotNull UUID uuid);
+
+ /**
+ * Set the state of the toggle for a particular player ID.
+ *
+ * @param uuid the player ID
+ * @param enabled whether the setting is enabled
+ * @return true if the setting changed as a result of being set
+ */
+ boolean set(@NotNull UUID uuid, boolean enabled);
+
+}
diff --git a/api/src/main/java/com/lishid/openinv/util/setting/PlayerToggles.java b/api/src/main/java/com/lishid/openinv/util/setting/PlayerToggles.java
new file mode 100644
index 00000000..d61cd115
--- /dev/null
+++ b/api/src/main/java/com/lishid/openinv/util/setting/PlayerToggles.java
@@ -0,0 +1,106 @@
+package com.lishid.openinv.util.setting;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.UnmodifiableView;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Utility class containing all of OpenInv's {@link PlayerToggle PlayerToggles}.
+ */
+public final class PlayerToggles {
+
+ private static final Map TOGGLES = new HashMap<>();
+ private static final PlayerToggle ANY = add(new MemoryToggle("AnyContainer"));
+ private static final PlayerToggle SILENT = add(new MemoryToggle("SilentContainer"));
+
+ /**
+ * Get the AnyContainer toggle.
+ *
+ * @return the AnyContainer toggle
+ */
+ public static @NotNull PlayerToggle any() {
+ return ANY;
+ }
+
+ /**
+ * Get the SilentContainer toggle.
+ *
+ * @return the SilentContainer toggle
+ */
+ public static @NotNull PlayerToggle silent() {
+ return SILENT;
+ }
+
+ /**
+ * Get a toggle by name.
+ *
+ * @param toggleName the name of the toggle
+ * @return the toggle, or null if no such toggle exists.
+ */
+ public static @Nullable PlayerToggle get(@NotNull String toggleName) {
+ PlayerToggle toggle = TOGGLES.get(toggleName);
+ if (toggle == null) {
+ toggle = TOGGLES.get(toggleName.toLowerCase(Locale.ENGLISH));
+ }
+ return toggle;
+ }
+
+ /**
+ * Get an unmodifable view of all toggles available.
+ *
+ * @return a view of all toggles available
+ */
+ public static @UnmodifiableView @NotNull Collection get() {
+ return Collections.unmodifiableCollection(TOGGLES.values());
+ }
+
+ private static @NotNull PlayerToggle add(@NotNull PlayerToggle toggle) {
+ TOGGLES.put(toggle.getName().toLowerCase(Locale.ENGLISH), toggle);
+ return toggle;
+ }
+
+ private PlayerToggles() {
+ throw new IllegalStateException("Cannot create instance of utility class.");
+ }
+
+ private static class MemoryToggle implements PlayerToggle {
+
+ private final @NotNull Set enabled;
+ private final @NotNull String name;
+
+ private MemoryToggle(@NotNull String name) {
+ enabled = new HashSet<>();
+ this.name = name;
+ }
+
+ @Override
+ public @NotNull String getName() {
+ return this.name;
+ }
+
+ @Override
+ public boolean is(@NotNull UUID uuid) {
+ return enabled.contains(uuid);
+ }
+
+ @Override
+ public boolean set(@NotNull UUID uuid, boolean enabled) {
+ if (enabled) {
+ return this.enabled.add(uuid);
+ } else {
+ return this.enabled.remove(uuid);
+ }
+ }
+
+ }
+
+}
diff --git a/common/pom.xml b/common/pom.xml
index 9218e348..caaaa9a0 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -7,7 +7,7 @@
com.lishid
openinvparent
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
openinvcommon
diff --git a/common/src/main/java/com/lishid/openinv/event/OpenEvents.java b/common/src/main/java/com/lishid/openinv/event/OpenEvents.java
index 1ad3a8a8..626372c2 100644
--- a/common/src/main/java/com/lishid/openinv/event/OpenEvents.java
+++ b/common/src/main/java/com/lishid/openinv/event/OpenEvents.java
@@ -1,12 +1,15 @@
package com.lishid.openinv.event;
import com.lishid.openinv.internal.ISpecialInventory;
+import com.lishid.openinv.util.setting.PlayerToggle;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
+import java.util.UUID;
+
/**
* Construct and call events.
*/
@@ -20,6 +23,10 @@ public static boolean saveCancelled(@NotNull ISpecialInventory inventory) {
return call(new OpenPlayerSaveEvent((Player) inventory.getPlayer(), inventory));
}
+ public static void notifyPlayerToggle(@NotNull PlayerToggle toggle, @NotNull UUID uuid, boolean state) {
+ Bukkit.getPluginManager().callEvent(new PlayerToggledEvent(toggle, uuid, state));
+ }
+
private static boolean call(T event) {
Bukkit.getPluginManager().callEvent(event);
return event.isCancelled();
diff --git a/internal/v1_20_R3/pom.xml b/internal/v1_20_R3/pom.xml
index 9d04b233..7b4819bd 100644
--- a/internal/v1_20_R3/pom.xml
+++ b/internal/v1_20_R3/pom.xml
@@ -23,7 +23,7 @@
openinvparent
com.lishid
../../pom.xml
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
openinvadapter1_20_R3
diff --git a/internal/v1_20_R4/pom.xml b/internal/v1_20_R4/pom.xml
index 5127d6c8..db450049 100644
--- a/internal/v1_20_R4/pom.xml
+++ b/internal/v1_20_R4/pom.xml
@@ -23,7 +23,7 @@
openinvparent
com.lishid
../../pom.xml
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
openinvadapter1_20_R4
diff --git a/internal/v1_21_R1/pom.xml b/internal/v1_21_R1/pom.xml
index 7a14abf0..3b8cff46 100644
--- a/internal/v1_21_R1/pom.xml
+++ b/internal/v1_21_R1/pom.xml
@@ -23,7 +23,7 @@
openinvparent
com.lishid
../../pom.xml
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
openinvadapter1_21_R1
diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java
index ca969983..a3b331ed 100644
--- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java
+++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java
@@ -45,7 +45,7 @@ public abstract class OpenChestMenu> bukkitEntity;
// Syncher fields
private @Nullable ContainerSynchronizer synchronizer;
private final List dataSlots = new ArrayList<>();
@@ -129,7 +129,7 @@ protected void preSlotSetup() {}
@Override
- public final @NotNull CraftInventoryView getBukkitView() {
+ public final @NotNull CraftInventoryView> getBukkitView() {
if (bukkitEntity == null) {
bukkitEntity = createBukkitEntity();
}
@@ -137,14 +137,14 @@ protected void preSlotSetup() {}
return bukkitEntity;
}
- protected @NotNull CraftInventoryView createBukkitEntity() {
+ protected @NotNull CraftInventoryView> createBukkitEntity() {
Inventory top;
if (viewOnly) {
top = new OpenDummyInventory(container);
} else {
top = container.getBukkitInventory();
}
- return new CraftInventoryView(viewer.getBukkitEntity(), top, this) {
+ return new CraftInventoryView<>(viewer.getBukkitEntity(), top, this) {
@Override
public @Nullable Inventory getInventory(int rawSlot) {
if (viewOnly) {
diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java
index c80af6e2..3c11fe91 100644
--- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java
+++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java
@@ -104,7 +104,7 @@ protected boolean checkViewOnly() {
}
@Override
- protected @NotNull CraftInventoryView createBukkitEntity() {
+ protected @NotNull CraftInventoryView> createBukkitEntity() {
org.bukkit.inventory.Inventory bukkitInventory;
if (viewOnly) {
bukkitInventory = new OpenDummyInventory(container);
@@ -114,7 +114,7 @@ protected boolean checkViewOnly() {
bukkitInventory = container.getBukkitInventory();
}
- return new CraftInventoryView(viewer.getBukkitEntity(), bukkitInventory, this) {
+ return new CraftInventoryView<>(viewer.getBukkitEntity(), bukkitInventory, this) {
@Override
public org.bukkit.inventory.ItemStack getItem(int index) {
if (viewOnly || index < 0) {
@@ -174,7 +174,7 @@ public int convertSlot(int rawSlot) {
if (slot >= topSize) {
return super.getSlotType(offset + slot);
}
- return container.getSlotType(offset + slot);
+ return OpenInventoryMenu.this.container.getSlotType(offset + slot);
}
@Override
diff --git a/plugin/pom.xml b/plugin/pom.xml
index edad9226..9a4b4a36 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -21,7 +21,7 @@
openinvparent
com.lishid
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
openinvplugin
@@ -47,19 +47,19 @@
com.lishid
openinvadapter1_21_R1
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
compile
com.lishid
openinvadapter1_20_R4
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
compile
com.lishid
openinvadapter1_20_R3
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
compile
diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInv.java b/plugin/src/main/java/com/lishid/openinv/OpenInv.java
index 457bff17..3f74b3ec 100644
--- a/plugin/src/main/java/com/lishid/openinv/OpenInv.java
+++ b/plugin/src/main/java/com/lishid/openinv/OpenInv.java
@@ -29,13 +29,15 @@
import com.lishid.openinv.internal.ISpecialPlayerInventory;
import com.lishid.openinv.listener.ContainerListener;
import com.lishid.openinv.listener.LegacyInventoryListener;
+import com.lishid.openinv.listener.ToggleListener;
import com.lishid.openinv.util.config.Config;
import com.lishid.openinv.util.config.ConfigUpdater;
import com.lishid.openinv.util.InternalAccessor;
import com.lishid.openinv.util.InventoryManager;
import com.lishid.openinv.util.lang.LangMigrator;
import com.lishid.openinv.util.PlayerLoader;
-import com.lishid.openinv.util.setting.Toggles;
+import com.lishid.openinv.util.setting.PlayerToggle;
+import com.lishid.openinv.util.setting.PlayerToggles;
import com.lishid.openinv.util.lang.LanguageManager;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
@@ -50,6 +52,7 @@
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
+import java.util.Locale;
import java.util.UUID;
import java.util.function.Consumer;
@@ -60,7 +63,6 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
private InternalAccessor accessor;
private Config config;
- private Toggles toggles;
private InventoryManager inventoryManager;
private LanguageManager languageManager;
private PlayerLoader playerLoader;
@@ -70,7 +72,6 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
public void reloadConfig() {
super.reloadConfig();
config.reload(getConfig());
- toggles.reload(getConfig());
languageManager.reload();
if (accessor != null && accessor.isSupported()) {
accessor.reload(getConfig());
@@ -103,12 +104,6 @@ public void onEnable() {
// Set up configurable features. Note that #reloadConfig is called on the first call to #getConfig!
// Configuration values should not be accessed until after all of these have been set up.
config = new Config();
- toggles = new Toggles() {
- @Override
- public void save() {
- saveConfig();
- }
- };
languageManager = new LanguageManager(this, "en");
accessor = new InternalAccessor(getLogger(), languageManager);
@@ -132,22 +127,11 @@ public void save() {
// Update existing configuration. May require internal access.
new ConfigUpdater(this).checkForUpdates();
- // Get plugin manager
- PluginManager pm = this.getServer().getPluginManager();
- // Register listeners
- if (BukkitVersions.MINECRAFT.lessThan(Version.of(1, 21))) {
- pm.registerEvents(new LegacyInventoryListener(this), this);
- }
- pm.registerEvents(playerLoader, this);
- pm.registerEvents(inventoryManager, this);
- pm.registerEvents(new ContainerListener(accessor, toggles, languageManager), this);
+ // Register relevant event listeners.
+ registerEvents();
- // Register commands to their executors
- this.setCommandExecutor(new OpenInvCommand(this, config, inventoryManager, languageManager, playerLoader), "openinv", "openender");
- this.setCommandExecutor(new SearchContainerCommand(this, languageManager), "searchcontainer");
- this.setCommandExecutor(new SearchInvCommand(languageManager), "searchinv", "searchender");
- this.setCommandExecutor(new SearchEnchantCommand(languageManager), "searchenchant");
- this.setCommandExecutor(new ContainerSettingCommand(toggles, languageManager), "silentcontainer", "anycontainer");
+ // Register commands to their executors.
+ registerCommands();
} else {
this.sendVersionError(this.getLogger()::warning);
@@ -155,6 +139,30 @@ public void save() {
}
+ private void registerEvents() {
+ PluginManager pluginManager = this.getServer().getPluginManager();
+ // Legacy: extra listener for permission handling and self-view issue prevention.
+ if (BukkitVersions.MINECRAFT.lessThan(Version.of(1, 21))) {
+ pluginManager.registerEvents(new LegacyInventoryListener(this), this);
+ }
+ pluginManager.registerEvents(playerLoader, this);
+ pluginManager.registerEvents(inventoryManager, this);
+ pluginManager.registerEvents(new ContainerListener(accessor, languageManager), this);
+ pluginManager.registerEvents(new ToggleListener(), this);
+ }
+
+ private void registerCommands() {
+ this.setCommandExecutor(new OpenInvCommand(this, config, inventoryManager, languageManager, playerLoader), "openinv", "openender");
+ this.setCommandExecutor(new SearchContainerCommand(this, languageManager), "searchcontainer");
+ this.setCommandExecutor(new SearchInvCommand(languageManager), "searchinv", "searchender");
+ this.setCommandExecutor(new SearchEnchantCommand(languageManager), "searchenchant");
+
+ ContainerSettingCommand settingCommand = new ContainerSettingCommand(languageManager);
+ for (PlayerToggle toggle : PlayerToggles.get()) {
+ setCommandExecutor(settingCommand, toggle.getName().toLowerCase(Locale.ENGLISH));
+ }
+ }
+
private void setCommandExecutor(@NotNull CommandExecutor executor, String @NotNull ... commands) {
for (String commandName : commands) {
PluginCommand command = this.getCommand(commandName);
@@ -210,22 +218,22 @@ public boolean noArgsOpensSelf() {
@Override
public boolean getAnyContainerStatus(@NotNull final OfflinePlayer offline) {
- return toggles.any().is(offline.getUniqueId());
+ return PlayerToggles.any().is(offline.getUniqueId());
}
@Override
public void setAnyContainerStatus(@NotNull final OfflinePlayer offline, final boolean status) {
- toggles.any().set(offline.getUniqueId(), status);
+ PlayerToggles.any().set(offline.getUniqueId(), status);
}
@Override
public boolean getSilentContainerStatus(@NotNull final OfflinePlayer offline) {
- return toggles.silent().is(offline.getUniqueId());
+ return PlayerToggles.silent().is(offline.getUniqueId());
}
@Override
public void setSilentContainerStatus(@NotNull final OfflinePlayer offline, final boolean status) {
- toggles.silent().set(offline.getUniqueId(), status);
+ PlayerToggles.silent().set(offline.getUniqueId(), status);
}
@Override
diff --git a/plugin/src/main/java/com/lishid/openinv/command/ContainerSettingCommand.java b/plugin/src/main/java/com/lishid/openinv/command/ContainerSettingCommand.java
index bc2f7906..af00131b 100644
--- a/plugin/src/main/java/com/lishid/openinv/command/ContainerSettingCommand.java
+++ b/plugin/src/main/java/com/lishid/openinv/command/ContainerSettingCommand.java
@@ -16,15 +16,17 @@
package com.lishid.openinv.command;
+import com.lishid.openinv.event.OpenEvents;
import com.lishid.openinv.util.setting.PlayerToggle;
import com.lishid.openinv.util.TabCompleter;
-import com.lishid.openinv.util.setting.Toggles;
+import com.lishid.openinv.util.setting.PlayerToggles;
import com.lishid.openinv.util.lang.LanguageManager;
import com.lishid.openinv.util.lang.Replacement;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
@@ -34,11 +36,9 @@
public class ContainerSettingCommand implements TabExecutor {
- private final @NotNull Toggles toggles;
private final @NotNull LanguageManager lang;
- public ContainerSettingCommand(@NotNull Toggles toggles, @NotNull LanguageManager lang) {
- this.toggles = toggles;
+ public ContainerSettingCommand(@NotNull LanguageManager lang) {
this.lang = lang;
}
@@ -49,24 +49,30 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
return true;
}
- boolean any = command.getName().startsWith("any");
- PlayerToggle toggle = any ? toggles.any() : toggles.silent();
+ PlayerToggle toggle = PlayerToggles.get(command.getName());
+
+ // Shouldn't be possible.
+ if (toggle == null) {
+ JavaPlugin.getProvidingPlugin(getClass()).getLogger().warning("Command /" + command.getName() + " registered with no corresponding toggle!");
+ return false;
+ }
+
UUID playerId = player.getUniqueId();
if (args.length > 0) {
args[0] = args[0].toLowerCase(Locale.ENGLISH);
if (args[0].equals("on")) {
- toggle.set(playerId, true);
+ set(toggle, playerId, true);
} else if (args[0].equals("off")) {
- toggle.set(playerId, false);
+ set(toggle, playerId, false);
} else if (!args[0].equals("check")) {
// Invalid argument, show usage.
return false;
}
} else {
- toggle.set(playerId, !toggle.is(playerId));
+ set(toggle, playerId, !toggle.is(playerId));
}
String onOff = lang.getLocalizedMessage(player, toggle.is(playerId) ? "messages.info.on" : "messages.info.off");
@@ -77,12 +83,18 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
lang.sendMessage(
sender,
"messages.info.settingState",
- new Replacement("%setting%", any ? "AnyContainer" : "SilentContainer"),
+ new Replacement("%setting%", toggle.getName()),
new Replacement("%state%", onOff));
return true;
}
+ private void set(@NotNull PlayerToggle toggle, @NotNull UUID uuid, boolean state) {
+ if (toggle.set(uuid, state)) {
+ OpenEvents.notifyPlayerToggle(toggle, uuid, state);
+ }
+ }
+
@Override
public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!command.testPermissionSilent(sender) || args.length != 1) {
diff --git a/plugin/src/main/java/com/lishid/openinv/listener/ContainerListener.java b/plugin/src/main/java/com/lishid/openinv/listener/ContainerListener.java
index ecc708da..d93e7f54 100644
--- a/plugin/src/main/java/com/lishid/openinv/listener/ContainerListener.java
+++ b/plugin/src/main/java/com/lishid/openinv/listener/ContainerListener.java
@@ -20,7 +20,7 @@
import com.lishid.openinv.internal.ViewOnly;
import com.lishid.openinv.util.InternalAccessor;
import com.lishid.openinv.util.Permissions;
-import com.lishid.openinv.util.setting.Toggles;
+import com.lishid.openinv.util.setting.PlayerToggles;
import com.lishid.openinv.util.lang.LanguageManager;
import org.bukkit.GameMode;
import org.bukkit.entity.HumanEntity;
@@ -47,12 +47,10 @@
public class ContainerListener implements Listener {
private final @NotNull InternalAccessor accessor;
- private final @NotNull Toggles toggles;
private final @NotNull LanguageManager lang;
- public ContainerListener(@NotNull InternalAccessor accessor, @NotNull Toggles toggles, @NotNull LanguageManager lang) {
+ public ContainerListener(@NotNull InternalAccessor accessor, @NotNull LanguageManager lang) {
this.accessor = accessor;
- this.toggles = toggles;
this.lang = lang;
}
@@ -74,14 +72,14 @@ private void onPlayerInteract(@NotNull PlayerInteractEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
- boolean any = Permissions.CONTAINER_ANY.hasPermission(player) && toggles.any().is(playerId);
+ boolean any = Permissions.CONTAINER_ANY.hasPermission(player) && PlayerToggles.any().is(playerId);
boolean needsAny = accessor.getAnySilentContainer().isAnyContainerNeeded(event.getClickedBlock());
if (!any && needsAny) {
return;
}
- boolean silent = Permissions.CONTAINER_SILENT.hasPermission(player) && toggles.silent().is(playerId);
+ boolean silent = Permissions.CONTAINER_SILENT.hasPermission(player) && PlayerToggles.silent().is(playerId);
// If anycontainer or silentcontainer is active
if (any || silent) {
@@ -106,7 +104,7 @@ private void onInventoryClose(@NotNull final InventoryCloseEvent event) {
}
InventoryHolder holder = event.getInventory().getHolder();
- if (toggles.silent().is(player.getUniqueId())
+ if (PlayerToggles.silent().is(player.getUniqueId())
&& holder != null
&& this.accessor.getAnySilentContainer().isAnySilentContainer(holder)) {
this.accessor.getAnySilentContainer().deactivateContainer(player);
diff --git a/plugin/src/main/java/com/lishid/openinv/listener/ToggleListener.java b/plugin/src/main/java/com/lishid/openinv/listener/ToggleListener.java
new file mode 100644
index 00000000..b39535ae
--- /dev/null
+++ b/plugin/src/main/java/com/lishid/openinv/listener/ToggleListener.java
@@ -0,0 +1,22 @@
+package com.lishid.openinv.listener;
+
+import com.google.errorprone.annotations.Keep;
+import com.lishid.openinv.util.setting.PlayerToggles;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.UUID;
+
+public class ToggleListener implements Listener {
+
+ @Keep
+ @EventHandler
+ private void onPlayerQuit(@NotNull PlayerQuitEvent event) {
+ UUID playerId = event.getPlayer().getUniqueId();
+ PlayerToggles.any().set(playerId, false);
+ PlayerToggles.silent().set(playerId, false);
+ }
+
+}
diff --git a/plugin/src/main/java/com/lishid/openinv/util/config/ConfigUpdater.java b/plugin/src/main/java/com/lishid/openinv/util/config/ConfigUpdater.java
index 6e86ee66..c5203d69 100644
--- a/plugin/src/main/java/com/lishid/openinv/util/config/ConfigUpdater.java
+++ b/plugin/src/main/java/com/lishid/openinv/util/config/ConfigUpdater.java
@@ -16,17 +16,15 @@
package com.lishid.openinv.util.config;
-import com.lishid.openinv.OpenInv;
-import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.plugin.Plugin;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-public record ConfigUpdater(OpenInv plugin) {
+public record ConfigUpdater(@NotNull Plugin plugin) {
public void checkForUpdates() {
final int version = plugin.getConfig().getInt("config-version", 1);
@@ -45,119 +43,78 @@ public void checkForUpdates() {
plugin.getLogger().warning("Could not back up config.yml before updating!");
}
- plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
- if (version < 2) {
- updateConfig1To2();
- }
- if (version < 3) {
- updateConfig2To3();
- }
- if (version < 4) {
- updateConfig3To4();
- }
- if (version < 5) {
- updateConfig4To5();
- }
- if (version < 6) {
- updateConfig5To6();
- }
-
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- plugin.saveConfig();
- plugin.getLogger().info("Configuration update complete!");
- });
- });
+ if (version < 2) {
+ updateConfig1To2();
+ }
+ if (version < 3) {
+ updateConfig2To3();
+ }
+ if (version < 4) {
+ updateConfig3To4();
+ }
+ if (version < 5) {
+ updateConfig4To5();
+ }
+ if (version < 6) {
+ updateConfig5To6();
+ }
+ if (version < 7) {
+ updateConfig6To7();
+ }
+
+ plugin.saveConfig();
+ plugin.getLogger().info("Configuration update complete!");
+ }
+
+ private void updateConfig6To7() {
+ FileConfiguration config = plugin.getConfig();
+ config.set("toggles", null);
+ String consoleLocale = config.getString("settings.locale", "en");
+ if (consoleLocale.isBlank() || consoleLocale.equalsIgnoreCase("en_us")) {
+ consoleLocale = "en";
+ }
+ config.set("settings.console-locale", consoleLocale);
+ config.set("settings.locale", null);
+ config.set("config-version", 7);
}
private void updateConfig5To6() {
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- plugin.getConfig().set("settings.command.open.no-args-opens-self", false);
- plugin.getConfig().set("settings.command.searchcontainer.max-radius", 10);
- plugin.getConfig().set("config-version", 6);
- });
+ FileConfiguration config = plugin.getConfig();
+ config.set("settings.command.open.no-args-opens-self", false);
+ config.set("settings.command.searchcontainer.max-radius", 10);
+ config.set("config-version", 6);
}
private void updateConfig4To5() {
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- plugin.getConfig().set("settings.disable-offline-access", false);
- plugin.getConfig().set("config-version", 5);
- });
+ FileConfiguration config = plugin.getConfig();
+ config.set("settings.disable-offline-access", false);
+ config.set("config-version", 5);
}
private void updateConfig3To4() {
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- plugin.getConfig().set("notify", null);
- plugin.getConfig().set("settings.locale", "en_US");
- plugin.getConfig().set("config-version", 4);
- });
+ FileConfiguration config = plugin.getConfig();
+ config.set("notify", null);
+ config.set("config-version", 4);
}
private void updateConfig2To3() {
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- plugin.getConfig().set("config-version", 3);
- plugin.getConfig().set("items.open-inv", null);
- plugin.getConfig().set("ItemOpenInv", null);
- plugin.getConfig().set("toggles.items.open-inv", null);
- plugin.getConfig().set("settings.disable-saving",
- plugin.getConfig().getBoolean("DisableSaving", false));
- plugin.getConfig().set("DisableSaving", null);
- });
+ FileConfiguration config = plugin.getConfig();
+ config.set("items", null);
+ config.set("ItemOpenInv", null);
+ config.set("toggles", null);
+ config.set("settings.disable-saving", config.getBoolean("DisableSaving", false));
+ config.set("DisableSaving", null);
+ config.set("config-version", 3);
}
private void updateConfig1To2() {
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- // Get the old config settings
- boolean notifySilentChest = plugin.getConfig().getBoolean("NotifySilentChest", true);
- boolean notifyAnyChest = plugin.getConfig().getBoolean("NotifyAnyChest", true);
- plugin.getConfig().set("ItemOpenInvItemID", null);
- plugin.getConfig().set("NotifySilentChest", null);
- plugin.getConfig().set("NotifyAnyChest", null);
- plugin.getConfig().set("config-version", 2);
- plugin.getConfig().set("notify.any-chest", notifyAnyChest);
- plugin.getConfig().set("notify.silent-chest", notifySilentChest);
- });
-
- updateToggles("AnyChest", "toggles.any-chest");
- updateToggles("SilentChest", "toggles.silent-chest");
- }
-
- private void updateToggles(final String sectionName, final String newSectionName) {
- ConfigurationSection section = plugin.getConfig().getConfigurationSection(sectionName);
- // Ensure section exists
- if (section == null) {
- return;
- }
-
- Set keys = section.getKeys(false);
-
- // Ensure section has content
- if (keys.isEmpty()) {
- return;
- }
-
- final Map toggles = new HashMap<>();
-
- for (String playerName : keys) {
- OfflinePlayer player = plugin.matchPlayer(playerName);
- if (player != null) {
- toggles.put(player.getUniqueId().toString(), section.getBoolean(playerName + ".toggle", false));
- }
- }
-
- plugin.getServer().getScheduler().runTask(plugin, () -> {
- // Wipe old ConfigurationSection
- plugin.getConfig().set(sectionName, null);
-
- // Prepare new ConfigurationSection
- ConfigurationSection newSection = plugin.getConfig().getConfigurationSection(newSectionName);
- if (newSection == null) {
- newSection = plugin.getConfig().createSection(newSectionName);
- }
- // Set new values
- for (Map.Entry entry : toggles.entrySet()) {
- newSection.set(entry.getKey(), entry.getValue());
- }
- });
+ FileConfiguration config = plugin.getConfig();
+ config.set("ItemOpenInvItemID", null);
+ config.set("NotifySilentChest", null);
+ config.set("NotifyAnyChest", null);
+ config.set("AnyChest", null);
+ config.set("SilentChest", null);
+ config.set("config-version", 2);
}
}
diff --git a/plugin/src/main/java/com/lishid/openinv/util/setting/PlayerToggle.java b/plugin/src/main/java/com/lishid/openinv/util/setting/PlayerToggle.java
deleted file mode 100644
index 85c1eb3a..00000000
--- a/plugin/src/main/java/com/lishid/openinv/util/setting/PlayerToggle.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.lishid.openinv.util.setting;
-
-import java.util.UUID;
-
-public interface PlayerToggle {
-
- boolean is(UUID uuid);
-
- void set(UUID uuid, boolean value);
-
-}
diff --git a/plugin/src/main/java/com/lishid/openinv/util/setting/Toggles.java b/plugin/src/main/java/com/lishid/openinv/util/setting/Toggles.java
deleted file mode 100644
index a830ecdf..00000000
--- a/plugin/src/main/java/com/lishid/openinv/util/setting/Toggles.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.lishid.openinv.util.setting;
-
-import org.bukkit.configuration.MemoryConfiguration;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.UUID;
-
-public abstract class Toggles {
-
- private static final String TOGGLE_ANYCONTAINER_BASE = "toggles.any-chest.";
- private static final String TOGGLE_SILENTCONTAINER_BASE = "toggles.silent-chest.";
-
- private final PlayerToggle any = new PlayerToggle() {
- @Override
- public boolean is(UUID uuid) {
- return configuration.getBoolean(TOGGLE_ANYCONTAINER_BASE + uuid, false);
- }
-
- @Override
- public void set(UUID uuid, boolean value) {
- configuration.set(TOGGLE_ANYCONTAINER_BASE + uuid, value);
- save();
- }
- };
-
- private final PlayerToggle silent = new PlayerToggle() {
- @Override
- public boolean is(UUID uuid) {
- return configuration.getBoolean(TOGGLE_SILENTCONTAINER_BASE + uuid, false);
- }
-
- @Override
- public void set(UUID uuid, boolean value) {
- configuration.set(TOGGLE_SILENTCONTAINER_BASE + uuid, value);
- save();
- }
- };
-
- private @NotNull MemoryConfiguration configuration;
-
- public Toggles() {
- this.configuration = new MemoryConfiguration();
- }
-
- public PlayerToggle any() {
- return any;
- }
-
- public PlayerToggle silent() {
- return silent;
- }
-
- public void reload(@NotNull MemoryConfiguration configuration) {
- this.configuration = configuration;
- }
-
- public abstract void save();
-
-}
diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml
index 6a68c9cb..a9133fe3 100644
--- a/plugin/src/main/resources/config.yml
+++ b/plugin/src/main/resources/config.yml
@@ -1,4 +1,4 @@
-config-version: 6
+config-version: 7
settings:
command:
open:
@@ -7,4 +7,4 @@ settings:
max-radius: 10
disable-offline-access: false
disable-saving: false
- locale: 'en_us'
+ console-locale: 'en'
diff --git a/pom.xml b/pom.xml
index 8c2a55a4..063ab17c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
common
- 5.0.1-SNAPSHOT
+ 5.1.0-SNAPSHOT
pom
@@ -41,6 +41,7 @@
all
api
+ addon/togglepersist
common
internal/v1_21_R1
internal/v1_20_R4