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