From 251de5d271c30c3d9783c862249ad0a2cb03e6d6 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:29:11 +0800 Subject: [PATCH 1/7] Remove migration plugin support and playerdata import (reimplemented in Multiverse-InventoriesImporter) --- build.gradle | 19 - .../inventories/MultiverseInventories.java | 11 - .../inventories/commands/MigrateCommand.java | 8 + .../commands/PlayerDataImportCommand.java | 61 +-- .../multiinv/MIInventoryConverter.java | 29 -- .../multiinv/MIInventoryInterface.java | 20 - .../multiinv/MIInventoryOldWrapper.java | 25 -- .../multiinv/MIInventoryWrapper.java | 25 -- .../multiinv/MIPlayerFileLoader.java | 114 ------ .../multiinv/MultiInvImportHelper.java | 149 -------- .../dataimport/multiinv/MultiInvImporter.java | 63 ---- .../dataimport/multiinv/package-info.java | 5 - .../PerWorldInventoryImporter.java | 66 ---- .../perworldinventory/PwiImportHelper.java | 356 ------------------ .../perworldinventory/package-info.java | 1 - .../WorldInventoriesImportHelper.java | 264 ------------- .../WorldInventoriesImporter.java | 64 ---- .../worldinventories/package-info.java | 5 - .../profile/nbt/PlayerDataExtractor.java | 5 + .../multiverse-inventories_en.properties | 2 +- 20 files changed, 17 insertions(+), 1275 deletions(-) delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryConverter.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryInterface.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryOldWrapper.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryWrapper.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIPlayerFileLoader.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImportHelper.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImporter.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/package-info.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PerWorldInventoryImporter.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PwiImportHelper.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/package-info.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImportHelper.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImporter.java delete mode 100644 src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/package-info.java diff --git a/build.gradle b/build.gradle index 193dec0c..5d3871c2 100644 --- a/build.gradle +++ b/build.gradle @@ -7,11 +7,6 @@ group = 'org.mvplugins.multiverse.inventories' description = 'Multiverse-Inventories' repositories { - maven { - name = 'codemc' - url = uri('https://repo.codemc.org/repository/maven-releases') - } - maven { name = "helpchatRepoReleases" url = uri("https://repo.helpch.at/releases/") @@ -59,24 +54,10 @@ dependencies { // Luckperms for group context compileOnly 'net.luckperms:api:5.4' - // Other plugins for import - compileOnly('uk.co:MultiInv:3.0.6') { - exclude group: '*', module: '*' - } - compileOnly('me.drayshak:WorldInventories:1.0.2') { - exclude group: '*', module: '*' - } - // perworldinventory is weird and has snakeyaml included in the jar, so we can only use compileOnly for build to work properly - compileOnly('me.ebonjaeger:perworldinventory-kt:2.3.2') { - exclude group: '*', module: '*' - } - // hk2 for annotation processing only compileOnly('org.glassfish.hk2:hk2-api:3.1.1') { exclude group: '*', module: '*' } - annotationProcessor 'org.glassfish.hk2:hk2-metadata-generator:3.1.1' - testAnnotationProcessor 'org.glassfish.hk2:hk2-metadata-generator:3.1.1' } shadowJar { diff --git a/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java b/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java index 38631539..ac40c799 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java @@ -63,8 +63,6 @@ public class MultiverseInventories extends MultiverseModule { @Inject private Provider profileContainerStoreProvider; @Inject - private Provider dataImportManager; - @Inject private Provider mvInvCommandCompletion; @Inject private Provider mvInvCommandContexts; @@ -112,9 +110,6 @@ public final void onEnable() { this.registerCommands(); this.registerDestinations(); - // Hook plugins that can be imported from - this.hookImportables(); - // Init other extensions this.hookLuckPerms(); this.loadPlaceholderApiIntegration(); @@ -171,12 +166,6 @@ private void registerDestinations() { destinationsProvider.get().registerDestination(serviceLocator.getService(LastLocationDestination.class)); } - private void hookImportables() { - serviceLocator.getAllServices(DataImporter.class).forEach(dataImporter -> { - dataImportManager.get().register(dataImporter); - }); - } - private void hookLuckPerms() { Try.run(() -> Class.forName("net.luckperms.api.LuckPerms")) .onFailure(e -> Logging.fine("Luckperms is not installed!")) diff --git a/src/main/java/org/mvplugins/multiverse/inventories/commands/MigrateCommand.java b/src/main/java/org/mvplugins/multiverse/inventories/commands/MigrateCommand.java index 62965a1c..3a6cb7dd 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/commands/MigrateCommand.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/commands/MigrateCommand.java @@ -1,5 +1,6 @@ package org.mvplugins.multiverse.inventories.commands; +import com.dumptruckman.minecraft.util.Logging; import org.jetbrains.annotations.NotNull; import org.jvnet.hk2.annotations.Service; import org.mvplugins.multiverse.core.command.MVCommandIssuer; @@ -46,6 +47,13 @@ void onMigrateCommand( @Syntax("") String pluginName) { + if (dataImportManager.getEnabledImporterNames().isEmpty()) { + issuer.sendError("Please install Multiverse-InventoriesImporter plugin to use this command."); + issuer.sendInfo("Download Link: https://modrinth.com/project/multiverse-inventoriesimporter/"); + issuer.sendInfo("Learn More: https://mvplugins.org/inventories/how-to/import-playerdata/"); + return; + } + dataImportManager.getImporter(pluginName) .onEmpty(() -> issuer.sendError(MVInvi18n.MIGRATE_UNSUPPORTEDPLUGIN, replace("{plugin}").with(pluginName))) .peek(dataImporter -> { diff --git a/src/main/java/org/mvplugins/multiverse/inventories/commands/PlayerDataImportCommand.java b/src/main/java/org/mvplugins/multiverse/inventories/commands/PlayerDataImportCommand.java index ce4f57f1..0a0fe19a 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/commands/PlayerDataImportCommand.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/commands/PlayerDataImportCommand.java @@ -1,6 +1,5 @@ package org.mvplugins.multiverse.inventories.commands; -import com.google.common.io.Files; import org.bukkit.World; import org.jvnet.hk2.annotations.Service; import org.mvplugins.multiverse.core.command.MVCommandIssuer; @@ -9,72 +8,18 @@ import org.mvplugins.multiverse.external.acf.commands.annotation.Description; import org.mvplugins.multiverse.external.acf.commands.annotation.Subcommand; import org.mvplugins.multiverse.external.acf.commands.annotation.Syntax; -import org.mvplugins.multiverse.external.jakarta.inject.Inject; -import org.mvplugins.multiverse.external.vavr.control.Try; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.data.ProfileData; -import org.mvplugins.multiverse.inventories.profile.key.ContainerType; -import org.mvplugins.multiverse.inventories.profile.key.GlobalProfileKey; -import org.mvplugins.multiverse.inventories.profile.key.ProfileKey; -import org.mvplugins.multiverse.inventories.profile.key.ProfileTypes; -import org.mvplugins.multiverse.inventories.profile.nbt.PlayerDataExtractor; - -import java.io.File; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; @Service final class PlayerDataImportCommand extends InventoriesCommand { - private final PlayerDataExtractor playerDataExtractor; - private final ProfileDataSource profileDataSource; - - @Inject - PlayerDataImportCommand(PlayerDataExtractor playerDataExtractor, ProfileDataSource profileDataSource) { - this.playerDataExtractor = playerDataExtractor; - this.profileDataSource = profileDataSource; - } - @Subcommand("playerdata import") @Syntax("") @CommandPermission("multiverse.inventories.importplayerdata") @CommandCompletion("@worldwithplayerdata") @Description("Import player data from the world's playerdata folder.") void onCommand(MVCommandIssuer issuer, World world) { - Path worldPath = world.getWorldFolder().toPath(); - File playerDataPath = worldPath.resolve("playerdata").toFile(); - if (!playerDataPath.isDirectory()) { - issuer.sendMessage("World's playerdata folder does not exist: " + world.getName()); - return; - } - - List> playerDataFutures = new ArrayList<>(); - File[] files = playerDataPath.listFiles(); - if (files == null) { - issuer.sendMessage("No player data files found in the world's playerdata folder: " + world.getName()); - return; - } - - for (File playerDataFile : files) { - if (!Files.getFileExtension(playerDataFile.getName()).equals("dat")) { - continue; - } - UUID playerUUID = UUID.fromString(Files.getNameWithoutExtension(playerDataFile.getName())); - playerDataExtractor.extract(playerDataFile.toPath()) - .onSuccess(profileData -> playerDataFutures.add(profileDataSource - .getGlobalProfile(GlobalProfileKey.of(playerUUID)) - .thenCompose(profileDataSource::updateGlobalProfile) - .thenCompose(ignore -> profileDataSource.getPlayerProfile( - ProfileKey.of(ContainerType.WORLD, world.getName(), ProfileTypes.getDefault(), playerUUID))) - .thenCompose(playerProfile -> { - playerProfile.update(profileData); - return profileDataSource.updatePlayerProfile(playerProfile); - }))); - } - CompletableFuture.allOf(playerDataFutures.toArray(new CompletableFuture[0])) - .thenRun(() -> issuer.sendMessage("Successfully imported all player data from " + world.getName() + ".")); + issuer.sendError("Please install Multiverse-InventoriesImporter plugin to use this command."); + issuer.sendInfo("Download Link: https://modrinth.com/project/multiverse-inventoriesimporter/"); + issuer.sendInfo("Learn More: https://mvplugins.org/inventories/how-to/import-playerdata/"); } } diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryConverter.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryConverter.java deleted file mode 100644 index 2cc77354..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryConverter.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import org.mvplugins.multiverse.inventories.util.MinecraftTools; -import org.bukkit.inventory.ItemStack; -import uk.co.tggl.pluckerpluck.multiinv.inventory.MIItemStack; - -/** - * Utility class for converting proprietary shit from MultiInv. - */ -final class MIInventoryConverter { - - /** - * @param oldContents Proprietary shiet from MultiInv. - * @return Standard ItemStacks. - */ - public static ItemStack[] convertMIItems(MIItemStack[] oldContents) { - ItemStack[] newContents = MinecraftTools.fillWithAir(new ItemStack[oldContents.length]); - for (int i = 0; i < oldContents.length; i++) { - if (oldContents[i] != null && oldContents[i].getItemStack() != null) { - newContents[i] = oldContents[i].getItemStack(); - } - } - return newContents; - } - - private MIInventoryConverter() { - } -} - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryInterface.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryInterface.java deleted file mode 100644 index 980e649b..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryInterface.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import org.bukkit.inventory.ItemStack; - -/** - * A little interface for retrieving normal ItemStack from the MultiInv inventory classes. - */ -sealed interface MIInventoryInterface permits MIInventoryWrapper, MIInventoryOldWrapper { - - /** - * @return The inventory contents. - */ - ItemStack[] getInventoryContents(); - - /** - * @return The armor contents. - */ - ItemStack[] getArmorContents(); -} - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryOldWrapper.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryOldWrapper.java deleted file mode 100644 index 8f5d90d1..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryOldWrapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import org.bukkit.inventory.ItemStack; -import uk.co.tggl.pluckerpluck.multiinv.inventory.MIInventoryOld; - -/** - * Wraps MIInventoryOld to provide a way of accessing the inventory/armor contents. - */ -final class MIInventoryOldWrapper extends MIInventoryOld implements MIInventoryInterface { - - public MIInventoryOldWrapper(String inventoryString) { - super(inventoryString); - } - - @Override - public ItemStack[] getInventoryContents() { - return MIInventoryConverter.convertMIItems(this.MIInventoryContents); - } - - @Override - public ItemStack[] getArmorContents() { - return MIInventoryConverter.convertMIItems(this.MIArmourContents); - } -} - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryWrapper.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryWrapper.java deleted file mode 100644 index b333eece..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIInventoryWrapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import org.bukkit.inventory.ItemStack; -import uk.co.tggl.pluckerpluck.multiinv.inventory.MIInventory; - -/** - * Wraps MIInventory to provide a way of accessing the inventory/armor contents. - */ -final class MIInventoryWrapper extends MIInventory implements MIInventoryInterface { - - public MIInventoryWrapper(String inventoryString) { - super(inventoryString); - } - - @Override - public ItemStack[] getInventoryContents() { - return MIInventoryConverter.convertMIItems(this.MIInventoryContents); - } - - @Override - public ItemStack[] getArmorContents() { - return MIInventoryConverter.convertMIItems(this.MIArmourContents); - } -} - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIPlayerFileLoader.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIPlayerFileLoader.java deleted file mode 100644 index 97dc42de..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MIPlayerFileLoader.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import org.mvplugins.multiverse.inventories.util.PlayerStats; -import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.file.YamlConfiguration; -import uk.co.tggl.pluckerpluck.multiinv.MultiInv; - -import java.io.File; - -/** - * A replacement for MultiInv's MIPlayerFile class so that it may accept an OfflinePlayer instead of Player. - */ -final class MIPlayerFileLoader { - - private final YamlConfiguration playerFile; - private final File file; - - public MIPlayerFileLoader(MultiInv plugin, OfflinePlayer player, String group) { - // Find and load configuration file for the player - File worldsFolder = new File(plugin.getDataFolder(), "Groups"); - file = new File(worldsFolder, group + File.separator + player.getName() + ".yml"); - - playerFile = new YamlConfiguration(); - } - - /** - * Loads the player file into memory. - * - * @return True if there was a file to load and it loaded successfully. - */ - public boolean load() { - if (file.exists()) { - try { - playerFile.load(file); - return true; - } catch (Exception ignore) { } - } - return false; - } - - /** - * Load particular inventory for specified player from specified group. - * - * @param inventoryName The gamemode for the inventory to load. - * @return An interface for retrieve the inventory/armor contents. - */ - public MIInventoryInterface getInventory(String inventoryName) { - // Get stored string from configuration file - MIInventoryInterface inventory; - String inventoryString = playerFile.getString(inventoryName, null); - // Check for old inventory save - if (inventoryString == null || inventoryString.contains(";-;")) { - inventory = new MIInventoryOldWrapper(inventoryString); - } else { - inventory = new MIInventoryWrapper(inventoryString); - } - return inventory; - } - - /** - * @return The player's health. - */ - public double getHealth() { - double health = playerFile.getDouble("health", PlayerStats.HEALTH); - if (health <= 0 || health > PlayerStats.HEALTH) { - health = PlayerStats.HEALTH; - } - return health; - } - - /** - * @return The player's hunger. - */ - public int getHunger() { - int hunger = playerFile.getInt("hunger", PlayerStats.FOOD_LEVEL); - if (hunger <= 0 || hunger > PlayerStats.FOOD_LEVEL) { - hunger = PlayerStats.FOOD_LEVEL; - } - return hunger; - } - - /** - * @return The player's saturation. - */ - public float getSaturation() { - double saturationDouble = playerFile.getDouble("saturation", 0); - float saturation = (float) saturationDouble; - return saturation; - } - - /** - * @return The player's total exp. - */ - public int getTotalExperience() { - return playerFile.getInt("experience", 0); - } - - /** - * @return The player's level. - */ - public int getLevel() { - return playerFile.getInt("level", 0); - } - - /** - * @return The player's exp. - */ - public float getExperience() { - double expDouble = playerFile.getDouble("exp", 0); - float exp = (float) expDouble; - return exp; - } -} - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImportHelper.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImportHelper.java deleted file mode 100644 index 9c4baf63..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImportHelper.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import com.dumptruckman.minecraft.util.Logging; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.OfflinePlayer; -import org.bukkit.World; -import org.jetbrains.annotations.NotNull; -import org.mvplugins.multiverse.inventories.config.InventoriesConfig; -import org.mvplugins.multiverse.inventories.dataimport.DataImportException; -import org.mvplugins.multiverse.inventories.profile.data.PlayerProfile; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.key.ProfileTypes; -import org.mvplugins.multiverse.inventories.profile.key.ContainerType; -import org.mvplugins.multiverse.inventories.profile.container.ProfileContainerStoreProvider; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroup; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager; -import org.mvplugins.multiverse.inventories.share.Sharables; -import uk.co.tggl.pluckerpluck.multiinv.MIYamlFiles; -import uk.co.tggl.pluckerpluck.multiinv.MultiInv; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -final class MultiInvImportHelper { - - @NotNull - private final MultiInv multiInv; - private final WorldGroupManager worldGroupManager; - private final InventoriesConfig inventoriesConfig; - private final ProfileContainerStoreProvider profileContainerStoreProvider; - private final ProfileDataSource profileDataSource; - - MultiInvImportHelper( - @NotNull MultiInv multiInv, - @NotNull WorldGroupManager worldGroupManager, - @NotNull InventoriesConfig inventoriesConfig, - @NotNull ProfileContainerStoreProvider profileContainerStoreProvider, - @NotNull ProfileDataSource profileDataSource) { - super(); - this.multiInv = multiInv; - this.worldGroupManager = worldGroupManager; - this.inventoriesConfig = inventoriesConfig; - this.profileContainerStoreProvider = profileContainerStoreProvider; - this.profileDataSource = profileDataSource; - } - - void importData() throws DataImportException { - HashMap miGroupMap = this.getGroupMap(); - if (miGroupMap == null) { - throw new DataImportException("There is no data to import from MultiInv!"); - } - if (!miGroupMap.isEmpty()) { - WorldGroup defaultWorldGroup = worldGroupManager.getDefaultGroup(); - if (defaultWorldGroup != null) { - worldGroupManager.removeGroup(defaultWorldGroup); - Logging.info("Removed automatically created world group in favor of imported groups."); - } - } - for (Map.Entry groupEntry : miGroupMap.entrySet()) { - WorldGroup worldGroup = worldGroupManager.getGroup(groupEntry.getValue()); - if (worldGroup == null) { - worldGroup = worldGroupManager.newEmptyGroup(groupEntry.getValue()); - worldGroup.getShares().mergeShares(Sharables.allOf()); - Logging.info("Importing group: " + groupEntry.getValue()); - worldGroupManager.updateGroup(worldGroup); - } - worldGroup.addWorld(groupEntry.getValue()); - } - inventoriesConfig.save(); - - for (OfflinePlayer player : Bukkit.getServer().getOfflinePlayers()) { - Logging.info("Processing MultiInv data for player: " + player.getName()); - for (Map.Entry entry : miGroupMap.entrySet()) { - String worldName = entry.getKey(); - String groupName = entry.getValue(); - MIPlayerFileLoader playerFileLoader = new MIPlayerFileLoader(multiInv, player, groupName); - if (!playerFileLoader.load()) { - continue; - } - Logging.info("Processing MultiInv data for player: " + player.getName() - + " for group: " + groupName); - mergeData(player, playerFileLoader, groupName, ContainerType.GROUP); - } - for (World world : Bukkit.getWorlds()) { - String worldName = world.getName(); - MIPlayerFileLoader playerFileLoader = new MIPlayerFileLoader(multiInv, player, worldName); - if (!playerFileLoader.load()) { - continue; - } - Logging.info("Processing MultiInv data for player: " + player.getName() - + " for world only: " + worldName); - mergeData(player, playerFileLoader, worldName, ContainerType.WORLD); - } - } - } - - private void mergeData(OfflinePlayer player, MIPlayerFileLoader playerFileLoader, - String dataName, ContainerType type) { - PlayerProfile playerProfile; - if (type.equals(ContainerType.GROUP)) { - WorldGroup group = worldGroupManager - .getGroup(dataName); - if (group == null) { - Logging.warning("Could not import player data for group: " + dataName); - return; - } - playerProfile = group.getGroupProfileContainer().getPlayerProfileNow(ProfileTypes.SURVIVAL, player); - } else { - playerProfile = profileContainerStoreProvider.getStore(type) - .getContainer(dataName).getPlayerProfileNow(ProfileTypes.SURVIVAL, player); - } - MIInventoryInterface inventoryInterface = - playerFileLoader.getInventory(GameMode.SURVIVAL.toString()); - playerProfile.set(Sharables.INVENTORY, inventoryInterface.getInventoryContents()); - playerProfile.set(Sharables.ARMOR, inventoryInterface.getArmorContents()); - playerProfile.set(Sharables.HEALTH, playerFileLoader.getHealth()); - playerProfile.set(Sharables.SATURATION, playerFileLoader.getSaturation()); - playerProfile.set(Sharables.EXPERIENCE, playerFileLoader.getExperience()); - playerProfile.set(Sharables.TOTAL_EXPERIENCE, playerFileLoader.getTotalExperience()); - playerProfile.set(Sharables.LEVEL, playerFileLoader.getLevel()); - playerProfile.set(Sharables.FOOD_LEVEL, playerFileLoader.getHunger()); - profileDataSource.updatePlayerProfile(playerProfile); - } - - /** - * @return The group mapping from MultiInv, where worldName -> groupName. - * @throws DataImportException If there was any issues getting the data through reflection. - */ - private HashMap getGroupMap() throws DataImportException { - Field field; - try { - field = MIYamlFiles.class.getDeclaredField("groups"); - } catch (NoSuchFieldException nsfe) { - throw new DataImportException("The running version of MultiInv is " - + "incompatible with the import feature.").setCauseException(nsfe); - } - field.setAccessible(true); - HashMap miGroupMap = null; - try { - miGroupMap = (HashMap) field.get(null); - } catch (IllegalAccessException | ClassCastException iae) { - throw new DataImportException("The running version of MultiInv is " - + "incompatible with the import feature.").setCauseException(iae); - } - return miGroupMap; - } -} diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImporter.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImporter.java deleted file mode 100644 index 3fd3b292..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/MultiInvImporter.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - -import org.jetbrains.annotations.NotNull; -import org.jvnet.hk2.annotations.Service; -import org.mvplugins.multiverse.external.jakarta.inject.Inject; -import org.mvplugins.multiverse.inventories.config.InventoriesConfig; -import org.mvplugins.multiverse.inventories.dataimport.AbstractDataImporter; -import org.mvplugins.multiverse.inventories.dataimport.DataImportException; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.container.ProfileContainerStoreProvider; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager; -import uk.co.tggl.pluckerpluck.multiinv.MultiInv; - -@Service -final class MultiInvImporter extends AbstractDataImporter { - - private final WorldGroupManager worldGroupManager; - private final InventoriesConfig inventoriesConfig; - private final ProfileContainerStoreProvider profileContainerStoreProvider; - private final ProfileDataSource profileDataSource; - - @Inject - MultiInvImporter( - @NotNull WorldGroupManager worldGroupManager, - @NotNull InventoriesConfig inventoriesConfig, - @NotNull ProfileContainerStoreProvider profileContainerStoreProvider, - @NotNull ProfileDataSource profileDataSource) { - super(); - this.worldGroupManager = worldGroupManager; - this.inventoriesConfig = inventoriesConfig; - this.profileContainerStoreProvider = profileContainerStoreProvider; - this.profileDataSource = profileDataSource; - } - - /** - * {@inheritDoc} - */ - @Override - protected void doDataImport() throws DataImportException { - new MultiInvImportHelper( - (MultiInv) importer, - worldGroupManager, - inventoriesConfig, - profileContainerStoreProvider, - profileDataSource - ).importData(); - } - /** - * {@inheritDoc} - */ - @Override - public @NotNull String getPluginName() { - return "MultiInv"; - } - - /** - * {@inheritDoc} - */ - @Override - public @NotNull Class getPluginClass() { - return MultiInv.class; - } -} diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/package-info.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/package-info.java deleted file mode 100644 index 46044732..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/multiinv/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * This package contains MultiInv classes to handle importing their data. - */ -package org.mvplugins.multiverse.inventories.dataimport.multiinv; - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PerWorldInventoryImporter.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PerWorldInventoryImporter.java deleted file mode 100644 index 54fb88f5..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PerWorldInventoryImporter.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.perworldinventory; - -import me.ebonjaeger.perworldinventory.PerWorldInventory; -import org.jetbrains.annotations.NotNull; -import org.jvnet.hk2.annotations.Service; -import org.mvplugins.multiverse.core.world.WorldManager; -import org.mvplugins.multiverse.external.jakarta.inject.Inject; -import org.mvplugins.multiverse.inventories.config.InventoriesConfig; -import org.mvplugins.multiverse.inventories.dataimport.AbstractDataImporter; -import org.mvplugins.multiverse.inventories.dataimport.DataImportException; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager; - -import java.util.Objects; - -@Service -final class PerWorldInventoryImporter extends AbstractDataImporter { - - private final InventoriesConfig inventoriesConfig; - private final WorldManager worldManager; - private final WorldGroupManager worldGroupManager; - private final ProfileDataSource profileDataSource; - - @Inject - PerWorldInventoryImporter( - @NotNull InventoriesConfig inventoriesConfig, - @NotNull WorldManager worldManager, - @NotNull WorldGroupManager worldGroupManager, - @NotNull ProfileDataSource profileDataSource) { - super(); - this.inventoriesConfig = inventoriesConfig; - this.worldManager = worldManager; - this.worldGroupManager = worldGroupManager; - this.profileDataSource = profileDataSource; - } - - /** - * {@inheritDoc} - */ - @Override - protected void doDataImport() throws DataImportException { - new PwiImportHelper( - Objects.requireNonNull(((PerWorldInventory) importer).getApi()), - inventoriesConfig, - worldManager, - worldGroupManager, - profileDataSource - ).importData(); - } - - /** - * {@inheritDoc} - */ - @Override - public @NotNull String getPluginName() { - return "PerWorldInventory"; - } - - /** - * {@inheritDoc} - */ - @Override - public @NotNull Class getPluginClass() { - return PerWorldInventory.class; - } -} diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PwiImportHelper.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PwiImportHelper.java deleted file mode 100644 index eaaf5ed5..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/PwiImportHelper.java +++ /dev/null @@ -1,356 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.perworldinventory; - -import com.dumptruckman.bukkit.configuration.util.SerializationHelper; -import com.dumptruckman.minecraft.util.Logging; -import me.ebonjaeger.perworldinventory.Group; -import me.ebonjaeger.perworldinventory.GroupManager; -import me.ebonjaeger.perworldinventory.api.PerWorldInventoryAPI; -import me.ebonjaeger.perworldinventory.configuration.PlayerSettings; -import me.ebonjaeger.perworldinventory.configuration.PluginSettings; -import me.ebonjaeger.perworldinventory.configuration.Settings; -import me.ebonjaeger.perworldinventory.data.FlatFile; -import me.ebonjaeger.perworldinventory.data.ProfileKey; -import me.ebonjaeger.perworldinventory.data.ProfileManager; -import me.ebonjaeger.perworldinventory.libs.json.JSONObject; -import me.ebonjaeger.perworldinventory.libs.json.parser.JSONParser; -import me.ebonjaeger.perworldinventory.serialization.PlayerSerializer; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.OfflinePlayer; -import org.bukkit.potion.PotionEffect; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.mvplugins.multiverse.core.utils.ReflectHelper; -import org.mvplugins.multiverse.core.world.WorldManager; -import org.mvplugins.multiverse.external.vavr.control.Try; -import org.mvplugins.multiverse.inventories.config.InventoriesConfig; -import org.mvplugins.multiverse.inventories.dataimport.DataImportException; -import org.mvplugins.multiverse.inventories.profile.GlobalProfile; -import org.mvplugins.multiverse.inventories.profile.data.PlayerProfile; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.key.GlobalProfileKey; -import org.mvplugins.multiverse.inventories.profile.key.ProfileTypes; -import org.mvplugins.multiverse.inventories.profile.key.ContainerType; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroup; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager; -import org.mvplugins.multiverse.inventories.share.Sharables; -import org.mvplugins.multiverse.inventories.util.FutureNow; -import org.mvplugins.multiverse.inventories.util.PlayerStats; - -import java.io.File; -import java.io.FileInputStream; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - -final class PwiImportHelper { - - private final PerWorldInventoryAPI pwiAPI; - private final InventoriesConfig inventoriesConfig; - private final WorldManager worldManager; - private final WorldGroupManager worldGroupManager; - private final ProfileDataSource profileDataSource; - - private Settings pwiSettings; - private GroupManager pwiGroupManager; - private FlatFile pwiFlatFile; - private File dataDirectory; - private Method getFileMethod; - private Method deserializeMethod; - - private List playerList; - - PwiImportHelper( - @NotNull PerWorldInventoryAPI pwiAPI, - @NotNull InventoriesConfig inventoriesConfig, - @NotNull WorldManager worldManager, - @NotNull WorldGroupManager worldGroupManager, - @NotNull ProfileDataSource profileDataSource) { - this.pwiAPI = pwiAPI; - this.inventoriesConfig = inventoriesConfig; - this.worldManager = worldManager; - this.worldGroupManager = worldGroupManager; - this.profileDataSource = profileDataSource; - } - - /** - * The 'Main' method for the import. - */ - void importData() throws DataImportException { - pwiSetUp(); - transferConfigOptions(); - findPlayersWithData(); - // Since there is no such thing as individual world container in PerWorldInventory, - // everything is just groups. No need for world playerData import. - for (Group group : getPWIGroups()) { - createMVGroup(group); - saveMVDataForGroup(group); - } - } - - /** - * Do the necessary reflection to get access to the classes needed for data import. - */ - private void pwiSetUp() { - this.pwiSettings = ReflectHelper.getFieldValue(pwiAPI, "settings", Settings.class); - this.pwiGroupManager = ReflectHelper.getFieldValue(this.pwiAPI, "groupManager", GroupManager.class); - ProfileManager pwiProfileManager = ReflectHelper.getFieldValue(this.pwiAPI, "profileManager", ProfileManager.class); - this.pwiFlatFile = ReflectHelper.getFieldValue(pwiProfileManager, "dataSource", FlatFile.class); - this.getFileMethod = ReflectHelper.getMethod(this.pwiFlatFile, "getFile", ProfileKey.class); - this.dataDirectory = ReflectHelper.getFieldValue(this.pwiFlatFile, "dataDirectory", File.class); - this.deserializeMethod = ReflectHelper.getMethod(SerializationHelper.class, "deserialize", Map.class, boolean.class); - } - - /** - * Set similar/supported config options in MultiverseInventories with the values used in PerWorldInventory. - */ - private void transferConfigOptions() { - inventoriesConfig.setEnableGamemodeShareHandling(this.pwiSettings.getProperty(PluginSettings.SEPARATE_GM_INVENTORIES)); - inventoriesConfig.setApplyPlayerdataOnJoin(this.pwiSettings.getProperty(PluginSettings.LOAD_DATA_ON_JOIN)); - inventoriesConfig.setDefaultUngroupedWorlds(this.pwiSettings.getProperty(PluginSettings.SHARE_IF_UNCONFIGURED)); - inventoriesConfig.getActiveOptionalShares().setSharing(Sharables.ECONOMY, this.pwiSettings.getProperty(PlayerSettings.USE_ECONOMY)); - inventoriesConfig.save(); - } - - private void findPlayersWithData() throws DataImportException { - if (dataDirectory == null) { - throw new DataImportException("PerWorldInventory data directory not found!"); - } - File[] playerFolders = dataDirectory.listFiles(); - if (playerFolders == null) { - throw new DataImportException("Unable to traverse PerWorldInventory data directory!"); - } - this.playerList = Arrays.stream(playerFolders) - .filter(File::isDirectory) - .map(file -> Try.of(() -> UUID.fromString(file.getName())) - .onFailure(throwable -> Logging.warning("Unable to convert %s to UUID: %s", - file.getName(), throwable.getMessage())) - .getOrNull()) - .filter(Objects::nonNull) - .map(Bukkit::getOfflinePlayer) - .toList(); - } - - /** - * Gets all PerWorldInventory groups based on all the worlds known by Multiverse. - * - * @return A collection of PerWorldInventory groups. - */ - private Collection getPWIGroups() { - Set groups = new HashSet<>(this.pwiGroupManager.getGroups().values()); - if (!inventoriesConfig.getDefaultUngroupedWorlds()) { - worldManager.getWorlds().forEach(world -> - groups.add(this.pwiGroupManager.getGroupFromWorld(world.getName()))); - } - return groups; - } - - /** - * Create a MultiverseInventories {@link WorldGroup} based on PerWorldInventory Group. - * - * @param group A PerWorldInventory Group. - */ - private void createMVGroup(Group group) { - Logging.finer("PerWorldInventory Group: %s", group); - WorldGroup worldGroup = worldGroupManager.getGroup(group.getName()); - if (worldGroup == null) { - worldGroup = worldGroupManager.newEmptyGroup(group.getName()); - } - - // In PerWorldInventory, shares can only be toggled to be enabled or disabled globally. - // So setting all shares here then transferring only those enabled later should work enough, - // since you can't actually disable shares in MultiverseInventories. - worldGroup.getShares().addAll(Sharables.allOf()); - worldGroup.addWorlds(group.getWorlds()); - if (group.getRespawnWorld() != null) { - worldGroup.setSpawnWorld(group.getRespawnWorld()); - } - worldGroupManager.updateGroup(worldGroup); - } - - /** - * Transfer all player data from PerWorldInventory to MultiverseInventories for a given group. - * - * @param group A PerWorldInventory Group. - */ - private void saveMVDataForGroup(Group group) throws DataImportException { - for (OfflinePlayer offlinePlayer : this.playerList) { - saveMVDataForPlayer(group, offlinePlayer); - } - } - - private void saveMVDataForPlayer(Group group, OfflinePlayer offlinePlayer) throws DataImportException { - GlobalProfile globalProfile = FutureNow.get(profileDataSource.getGlobalProfile(GlobalProfileKey.of(offlinePlayer))); - globalProfile.setLoadOnLogin(pwiSettings.getProperty(PluginSettings.LOAD_DATA_ON_JOIN)); - profileDataSource.updateGlobalProfile(globalProfile); - for (GameMode gameMode : GameMode.values()) { - me.ebonjaeger.perworldinventory.data.PlayerProfile pwiPlayerData = getPWIPlayerData(offlinePlayer, group, gameMode); - if (pwiPlayerData == null) { - continue; - } - for (var mvProfile : getMVPlayerData(offlinePlayer, group, gameMode)) { - transferToMVPlayerData(mvProfile, pwiPlayerData); - } - } - } - - /** - * Gets MultiverseInventories PlayerProfile based on PerWorldInventory ProfileKey. - * - * @param offlinePlayer OfflinePlayer to get data for. - * @param group Group to get data for. - * @param gameMode GameMode to get data for. - * @return A MultiverseInventories PLayerProfile. - */ - private List getMVPlayerData( - @NotNull OfflinePlayer offlinePlayer, @NotNull Group group, @NotNull GameMode gameMode) { - List profiles = new ArrayList<>(); - profiles.add(FutureNow.get(profileDataSource.getPlayerProfile(org.mvplugins.multiverse.inventories.profile.key.ProfileKey - .of(ContainerType.GROUP, group.getName(), ProfileTypes.forGameMode(gameMode), offlinePlayer.getUniqueId())))); - for (var worldName : group.getWorlds()) { - profiles.add(FutureNow.get(profileDataSource.getPlayerProfile(org.mvplugins.multiverse.inventories.profile.key.ProfileKey - .of(ContainerType.WORLD, worldName, ProfileTypes.forGameMode(gameMode), offlinePlayer.getUniqueId())))); - } - return profiles; - } - - /** - * Gets PerWorldInventory PlayerProfile based on PerWorldInventory ProfileKey. - * - * @param offlinePlayer OfflinePlayer to get data for. - * @param group Group to get data for. - * @param gameMode GameMode to get data for. - * @return A PerWorldInventory PLayerProfile. - */ - private @Nullable me.ebonjaeger.perworldinventory.data.PlayerProfile getPWIPlayerData( - @NotNull OfflinePlayer offlinePlayer, @NotNull Group group, @NotNull GameMode gameMode) throws DataImportException { - ProfileKey pwiKey = new ProfileKey(offlinePlayer.getUniqueId(), group, gameMode); - File pwiPlayerDataFile = getPWIFile(pwiKey); - if (!pwiPlayerDataFile.isFile()) { - Logging.finer("No data for %s.", pwiKey.toString()); - return null; - } - - me.ebonjaeger.perworldinventory.data.PlayerProfile pwiPlayerProfile; - try { - JSONParser parser = new JSONParser(JSONParser.USE_INTEGER_STORAGE); - JSONObject jsonObject = (JSONObject) parser.parse(new FileInputStream(pwiPlayerDataFile)); - if (jsonObject.containsKey("==")) { - pwiPlayerProfile = ReflectHelper.invokeMethod(null, deserializeMethod, jsonObject, true); - } else { - // Use legacy serialization that doesn't use ConfigurationSerializable - pwiPlayerProfile = PlayerSerializer.INSTANCE.deserialize( - jsonObject, - Objects.requireNonNull(offlinePlayer.getName()), - PlayerStats.INVENTORY_SIZE, - PlayerStats.ENDER_CHEST_SIZE); - } - } catch (Exception e) { - Logging.severe("Unable to parse file into profile: " + pwiPlayerDataFile.getAbsolutePath()); - e.printStackTrace(); - return null; - } - if (pwiPlayerProfile == null) { - Logging.warning("Empty serialization for %s.", pwiKey.toString()); - return null; - } - Logging.finer("Got pwiPlayerProfile for %s.", pwiKey.toString()); - return pwiPlayerProfile; - } - - /** - * Gets a PerWorldInventory data file based on it's ProfileKey. - * - * @param pwiKey PerWorldInventory profile key. - * @return A PerWorldInventory data file. - */ - private File getPWIFile(ProfileKey pwiKey) throws DataImportException { - return ReflectHelper.invokeMethod(this.pwiFlatFile, this.getFileMethod, pwiKey); - } - - /** - * Transfers supported player data from PerWorldInventory to MultiverseInventories. - * - * @param mvPlayerProfile MultiverseInventories PlayerProfile to transfer to. - * @param pwiPlayerProfile PerWorldInventory PlayerProfile to transfer from. - */ - private void transferToMVPlayerData( - PlayerProfile mvPlayerProfile, - me.ebonjaeger.perworldinventory.data.PlayerProfile pwiPlayerProfile - ) throws DataImportException { - if (pwiPlayerProfile == null || mvPlayerProfile == null) { - Logging.finer("Null profile(s). No data transferred for %s and %s.", mvPlayerProfile, pwiPlayerProfile); - return; - } - - // Move data from PerWorldInventory profile to MultiverseInventories profile - // Shares that are not available are commented out. - if (pwiSettings.getProperty(PlayerSettings.LOAD_INVENTORY)) { - mvPlayerProfile.set(Sharables.ARMOR, pwiPlayerProfile.getArmor()); - mvPlayerProfile.set(Sharables.INVENTORY, pwiPlayerProfile.getInventory()); - } - if (pwiSettings.getProperty(PlayerSettings.USE_ECONOMY)) { - mvPlayerProfile.set(Sharables.ECONOMY, pwiPlayerProfile.getBalance()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_ENDER_CHEST)) { - mvPlayerProfile.set(Sharables.ENDER_CHEST, pwiPlayerProfile.getEnderChest()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_EXHAUSTION)) { - mvPlayerProfile.set(Sharables.EXHAUSTION, pwiPlayerProfile.getExhaustion()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_EXP)) { - mvPlayerProfile.set(Sharables.EXPERIENCE, pwiPlayerProfile.getExperience()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_FALL_DISTANCE)) { - mvPlayerProfile.set(Sharables.FALL_DISTANCE, pwiPlayerProfile.getFallDistance()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_FIRE_TICKS)) { - mvPlayerProfile.set(Sharables.FIRE_TICKS, pwiPlayerProfile.getFireTicks()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_HUNGER)) { - mvPlayerProfile.set(Sharables.FOOD_LEVEL, pwiPlayerProfile.getFoodLevel()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_HUNGER)) { - mvPlayerProfile.set(Sharables.FOOD_LEVEL, pwiPlayerProfile.getFoodLevel()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_HEALTH)) { - mvPlayerProfile.set(Sharables.HEALTH, pwiPlayerProfile.getHealth()); - // mvPlayerProfile.set(Sharables, pwiPlayerProfile.getMaxHealth()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_LEVEL)) { - mvPlayerProfile.set(Sharables.LEVEL, pwiPlayerProfile.getLevel()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_MAX_AIR)) { - mvPlayerProfile.set(Sharables.MAXIMUM_AIR, pwiPlayerProfile.getMaximumAir()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_POTION_EFFECTS)) { - mvPlayerProfile.set(Sharables.POTIONS, pwiPlayerProfile.getPotionEffects().toArray(new PotionEffect[0])); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_REMAINING_AIR)) { - mvPlayerProfile.set(Sharables.REMAINING_AIR, pwiPlayerProfile.getRemainingAir()); - } - if (pwiSettings.getProperty(PlayerSettings.LOAD_SATURATION)) { - mvPlayerProfile.set(Sharables.REMAINING_AIR, pwiPlayerProfile.getRemainingAir()); - } - // if (pwiSettings.getProperty(PlayerSettings.LOAD_DISPLAY_NAME)) { - // mvPlayerProfile.set(Sharables, pwiPlayerProfile.getDisplayName()); - // } - // if (pwiSettings.getProperty(PlayerSettings.LOAD_FLYING)) { - // mvPlayerProfile.set(Sharables, pwiPlayerProfile.getAllowFlight()); - // } - // mvPlayerProfile.set(Sharables.BED_SPAWN, pwiPlayerProfile); - // mvPlayerProfile.set(Sharables.HUNGER, pwiPlayerProfile); - // mvPlayerProfile.set(Sharables.LAST_LOCATION, pwiPlayerProfile); - // mvPlayerProfile.set(Sharables.OFF_HAND, pwiPlayerProfile); - // mvPlayerProfile.set(Sharables.TOTAL_EXPERIENCE, pwiPlayerProfile); - - profileDataSource.updatePlayerProfile(mvPlayerProfile); - } -} diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/package-info.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/package-info.java deleted file mode 100644 index c8e7f714..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/perworldinventory/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.perworldinventory; \ No newline at end of file diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImportHelper.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImportHelper.java deleted file mode 100644 index 363fc9ca..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImportHelper.java +++ /dev/null @@ -1,264 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.worldinventories; - -import com.dumptruckman.minecraft.util.Logging; -import me.drayshak.WorldInventories.Group; -import me.drayshak.WorldInventories.WIPlayerInventory; -import me.drayshak.WorldInventories.WIPlayerStats; -import me.drayshak.WorldInventories.WorldInventories; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.World; -import org.jetbrains.annotations.NotNull; -import org.mvplugins.multiverse.inventories.config.InventoriesConfig; -import org.mvplugins.multiverse.inventories.dataimport.DataImportException; -import org.mvplugins.multiverse.inventories.profile.data.PlayerProfile; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.key.ProfileTypes; -import org.mvplugins.multiverse.inventories.profile.key.ContainerType; -import org.mvplugins.multiverse.inventories.profile.container.ProfileContainer; -import org.mvplugins.multiverse.inventories.profile.container.ProfileContainerStoreProvider; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroup; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager; -import org.mvplugins.multiverse.inventories.share.Sharables; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -final class WorldInventoriesImportHelper { - - @NotNull - private final WorldInventories worldInventories; - private final WorldGroupManager worldGroupManager; - private final InventoriesConfig inventoriesConfig; - private final ProfileContainerStoreProvider profileContainerStoreProvider; - private final ProfileDataSource profileDataSource; - - WorldInventoriesImportHelper( - @NotNull WorldInventories worldInventories, - @NotNull WorldGroupManager worldGroupManager, - @NotNull InventoriesConfig inventoriesConfig, - @NotNull ProfileContainerStoreProvider profileContainerStoreProvider, - @NotNull ProfileDataSource profileDataSource) { - super(); - this.worldInventories = worldInventories; - this.worldGroupManager = worldGroupManager; - this.inventoriesConfig = inventoriesConfig; - this.profileContainerStoreProvider = profileContainerStoreProvider; - this.profileDataSource = profileDataSource; - } - - void importData() throws DataImportException { - List wiGroups; - try { - wiGroups = worldInventories.getGroups(); - } catch (Exception e) { - throw new DataImportException("Unable to import from this version of WorldInventories!") - .setCauseException(e); - } catch (Error e) { - throw new DataImportException("Unable to import from this version of WorldInventories!"); - } - if (wiGroups == null) { - throw new DataImportException("No data to import from WorldInventories!"); - } - - if (!wiGroups.isEmpty()) { - WorldGroup defaultWorldGroup = worldGroupManager.getDefaultGroup(); - if (defaultWorldGroup != null) { - worldGroupManager.removeGroup(defaultWorldGroup); - Logging.info("Removed automatically created world group in favor of imported groups."); - } - } - - this.createGroups(wiGroups); - Set noGroupWorlds = this.getWorldsWithoutGroups(); - inventoriesConfig.save(); - - OfflinePlayer[] offlinePlayers = Bukkit.getServer().getOfflinePlayers(); - Logging.info("Processing data for " + offlinePlayers.length + " players. The larger than number, the longer" - + " this process will take. Please be patient. :) Your server will freeze for the duration."); - int playerCount = 0; - for (OfflinePlayer player : offlinePlayers) { - playerCount++; - Logging.finer("(" + playerCount + "/" + offlinePlayers.length - + ")Processing WorldInventories data for player: " + player.getName()); - for (Group wiGroup : wiGroups) { - WorldGroup worldGroup = worldGroupManager.getGroup(wiGroup.getName()); - if (worldGroup == null) { - Logging.finest("Could not import player data for WorldInventories group: " + wiGroup.getName() - + " because there is no Multiverse-Inventories group by that name."); - continue; - } - this.transferData(player, wiGroup, worldGroup.getGroupProfileContainer()); - } - for (ProfileContainer container : noGroupWorlds) { - this.transferData(player, null, container); - } - } - } - - private void createGroups(List wiGroups) { - for (Group wiGroup : wiGroups) { - if (wiGroup.getWorlds().isEmpty()) { - Logging.warning("Group '" + wiGroup.getName() + "' has no worlds." - + " You may need to add these manually!"); - } - WorldGroup newGroup = worldGroupManager.newEmptyGroup(wiGroup.getName()); - for (String worldName : wiGroup.getWorlds()) { - newGroup.addWorld(worldName); - } - - try { - if (WorldInventories.doStats) { - newGroup.getShares().mergeShares(Sharables.allOf()); - } else { - newGroup.getShares().setSharing(Sharables.ALL_INVENTORY, true); - } - } catch (Exception ignore) { - Logging.warning("Group '" + wiGroup.getName() + "' unable to import fully, sharing only inventory."); - newGroup.getShares().setSharing(Sharables.ALL_INVENTORY, true); - } catch (Error e) { - Logging.warning("Group '" + wiGroup.getName() + "' unable to import fully, sharing only inventory."); - newGroup.getShares().setSharing(Sharables.ALL_INVENTORY, true); - } - worldGroupManager.updateGroup(newGroup); - Logging.info("Created Multiverse-Inventories group: " + wiGroup.getName()); - } - } - - private Set getWorldsWithoutGroups() { - Set noGroupWorlds = new LinkedHashSet<>(); - for (World world : Bukkit.getWorlds()) { - if (worldGroupManager.getGroupsForWorld(world.getName()).isEmpty()) { - Logging.fine("Added ungrouped world for importing."); - ProfileContainer container = profileContainerStoreProvider.getStore(ContainerType.WORLD) - .getContainer(world.getName()); - noGroupWorlds.add(container); - } - } - return noGroupWorlds; - } - - private void transferData(OfflinePlayer player, Group wiGroup, ProfileContainer profileContainer) { - PlayerProfile playerProfile = profileContainer.getPlayerProfileNow(ProfileTypes.SURVIVAL, player); - WIPlayerInventory wiInventory = this.loadPlayerInventory(player, wiGroup); - WIPlayerStats wiStats = this.loadPlayerStats(player, wiGroup); - if (wiInventory != null) { - playerProfile.set(Sharables.INVENTORY, wiInventory.getItems()); - playerProfile.set(Sharables.ARMOR, wiInventory.getArmour()); - } - if (wiStats != null) { - playerProfile.set(Sharables.HEALTH, (double) wiStats.getHealth()); - playerProfile.set(Sharables.SATURATION, wiStats.getSaturation()); - playerProfile.set(Sharables.EXPERIENCE, wiStats.getExp()); - playerProfile.set(Sharables.LEVEL, wiStats.getLevel()); - playerProfile.set(Sharables.EXHAUSTION, wiStats.getExhaustion()); - playerProfile.set(Sharables.FOOD_LEVEL, wiStats.getFoodLevel()); - } - profileDataSource.updatePlayerProfile(playerProfile); - Logging.finest("Player's data imported successfully for group: " + profileContainer.getContainerName()); - } - - private File getFile(OfflinePlayer player, Group group, DataType dataType) { - StringBuilder path = new StringBuilder(); - path.append(File.separator); - - // Use default group - if (group == null) { - path.append("default"); - } else { - path.append(group.getName()); - } - path.insert(0, worldInventories.getDataFolder().getAbsolutePath()); - path.append(File.separator).append(player.getName()).append(dataType.fileExtension); - - File file = new File(path.toString()); - if (!file.exists()) { - file = null; - } - return file; - } - - // Copied and modified from WorldInventories - private WIPlayerInventory loadPlayerInventory(OfflinePlayer player, Group group) { - File file = this.getFile(player, group, DataType.INVENTORY); - if (file == null) { - return null; - } - WIPlayerInventory playerInventory = null; - FileInputStream fIS = null; - ObjectInputStream obIn = null; - try { - fIS = new FileInputStream(file); - obIn = new ObjectInputStream(fIS); - playerInventory = (WIPlayerInventory) obIn.readObject(); - } catch (Exception ignore) { - } finally { - if (obIn != null) { - try { - obIn.close(); - } catch (IOException ignore) { - } - } - if (fIS != null) { - try { - fIS.close(); - } catch (IOException ignore) { - } - } - } - - return playerInventory; - } - - // Copied and modified from WorldInventories - private WIPlayerStats loadPlayerStats(OfflinePlayer player, Group group) { - File file = this.getFile(player, group, DataType.STATS); - if (file == null) { - return null; - } - WIPlayerStats playerstats = null; - FileInputStream fIS = null; - ObjectInputStream obIn = null; - try { - fIS = new FileInputStream(file); - obIn = new ObjectInputStream(fIS); - playerstats = (WIPlayerStats) obIn.readObject(); - } catch (Exception ignore) { - } finally { - if (obIn != null) { - try { - obIn.close(); - } catch (IOException ignore) { - } - } - if (fIS != null) { - try { - fIS.close(); - } catch (IOException ignore) { - } - } - } - - return playerstats; - } - - - /** - * Indicates the type of data we're importing for. - */ - private enum DataType { - INVENTORY(".inventory"), - STATS(".stats"); - - private String fileExtension; - - DataType(String fileExtension) { - this.fileExtension = fileExtension; - } - } -} diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImporter.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImporter.java deleted file mode 100644 index 42ce3963..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/WorldInventoriesImporter.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.mvplugins.multiverse.inventories.dataimport.worldinventories; - -import me.drayshak.WorldInventories.WorldInventories; -import org.jetbrains.annotations.NotNull; -import org.jvnet.hk2.annotations.Service; -import org.mvplugins.multiverse.external.jakarta.inject.Inject; -import org.mvplugins.multiverse.inventories.config.InventoriesConfig; -import org.mvplugins.multiverse.inventories.dataimport.AbstractDataImporter; -import org.mvplugins.multiverse.inventories.dataimport.DataImportException; -import org.mvplugins.multiverse.inventories.profile.ProfileDataSource; -import org.mvplugins.multiverse.inventories.profile.container.ProfileContainerStoreProvider; -import org.mvplugins.multiverse.inventories.profile.group.WorldGroupManager; - -@Service -final class WorldInventoriesImporter extends AbstractDataImporter { - - private final WorldGroupManager worldGroupManager; - private final InventoriesConfig inventoriesConfig; - private final ProfileContainerStoreProvider profileContainerStoreProvider; - private final ProfileDataSource profileDataSource; - - @Inject - WorldInventoriesImporter( - @NotNull WorldGroupManager worldGroupManager, - @NotNull InventoriesConfig inventoriesConfig, - @NotNull ProfileContainerStoreProvider profileContainerStoreProvider, - @NotNull ProfileDataSource profileDataSource) { - super(); - this.worldGroupManager = worldGroupManager; - this.inventoriesConfig = inventoriesConfig; - this.profileContainerStoreProvider = profileContainerStoreProvider; - this.profileDataSource = profileDataSource; - } - - /** - * {@inheritDoc} - */ - @Override - protected void doDataImport() throws DataImportException { - new WorldInventoriesImportHelper( - (WorldInventories) importer, - worldGroupManager, - inventoriesConfig, - profileContainerStoreProvider, - profileDataSource - ).importData(); - } - - /** - * {@inheritDoc} - */ - @Override - public @NotNull String getPluginName() { - return "WorldInventories"; - } - - /** - * {@inheritDoc} - */ - @Override - public @NotNull Class getPluginClass() { - return WorldInventories.class; - } -} diff --git a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/package-info.java b/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/package-info.java deleted file mode 100644 index adae4de0..00000000 --- a/src/main/java/org/mvplugins/multiverse/inventories/dataimport/worldinventories/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * This package contains WorldInventories classes to handle importing their data. - */ -package org.mvplugins.multiverse.inventories.dataimport.worldinventories; - diff --git a/src/main/java/org/mvplugins/multiverse/inventories/profile/nbt/PlayerDataExtractor.java b/src/main/java/org/mvplugins/multiverse/inventories/profile/nbt/PlayerDataExtractor.java index 425bbd2a..d35dabd4 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/profile/nbt/PlayerDataExtractor.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/profile/nbt/PlayerDataExtractor.java @@ -19,6 +19,11 @@ import java.nio.file.Path; import java.util.zip.GZIPOutputStream; +/** + * @deprecated This feature has been moved to Multiverse-InventoriesImporter plugin. This class's code logic is outdated + * and does not work on some Minecraft versions, hence should not be used. + */ +@Deprecated(since = "5.3", forRemoval = true) @ApiStatus.AvailableSince("5.2") @Service public final class PlayerDataExtractor { diff --git a/src/main/resources/multiverse-inventories_en.properties b/src/main/resources/multiverse-inventories_en.properties index dcf0af74..8ae14ab5 100644 --- a/src/main/resources/multiverse-inventories_en.properties +++ b/src/main/resources/multiverse-inventories_en.properties @@ -94,7 +94,7 @@ mv-inventories.group.invalidoption=&cThat is not a valid option! Type &f##&c to # Migrate command mv-inventories.migrate.pluginnotenabled=&f{plugin} &6is not enabled so you may not import data from it! -mv-inventories.migrate.unsupportedplugin=&6Sorry, ''&f{plugin}&6'' is not supported for importing. +mv-inventories.migrate.unsupportedplugin=&6Sorry, the plugin '&f{plugin}&6' is not supported for importing. mv-inventories.migrate.confirmprompt=&6Are you sure you want to import data from &f{plugin}&6? This will override existing Multiverse-Inventories playerdata!!! mv-inventories.migrate.success=&2Successfully imported data from &f{plugin}! mv-inventories.migrate.failed=Failed to import data from &f{plugin}! From 37613f2127c003ce191e4349a4e2b82ef3705783 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:29:40 +0800 Subject: [PATCH 2/7] Remove a weird comment --- .../inventories/util/ItemStackConverter.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/inventories/util/ItemStackConverter.java b/src/main/java/org/mvplugins/multiverse/inventories/util/ItemStackConverter.java index afc4c4d7..666b15a5 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/util/ItemStackConverter.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/util/ItemStackConverter.java @@ -31,17 +31,6 @@ public static boolean isEmptyItemStack(@Nullable ItemStack itemStack) { return itemStack == null || itemStack.getType() == Material.AIR || itemStack.getAmount() == 0; } -// /** -// * Format: `material[custom properties] amount` -// * Example: iron_sword[attribute_modifiers=[{type:"generic.attack_damage",id:"op_damage",amount:10000,operation:"add_value",slot:"mainhand"}]] 1 -// * -// * @return -// */ -// @Nullable -// public static ItemStack fromString(String item) { -// -// } - @Nullable public static ItemStack deserialize(Object obj) { if (obj instanceof ItemStack itemStack) { From 8ec96dc6e42783b7735dd4999f4624b84bf53668 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:33:07 +0800 Subject: [PATCH 3/7] Bump core api target to v5.3 --- build.gradle | 2 +- .../mvplugins/multiverse/inventories/MultiverseInventories.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 193dec0c..9bbed077 100644 --- a/build.gradle +++ b/build.gradle @@ -36,7 +36,7 @@ configure(apiDependencies) { dependencies { // Core - externalPlugin 'org.mvplugins.multiverse.core:multiverse-core:5.2.0' + externalPlugin 'org.mvplugins.multiverse.core:multiverse-core:5.3.0' // Config shadowed 'com.dumptruckman.minecraft:JsonConfiguration:1.2-SNAPSHOT' diff --git a/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java b/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java index 38631539..fd40eb61 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/MultiverseInventories.java @@ -44,7 +44,7 @@ @Service public class MultiverseInventories extends MultiverseModule { - private static final double TARGET_CORE_API_VERSION = 5.2; + private static final double TARGET_CORE_API_VERSION = 5.3; @Inject private Provider coreConfig; From 8a448503e4b67d91bc6c22706ba4b2d09a608fc9 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:42:50 +0800 Subject: [PATCH 4/7] Remove unused `use-improved-respawn-location-detection` config option --- .../multiverse/inventories/config/InventoriesConfig.java | 6 ++++-- .../inventories/config/InventoriesConfigNodes.java | 8 -------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfig.java b/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfig.java index 14d549ae..cbade8f1 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfig.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfig.java @@ -144,12 +144,14 @@ public Try setActiveOptionalShares(Shares shares) { return this.configHandle.set(configNodes.activeOptionalShares, shares); } + @Deprecated(since = "5.3", forRemoval = true) public boolean getUseImprovedRespawnLocationDetection() { - return this.configHandle.get(configNodes.useImprovedRespawnLocationDetection); + return true; } + @Deprecated(since = "5.3", forRemoval = true) public Try setUseImprovedRespawnLocationDetection(boolean useImprovedRespawnLocationDetection) { - return this.configHandle.set(configNodes.useImprovedRespawnLocationDetection, useImprovedRespawnLocationDetection); + return Try.failure(new IllegalStateException("this config option has been removed")); } @ApiStatus.AvailableSince("5.2") diff --git a/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfigNodes.java b/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfigNodes.java index 62a50f41..368fd4fd 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfigNodes.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/config/InventoriesConfigNodes.java @@ -113,15 +113,7 @@ public Object serialize(Shares sharables, Class aClass) { .comment("") .build()); - final ConfigNode useImprovedRespawnLocationDetection = node(ConfigNode.builder("sharables.use-improved-respawn-location-detection", Boolean.class) - .comment("When enabled, we will use 1.21's PlayerSpawnChangeEvent to better detect bed and anchor respawn locations.") - .comment("This options is not applicable for older minecraft server versions.") - .defaultValue(true) - .name("use-improved-respawn-location-detection") - .build()); - final ConfigNode validateBedAnchorRespawnLocation = node(ConfigNode.builder("sharables.validate-bed-anchor-respawn-location", Boolean.class) - .comment("") .comment("When enabled, we will validate the bed/anchor respawn location on group/world change.") .comment("The validation checks if the bed/anchor block still exists at the saved location and is usable.") .comment("When the validation fails, the respawn location will be cleared and default world spawn will be used instead.") From eba89bf3aeb7d838a534e24b5ab1ff4ef08ee8a8 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:48:45 +0800 Subject: [PATCH 5/7] Fix config test --- src/test/resources/config/fresh_config.yml | 1 - src/test/resources/config/migrated_config.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/src/test/resources/config/fresh_config.yml b/src/test/resources/config/fresh_config.yml index f4f4fc5c..8a0177b4 100644 --- a/src/test/resources/config/fresh_config.yml +++ b/src/test/resources/config/fresh_config.yml @@ -6,7 +6,6 @@ share-handling: active-optional-shares: [] sharables: - use-improved-respawn-location-detection: true validate-bed-anchor-respawn-location: true reset-last-location-on-death: false apply-last-location-for-all-teleports: true diff --git a/src/test/resources/config/migrated_config.yml b/src/test/resources/config/migrated_config.yml index ed14049b..819d805f 100644 --- a/src/test/resources/config/migrated_config.yml +++ b/src/test/resources/config/migrated_config.yml @@ -7,7 +7,6 @@ share-handling: - last_location sharables: - use-improved-respawn-location-detection: true validate-bed-anchor-respawn-location: true reset-last-location-on-death: false apply-last-location-for-all-teleports: true From 4df570bdb0c23ce6e6572717ab0b3cbf192cfa15 Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Thu, 4 Dec 2025 00:00:33 +0800 Subject: [PATCH 6/7] Add tip for last location configuration wiki link --- .../multiverse/inventories/commands/ToggleCommand.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/mvplugins/multiverse/inventories/commands/ToggleCommand.java b/src/main/java/org/mvplugins/multiverse/inventories/commands/ToggleCommand.java index a6e93e9e..9519550c 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/commands/ToggleCommand.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/commands/ToggleCommand.java @@ -4,6 +4,7 @@ import org.mvplugins.multiverse.core.command.MVCommandIssuer; import org.mvplugins.multiverse.inventories.config.InventoriesConfig; import org.mvplugins.multiverse.inventories.share.Sharable; +import org.mvplugins.multiverse.inventories.share.Sharables; import org.mvplugins.multiverse.inventories.share.Shares; import org.mvplugins.multiverse.core.command.MVCommandManager; import org.mvplugins.multiverse.external.acf.commands.annotation.CommandAlias; @@ -54,6 +55,13 @@ void onToggleCommand( } else { optionalShares.add(sharable); issuer.sendInfo(MVInvi18n.TOGGLE_NOWUSINGOPTIONAL, replace("{share}").with(sharable.getNames()[0])); + + // special tip to our wiki page, hopefully this reduces the number of people asking the + // same old questions about last location config options on discord. + if (sharable == Sharables.LAST_LOCATION) { + issuer.sendInfo("For more information on configuring last location, please see: " + + "https://mvplugins.org/inventories/how-to/configure-last-location/"); + } } inventoriesConfig.setActiveOptionalShares(optionalShares); inventoriesConfig.save(); From 39e44c9fb5f25cb4e7680aed85f90100d90e381c Mon Sep 17 00:00:00 2001 From: Ben Woo <30431861+benwoo1110@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:24:56 +0800 Subject: [PATCH 7/7] Refactor RespawnLocation to extend UnloadedWorldLocation to reduce duplicate code --- .../inventories/util/RespawnLocation.java | 111 ++---------------- 1 file changed, 13 insertions(+), 98 deletions(-) diff --git a/src/main/java/org/mvplugins/multiverse/inventories/util/RespawnLocation.java b/src/main/java/org/mvplugins/multiverse/inventories/util/RespawnLocation.java index a4670065..d180ca68 100644 --- a/src/main/java/org/mvplugins/multiverse/inventories/util/RespawnLocation.java +++ b/src/main/java/org/mvplugins/multiverse/inventories/util/RespawnLocation.java @@ -1,6 +1,5 @@ package org.mvplugins.multiverse.inventories.util; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Utility; @@ -12,46 +11,38 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.mvplugins.multiverse.core.world.location.UnloadedWorldLocation; import org.mvplugins.multiverse.external.vavr.control.Try; -import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.Objects; /** * Location information with respawn type. See also {@link RespawnLocationType}. - *
- * TODO: This should extend UnloadedWorldLocation, but that class is currently a final class!!! */ @SerializableAs("RespawnLocation") @ApiStatus.AvailableSince("5.2") -public class RespawnLocation extends Location { +public class RespawnLocation extends UnloadedWorldLocation { - private @Nullable String worldName; - private @NotNull RespawnLocationType respawnType = RespawnLocationType.UNKNOWN; + private @NotNull RespawnLocationType respawnType; public RespawnLocation(@Nullable String worldName, double x, double y, double z, @NotNull RespawnLocationType respawnType) { - super(null, x, y, z); - setWorldName(worldName); + super(worldName, x, y, z); this.respawnType = respawnType; } public RespawnLocation(@Nullable String worldName, double x, double y, double z, float yaw, float pitch, @NotNull RespawnLocationType respawnType) { - super(null, x, y, z, yaw, pitch); - setWorldName(worldName); + super(worldName, x, y, z, yaw, pitch); this.respawnType = respawnType; } public RespawnLocation(@Nullable World world, double x, double y, double z, @NotNull RespawnLocationType respawnType) { - super(null, x, y, z); - setWorldName(world == null ? null : world.getName()); + super(world, x, y, z); this.respawnType = respawnType; } public RespawnLocation(@Nullable World world, double x, double y, double z, float yaw, float pitch, @NotNull RespawnLocationType respawnType) { - super(null, x, y, z, yaw, pitch); - setWorldName(world == null ? null : world.getName()); + super(world, x, y, z, yaw, pitch); this.respawnType = respawnType; } @@ -59,55 +50,12 @@ public RespawnLocation(@NotNull Location location, @NotNull RespawnLocationType this(location.getWorld(), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch(), respawnType); } - /** - * Makes a bukkit {@link Location} copy from this SpawnLocation. - * - * @return The bukkit location - */ - public Location toBukkitLocation() { - return new Location(getWorld(), getX(), getY(), getZ(), getYaw(), getPitch()); - } - - public void setWorldName(@Nullable String worldName) { - this.worldName = worldName; - } - - public @Nullable String getWorldName() { - return worldName; - } - - @Override - public void setWorld(@Nullable World world) { - this.worldName = (world == null) ? null : world.getName(); - } - - @Override - public @Nullable World getWorld() { - if (worldName == null) { - return null; - } - return Bukkit.getWorld(worldName); - } - @Override @Utility @NotNull public Map serialize() { - Map data = new HashMap<>(); - - if (this.worldName != null) { - data.put("world", this.worldName); - } - - data.put("x", getX()); - data.put("y", getY()); - data.put("z", getZ()); - - data.put("yaw", getYaw()); - data.put("pitch", getPitch()); - + Map data = super.serialize(); data.put("respawnType", this.respawnType.name()); - return data; } @@ -138,58 +86,25 @@ public static Location deserialize(@NotNull Map args) { @Override public boolean equals(Object obj) { - if (obj == null) { - return false; - } if (!(obj instanceof Location other)) { return false; } - String otherWorldName = Try.of(() -> other instanceof RespawnLocation RespawnLocation - ? RespawnLocation.worldName - : other.getWorld().getName()) - .getOrNull(); - if (!Objects.equals(this.worldName, otherWorldName)) { - return false; - } - if (Double.doubleToLongBits(this.getX()) != Double.doubleToLongBits(other.getX())) { - return false; - } - if (Double.doubleToLongBits(this.getY()) != Double.doubleToLongBits(other.getY())) { - return false; - } - if (Double.doubleToLongBits(this.getZ()) != Double.doubleToLongBits(other.getZ())) { - return false; - } - if (Float.floatToIntBits(this.getPitch()) != Float.floatToIntBits(other.getPitch())) { - return false; - } - if (Float.floatToIntBits(this.getYaw()) != Float.floatToIntBits(other.getYaw())) { - return false; - } - if (other instanceof RespawnLocation otherRespawnLocation - && this.respawnType != otherRespawnLocation.respawnType) { + if (!super.equals(obj)) { return false; } - return true; + return !(other instanceof RespawnLocation otherRespawnLocation) + || this.respawnType == otherRespawnLocation.respawnType; } @Override public int hashCode() { - int hash = 3; - hash = 19 * hash + String.valueOf(worldName).hashCode(); - hash = 19 * hash + Long.hashCode(Double.doubleToLongBits(this.getX())); - hash = 19 * hash + Long.hashCode(Double.doubleToLongBits(this.getY())); - hash = 19 * hash + Long.hashCode(Double.doubleToLongBits(this.getZ())); - hash = 19 * hash + Float.floatToIntBits(this.getPitch()); - hash = 19 * hash + Float.floatToIntBits(this.getYaw()); - hash = 19 * hash + this.respawnType.hashCode(); - return hash; + return 19 * super.hashCode() + this.respawnType.hashCode(); } @Override public String toString() { return "RespawnLocation{" + - "world=" + worldName + + "world=" + getWorldName() + ",x=" + getX() + ",y=" + getY() + ",z=" + getZ() +