diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d91b5d639..eebb6766f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,10 +10,10 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 - uses: gradle/wrapper-validation-action@v3 - name: Set up JDK 17 - uses: actions/setup-java@v4.4.0 + uses: actions/setup-java@v4.6.0 with: distribution: temurin java-version: 17 @@ -25,7 +25,7 @@ jobs: - name: Build with Gradle run: ./gradlew build - name: Upload artifacts - uses: "actions/upload-artifact@v4.4.1" + uses: "actions/upload-artifact@v4.5.0" with: name: "IridiumSkyblock" path: "build/libs/IridiumSkyblock-*.jar" diff --git a/build.gradle.kts b/build.gradle.kts index bd2311163..118c08770 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ plugins { java `maven-publish` - id("com.github.johnrengelman.shadow") version "8.1.1" + id("io.github.goooler.shadow") version "8.1.8" id("net.minecrell.plugin-yml.bukkit") version "0.6.0" } @@ -22,21 +22,21 @@ repositories { dependencies { // Dependencies that we want to shade in - implementation("org.jetbrains:annotations:25.0.0") + implementation("org.jetbrains:annotations:26.0.1") implementation("com.j256.ormlite:ormlite-core:6.1") implementation("com.j256.ormlite:ormlite-jdbc:6.1") - implementation("com.iridium:IridiumTeams:2.5.9") + implementation("com.iridium:IridiumTeams:2.5.9.8") implementation("commons-lang:commons-lang:2.6") // Other dependencies that are not required or already available at runtime - compileOnly("org.projectlombok:lombok:1.18.34") - compileOnly("org.spigotmc:spigot-api:1.21.1-R0.1-SNAPSHOT") + compileOnly("org.projectlombok:lombok:1.18.36") + compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") compileOnly("net.ess3:EssentialsXSpawn:2.16.1") compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.13-SNAPSHOT") // Enable lombok annotation processing - annotationProcessor("org.projectlombok:lombok:1.18.34") + annotationProcessor("org.projectlombok:lombok:1.18.36") } bukkit { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72b8..cea7a793a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6d6..f3b75f3b0 100755 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/src/main/java/com/iridium/iridiumskyblock/commands/ClearDataCommand.java b/src/main/java/com/iridium/iridiumskyblock/commands/ClearDataCommand.java new file mode 100644 index 000000000..a5d275293 --- /dev/null +++ b/src/main/java/com/iridium/iridiumskyblock/commands/ClearDataCommand.java @@ -0,0 +1,276 @@ +package com.iridium.iridiumskyblock.commands; + +import com.iridium.iridiumcore.utils.StringUtils; +import com.iridium.iridiumskyblock.IridiumSkyblock; +import com.iridium.iridiumskyblock.database.Island; +import com.iridium.iridiumskyblock.database.User; +import com.iridium.iridiumskyblock.managers.DatabaseManager; +import com.iridium.iridiumskyblock.managers.tablemanagers.*; +import com.iridium.iridiumteams.IridiumTeams; +import com.iridium.iridiumteams.commands.Command; +import com.iridium.iridiumteams.database.*; +import com.iridium.iridiumteams.gui.ConfirmationGUI; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +public class ClearDataCommand extends Command < Island, User > { + + public ClearDataCommand() { + super(Collections.singletonList("cleardata"), "Deletes data from database", "%prefix% &7/is cleardata --skip-confirm", "iridiumSkyblock.clearData", 10); + } + + @Override + public boolean execute(CommandSender sender, String[] args, IridiumTeams < Island, User > iridiumTeams) { + DataTable table = DataTable.ALL; + boolean skipConfirmation = false; + Optional < Island > island = Optional.empty(); + + if (args.length == 0 || Arrays.stream(DataTable.values()).noneMatch(dataTable -> dataTable.name().equalsIgnoreCase(args[0]))) { + sender.sendMessage(StringUtils.color(syntax.replace("%prefix%", IridiumSkyblock.getInstance().getConfiguration().prefix))); + return false; + } + + switch (args.length) { + case 2: { + if (!args[1].equalsIgnoreCase("--skip-confirm")) { + island = IridiumSkyblock.getInstance().getIslandManager().getTeamViaNameOrPlayer(args[1]); + if (!island.isPresent()) { + sender.sendMessage(StringUtils.color(IridiumSkyblock.getInstance().getMessages().teamDoesntExistByName + .replace("%prefix%", IridiumSkyblock.getInstance().getConfiguration().prefix))); + return false; + } + } + } + case 1: { + try { + if (Arrays.stream(DataTable.values()).anyMatch(dataTable -> dataTable.name().equalsIgnoreCase(args[0]))) + table = DataTable.valueOf(args[0]); + } catch (IllegalArgumentException e) { + IridiumSkyblock.getInstance().getLogger().warning(e.getMessage()); + return false; + } + } + } + + if (Arrays.stream(args).anyMatch(argument -> argument.equalsIgnoreCase("--skip-confirm"))) + skipConfirmation = true; + + if (sender instanceof Player && !skipConfirmation) { + confirmDataDeletion((Player) sender, island, table); + return true; + } + deleteData(sender, island, table); + + return true; + } + + private void confirmDataDeletion(Player player, Optional < Island > island, DataTable table) { + String islandName = "ALL"; + if (island.isPresent()) islandName = island.get().getName() + " (" + island.get().getOwner().get().getName() + ")"; + player.sendMessage(StringUtils.color(IridiumSkyblock.getInstance().getMessages().confirmDataDeletion + .replace("%prefix%", IridiumSkyblock.getInstance().getConfiguration().prefix) + .replace("%table%", table.name()) + .replace("%island%", islandName))); + + player.openInventory(new ConfirmationGUI < > (() -> deleteData(player, island, table), IridiumSkyblock.getInstance()).getInventory()); + } + + private CompletableFuture < Void > deleteData(CommandSender sender, Optional < Island > island, DataTable table) { + return CompletableFuture.runAsync(() -> { + + if (!backupDatabaseFile()) return; + + List < Island > islands = new ArrayList < > (); + if (!island.isPresent()) { + islands = IridiumSkyblock.getInstance().getIslandManager().getTeams(); + } else islands.add(island.get()); + + boolean all = table == DataTable.ALL; + + DatabaseManager databaseManager = IridiumSkyblock.getInstance().getDatabaseManager(); + + try { + switch (table) { + case ALL: + case ISLAND: { + databaseManager.getIslandTableManager().delete(islands).join(); + if (!all) break; + } + case INVITE: { + ForeignIslandTableManager < String, TeamInvite > inviteTableManager = databaseManager.getInvitesTableManager(); + for (Island islandEntry: islands) { + for (TeamInvite teamInvite: inviteTableManager.getEntries(islandEntry)) { + inviteTableManager.delete(teamInvite).join(); + } + } + if (!all) break; + } + case TRUST: { + ForeignIslandTableManager < String, TeamTrust > trustTableManager = databaseManager.getTrustTableManager(); + for (Island islandEntry: islands) { + for (TeamTrust teamTrust: trustTableManager.getEntries(islandEntry)) { + trustTableManager.delete(teamTrust).join(); + } + } + if (!all) break; + } + case PERMISSION: { + ForeignIslandTableManager < String, TeamPermission > permissionTableManager = databaseManager.getPermissionsTableManager(); + for (Island islandEntry: islands) { + for (TeamPermission teamPermission: permissionTableManager.getEntries(islandEntry)) { + permissionTableManager.delete(teamPermission).join(); + } + } + if (!all) break; + } + case BANK: { + ForeignIslandTableManager < String, TeamBank > bankTableManager = databaseManager.getBankTableManager(); + for (Island islandEntry: islands) { + for (TeamBank teamBank: bankTableManager.getEntries(islandEntry)) { + bankTableManager.delete(teamBank).join(); + } + } + if (!all) break; + } + case ENHANCEMENT: { + ForeignIslandTableManager < String, TeamEnhancement > enhancementTableManager = databaseManager.getEnhancementTableManager(); + for (Island islandEntry: islands) { + for (TeamEnhancement teamEnhancement: enhancementTableManager.getEntries(islandEntry)) { + enhancementTableManager.delete(teamEnhancement).join(); + } + } + if (!all) break; + } + case TEAM_BLOCK: { + ForeignIslandTableManager < String, TeamBlock > blockTableManager = databaseManager.getTeamBlockTableManager(); + for (Island islandEntry: islands) { + for (TeamBlock teamBlock: blockTableManager.getEntries(islandEntry)) { + blockTableManager.delete(teamBlock).join(); + } + } + if (!all) break; + } + case TEAM_SPAWNER: { + ForeignIslandTableManager < String, TeamSpawners > spawnerTableManager = databaseManager.getTeamSpawnerTableManager(); + for (Island islandEntry: islands) { + for (TeamSpawners teamSpawners: spawnerTableManager.getEntries(islandEntry)) { + spawnerTableManager.delete(teamSpawners).join(); + } + } + if (!all) break; + } + case TEAM_WARP: { + ForeignIslandTableManager < String, TeamWarp > warpTableManager = databaseManager.getTeamWarpTableManager(); + for (Island islandEntry: islands) { + for (TeamWarp teamWarp: warpTableManager.getEntries(islandEntry)) { + warpTableManager.delete(teamWarp).join(); + } + } + if (!all) break; + } + case TEAM_MISSION: { + ForeignIslandTableManager < String, TeamMission > missionTableManager = databaseManager.getTeamMissionTableManager(); + for (Island islandEntry: islands) { + for (TeamMission teamMission: missionTableManager.getEntries(islandEntry)) { + IridiumSkyblock.getInstance().getIslandManager().deleteTeamMission(teamMission); + IridiumSkyblock.getInstance().getIslandManager().deleteTeamMissionData(teamMission); + } + } + if (!all) break; + } + + case TEAM_REWARDS: { + ForeignIslandTableManager < String, TeamReward > rewardTableManager = databaseManager.getTeamRewardsTableManager(); + for (Island islandEntry: islands) { + for (TeamReward teamReward: rewardTableManager.getEntries(islandEntry)) { + rewardTableManager.delete(teamReward).join(); + } + } + if (!all) break; + } + case TEAM_SETTINGS: { + ForeignIslandTableManager < String, TeamSetting > settingTableManager = databaseManager.getTeamSettingsTableManager(); + for (Island islandEntry: islands) { + for (TeamSetting teamSetting: settingTableManager.getEntries(islandEntry)) { + settingTableManager.delete(teamSetting).join(); + } + } + } + } + } catch (Exception e) { + IridiumSkyblock.getInstance().getLogger().warning(e.getMessage()); + return; + } + + sender.sendMessage(StringUtils.color(IridiumSkyblock.getInstance().getMessages().dataDeletion + .replace("%prefix%", IridiumSkyblock.getInstance().getConfiguration().prefix))); + }); + } + + private boolean backupDatabaseFile() { + IridiumSkyblock.getInstance().getLogger().info("Creating a backup for IridiumSkyblock.db in \"backups\" folder..."); + + File pluginFolder = new File(IridiumSkyblock.getInstance().getDataFolder().getPath()); + File file = new File(pluginFolder + File.separator + "IridiumSkyblock.db"); + File backupFolder = new File(pluginFolder.getPath() + File.separator + "backups"); + File backupDatabaseFile = new File(backupFolder + File.separator + file.getName()); + + try { + if (!backupFolder.exists()) backupFolder.mkdir(); + Files.copy(file.toPath(), backupDatabaseFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + IridiumSkyblock.getInstance().getLogger().info("Success! Backup \"IridiumSkyblock.db\" created, check \"" + backupFolder.getPath() + "\"."); + return true; + } catch (IOException exception) { + IridiumSkyblock.getInstance().getLogger().severe("Failed to move \"IridiumSkyblock.db\" to " + backupFolder + ": " + + exception.getMessage()); + return false; + } + } + + @Override + public List < String > onTabComplete(CommandSender commandSender, String[] args, IridiumTeams < Island, User > iridiumTeams) { + switch (args.length) { + case 1: { + List < String > tables = new ArrayList < > (); + for (DataTable table: DataTable.values()) { + tables.add(table.name()); + } + return tables; + } + case 2: { + List < String > fullTabComplete = Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + fullTabComplete.add("--skip-confirm"); + return fullTabComplete; + } + case 3: + return Collections.singletonList("--skip-confirm"); + default: + return Collections.emptyList(); + } + } +} + +enum DataTable { + ALL, + ISLAND, + INVITE, + TRUST, + PERMISSION, + BANK, + ENHANCEMENT, + TEAM_BLOCK, + TEAM_SPAWNER, + TEAM_WARP, + TEAM_MISSION, + TEAM_REWARDS, + TEAM_SETTINGS; +} \ No newline at end of file diff --git a/src/main/java/com/iridium/iridiumskyblock/configs/Commands.java b/src/main/java/com/iridium/iridiumskyblock/configs/Commands.java index e4b955193..10dded96c 100644 --- a/src/main/java/com/iridium/iridiumskyblock/configs/Commands.java +++ b/src/main/java/com/iridium/iridiumskyblock/configs/Commands.java @@ -1,9 +1,6 @@ package com.iridium.iridiumskyblock.configs; -import com.iridium.iridiumskyblock.commands.BiomeCommand; -import com.iridium.iridiumskyblock.commands.BorderCommand; -import com.iridium.iridiumskyblock.commands.RegenCommand; -import com.iridium.iridiumskyblock.commands.VisitCommand; +import com.iridium.iridiumskyblock.commands.*; import com.iridium.iridiumskyblock.database.Island; import com.iridium.iridiumskyblock.database.User; @@ -16,4 +13,5 @@ public Commands() { public BorderCommand borderCommand = new BorderCommand(); public RegenCommand regenCommand = new RegenCommand(); public BiomeCommand biomeCommand = new BiomeCommand(); + public ClearDataCommand clearDataCommand = new ClearDataCommand(); } diff --git a/src/main/java/com/iridium/iridiumskyblock/configs/Messages.java b/src/main/java/com/iridium/iridiumskyblock/configs/Messages.java index e08245983..76ca1cedc 100644 --- a/src/main/java/com/iridium/iridiumskyblock/configs/Messages.java +++ b/src/main/java/com/iridium/iridiumskyblock/configs/Messages.java @@ -29,4 +29,7 @@ public Messages() { public String noBiomeCategory = "%prefix% &7No biome category with that name."; public String noBiome = "%prefix% &7No biome with that name."; public String changedBiome = "%prefix% &7%player% successfully changed your Island biome to %biome%."; + public String specifyData = "%prefix% &7Due to the nature of this destructive command, you must specify the data to be deleted (or specify \"all\")."; + public String confirmDataDeletion = "%prefix% &7You are about to delete the following data: %table% | [for: %island%] in 5 seconds. &cAre you sure you want to do this? (DATA IS &4&lUNRECOVERABLE&r&c)"; + public String dataDeletion = "%prefix% &cData has been deleted successfully. &7You may need to restart your server for it to take effect."; } diff --git a/src/main/java/com/iridium/iridiumskyblock/configs/Schematics.java b/src/main/java/com/iridium/iridiumskyblock/configs/Schematics.java index b7f25abff..092107ecf 100644 --- a/src/main/java/com/iridium/iridiumskyblock/configs/Schematics.java +++ b/src/main/java/com/iridium/iridiumskyblock/configs/Schematics.java @@ -1,5 +1,6 @@ package com.iridium.iridiumskyblock.configs; +import com.cryptomorin.xseries.XBiome; import com.cryptomorin.xseries.XMaterial; import com.cryptomorin.xseries.XSound; import com.cryptomorin.xseries.reflection.XReflection; @@ -20,27 +21,27 @@ public class Schematics { public Map schematics = ImmutableMap.builder() .put("desert", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 11, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGY0OTNkZDgwNjUzM2Q5ZDIwZTg0OTUzOTU0MzY1ZjRkMzY5NzA5Y2ViYzlkZGVmMDIyZDFmZDQwZDg2YTY4ZiJ9fX0=", 1, "&9&lDesert Island", Arrays.asList("&7A starter desert island.", "", "&9&l[!] &7Costs $1000")), - new Schematics.Cost(0, new HashMap<>()), 1, -0.5, 89, -0.5, 90, new SchematicWorld(Biome.DESERT, + new Schematics.Cost(0, new HashMap<>()), 1, -0.5, 89, -0.5, 90, new SchematicWorld(XBiome.DESERT, "desert.schem", 90.0, true - ), new SchematicWorld(XReflection.supports(16) ? Biome.NETHER_WASTES : Biome.valueOf("NETHER"), + ), new SchematicWorld(XBiome.NETHER_WASTES, "desert_nether.schem", 90.0, true - ), new SchematicWorld(Biome.THE_END, + ), new SchematicWorld(XBiome.THE_END, "desert_end.schem", 90.0, true ))) .put("jungle", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 13, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjgzYWRmNDU2MGRlNDc0MTQwNDA5M2FjNjFjMzNmYjU1NmIzZDllZTUxNDBmNjIwMzYyNTg5ZmRkZWRlZmEyZCJ9fX0=", 1, "&9&lJungle Island", Arrays.asList("&7A starter jungle island.", "", "&9&l[!] &7Costs $1000")), - new Schematics.Cost(0, new HashMap<>()), 1, 1.5, 83, 1.5, 90, new SchematicWorld(Biome.JUNGLE, + new Schematics.Cost(0, new HashMap<>()), 1, 1.5, 83, 1.5, 90, new SchematicWorld(XBiome.JUNGLE, "jungle.schem", 90.0, true - ), new SchematicWorld(XReflection.supports(16) ? Biome.NETHER_WASTES : Biome.valueOf("NETHER"), + ), new SchematicWorld(XBiome.NETHER_WASTES, "jungle_nether.schem", 90.0, true - ), new SchematicWorld(Biome.THE_END, + ), new SchematicWorld(XBiome.THE_END, "jungle_end.schem", 90.0, true ))) .put("mushroom", new SchematicConfig(new Item(XMaterial.PLAYER_HEAD, 15, "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE0NWQxYjQxN2NiZGRjMjE3NjdiMDYwNDRlODk5YjI2NmJmNzhhNjZlMjE4NzZiZTNjMDUxNWFiNTVkNzEifX19", 1, "&9&lMushroom Island", Arrays.asList("&7A starter mushroom island.", "", "&9&l[!] &7Costs $1000")), - new Schematics.Cost(0, new HashMap<>()), 1, 0.5, 89, -0.5, 90, new SchematicWorld(Biome.MUSHROOM_FIELDS, + new Schematics.Cost(0, new HashMap<>()), 1, 0.5, 89, -0.5, 90, new SchematicWorld(XBiome.MUSHROOM_FIELDS, "mushroom.schem", 90.0, true - ), new SchematicWorld(XReflection.supports(16) ? Biome.NETHER_WASTES : Biome.valueOf("NETHER"), + ), new SchematicWorld(XBiome.NETHER_WASTES, "mushroom_nether.schem", 90.0, true - ), new SchematicWorld(Biome.THE_END, + ), new SchematicWorld(XBiome.THE_END, "mushroom_end.schem", 90.0, true ))) .build(); @@ -68,12 +69,12 @@ public static class SchematicConfig { @NoArgsConstructor public static class SchematicWorld { - public Biome biome; + public XBiome biome; public String schematicID; public Double islandHeight; public Boolean ignoreAirBlocks; - public SchematicWorld(Biome biome, String schematicID, Double islandHeight, Boolean ignoreAirBlocks) { + public SchematicWorld(XBiome biome, String schematicID, Double islandHeight, Boolean ignoreAirBlocks) { this.biome = biome; this.schematicID = schematicID; this.islandHeight = islandHeight; diff --git a/src/main/java/com/iridium/iridiumskyblock/managers/BiomeManager.java b/src/main/java/com/iridium/iridiumskyblock/managers/BiomeManager.java index 8f08aed27..f8bb85c4e 100644 --- a/src/main/java/com/iridium/iridiumskyblock/managers/BiomeManager.java +++ b/src/main/java/com/iridium/iridiumskyblock/managers/BiomeManager.java @@ -20,7 +20,7 @@ public void buy(Player player, Biomes.BiomeItem biomeItem) { XBiome biome = biomeItem.biome; User user = IridiumSkyblock.getInstance().getUserManager().getUser(player); Optional island = user.getIsland(); - Optional biomeOptional = XBiome.matchXBiome(biomeItem.biome.toString()); + Optional biomeOptional = XBiome.of(biomeItem.biome.toString()); if (!canPurchase(player, biomeItem)) { IridiumSkyblock.getInstance().getBiomes().failSound.play(player); diff --git a/src/main/java/com/iridium/iridiumskyblock/managers/CommandManager.java b/src/main/java/com/iridium/iridiumskyblock/managers/CommandManager.java index 78ffd3a7c..43b74c2f0 100644 --- a/src/main/java/com/iridium/iridiumskyblock/managers/CommandManager.java +++ b/src/main/java/com/iridium/iridiumskyblock/managers/CommandManager.java @@ -23,6 +23,7 @@ public void registerCommands() { registerCommand(IridiumSkyblock.getInstance().getCommands().borderCommand); registerCommand(IridiumSkyblock.getInstance().getCommands().regenCommand); registerCommand(IridiumSkyblock.getInstance().getCommands().biomeCommand); + registerCommand(IridiumSkyblock.getInstance().getCommands().clearDataCommand); registerCommand(new IsThisWorking()); registerCommand(new IsMyComputerOnFire()); } diff --git a/src/main/java/com/iridium/iridiumskyblock/managers/DatabaseManager.java b/src/main/java/com/iridium/iridiumskyblock/managers/DatabaseManager.java index 6834aa312..c29ef7ee9 100644 --- a/src/main/java/com/iridium/iridiumskyblock/managers/DatabaseManager.java +++ b/src/main/java/com/iridium/iridiumskyblock/managers/DatabaseManager.java @@ -19,6 +19,8 @@ import java.io.File; import java.sql.SQLException; +import java.util.Comparator; +import java.util.List; import java.util.concurrent.CompletableFuture; @Getter @@ -50,6 +52,11 @@ public void init() throws SQLException { String databaseURL = getDatabaseURL(sqlConfig); DataPersisterManager.registerDataPersisters(XMaterialType.getSingleton()); + DataPersisterManager.registerDataPersisters(XEntityTypeType.getSingleton()); + DataPersisterManager.registerDataPersisters(XPotionType.getSingleton()); + DataPersisterManager.registerDataPersisters(XEnchantmentType.getSingleton()); + DataPersisterManager.registerDataPersisters(XBiomeType.getSingleton()); + DataPersisterManager.registerDataPersisters(LocationType.getSingleton()); DataPersisterManager.registerDataPersisters(InventoryType.getSingleton()); DataPersisterManager.registerDataPersisters(LocalDateTimeType.getSingleton()); @@ -77,6 +84,14 @@ public void init() throws SQLException { this.teamMissionTableManager = new ForeignIslandTableManager<>(teamMission -> getDatabaseKey(teamMission.getTeamID(), teamMission.getMissionName()), connectionSource, TeamMission.class); this.teamRewardsTableManager = new ForeignIslandTableManager<>(teamRewards -> getDatabaseKey(teamRewards.getId()), connectionSource, TeamReward.class); this.teamSettingsTableManager = new ForeignIslandTableManager<>(teamSetting -> getDatabaseKey(teamSetting.getTeamID(), teamSetting.getSetting()), connectionSource, TeamSetting.class); + + // We need to clear out null values + for(TeamBlock teamBlock : teamBlockTableManager.getEntries()) { + if(teamBlock.getXMaterial() == null) teamBlockTableManager.delete(teamBlock); + } + for(TeamSpawners teamSpawners : teamSpawnerTableManager.getEntries()) { + if(teamSpawners.getEntityType() == null) teamSpawnerTableManager.delete(teamSpawners); + } } private String getDatabaseKey(Object... params) { diff --git a/src/main/java/com/iridium/iridiumskyblock/managers/IslandManager.java b/src/main/java/com/iridium/iridiumskyblock/managers/IslandManager.java index dbfa64c1f..defc08a89 100644 --- a/src/main/java/com/iridium/iridiumskyblock/managers/IslandManager.java +++ b/src/main/java/com/iridium/iridiumskyblock/managers/IslandManager.java @@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -127,7 +128,7 @@ public void createCacheWorld(World world) { } public void setIslandBiome(@NotNull Island island, @NotNull XBiome biome) { - World.Environment dimension = biome.getEnvironment(); + World.Environment dimension = biome.getEnvironment().get(); World world = getWorld(dimension); if (world == null) return; @@ -308,9 +309,9 @@ private void setHome(Island island, Schematics.SchematicConfig schematicConfig) } public void setIslandBiome(Island island, Schematics.SchematicConfig schematicConfig) { - setIslandBiome(island, XBiome.matchXBiome(schematicConfig.overworld.biome)); - setIslandBiome(island, XBiome.matchXBiome(schematicConfig.nether.biome)); - setIslandBiome(island, XBiome.matchXBiome(schematicConfig.end.biome)); + setIslandBiome(island, schematicConfig.overworld.biome); + setIslandBiome(island, schematicConfig.nether.biome); + setIslandBiome(island, schematicConfig.end.biome); } public CompletableFuture clearEntities(Island island) { @@ -761,6 +762,16 @@ public void deleteTeamMission(TeamMission teamMission) { IridiumSkyblock.getInstance().getDatabaseManager().getTeamMissionTableManager().delete(teamMission); } + @Override + public void deleteTeamMissionData(TeamMission teamMission) { + MissionData missionData = IridiumSkyblock.getInstance().getMissions().missions.get(teamMission.getMissionName()).getMissionData().get(teamMission.getMissionLevel()); + + for (int i = 0; i < missionData.getMissions().size(); i++) { + Optional data = IridiumSkyblock.getInstance().getDatabaseManager().getTeamMissionDataTableManager().getEntry(new TeamMissionData(teamMission, i)); + data.ifPresent(teamMissionData -> IridiumSkyblock.getInstance().getDatabaseManager().getTeamMissionDataTableManager().delete(teamMissionData)); + } + } + @Override public List getTeamRewards(Island island) { return IridiumSkyblock.getInstance().getDatabaseManager().getTeamRewardsTableManager().getEntries(island); @@ -872,14 +883,51 @@ public void handleBlockPlaceOutsideTerritory(BlockPlaceEvent blockEvent) { public void clearTeamInventory(Island island) { - if (IridiumSkyblock.getInstance().getConfiguration().clearInventoryOnRegen) { - IridiumSkyblock.getInstance().getIslandManager().getMembersOnIsland(island).forEach(member -> - member.getPlayer().getInventory().clear()); + List onlinePlayers = new ArrayList<>(); + List offlinePlayers = new ArrayList<>(); + + for(User user : island.getMembers()) { + + if (user.getUserRank() == -1) continue; + + try{ + user.getPlayer(); + onlinePlayers.add(user); + } catch (Exception e) { + offlinePlayers.add(user); + } } - if (IridiumSkyblock.getInstance().getConfiguration().clearEnderChestOnRegen) { - IridiumSkyblock.getInstance().getIslandManager().getMembersOnIsland(island).forEach(member -> - member.getPlayer().getEnderChest().clear()); + for (User user : onlinePlayers) { + if (IridiumSkyblock.getInstance().getConfiguration().clearInventoryOnRegen) user.getPlayer().getInventory().clear(); + if (IridiumSkyblock.getInstance().getConfiguration().clearEnderChestOnRegen) user.getPlayer().getEnderChest().clear(); + } + + for(User user : offlinePlayers) { + + try { + File file = new File(Bukkit.getWorlds().get(0).getWorldFolder().getPath() + File.pathSeparator + "playerdata" + File.pathSeparator + user.getUuid() + ".dat"); + NBTFile playerFile = new NBTFile(file); + + if (IridiumSkyblock.getInstance().getConfiguration().clearInventoryOnRegen) { + NBTCompound compound = playerFile.getCompound("").getCompound("Inventory"); + compound.clearNBT(); + playerFile.save(); + } + + if (IridiumSkyblock.getInstance().getConfiguration().clearEnderChestOnRegen) { + NBTCompound compound = playerFile.getCompound("").getCompound("EnderItems"); + compound.clearNBT(); + playerFile.save(); + } + + } catch (IOException e) { + IridiumSkyblock.getInstance().getLogger().warning("Cannot mutate user: " + user.getName() + ". See stacktrace for details."); + IridiumSkyblock.getInstance().getLogger().warning(e.getMessage()); + } catch (NullPointerException e) { + IridiumSkyblock.getInstance().getLogger().warning("Cannot mutate user: " + user.getName() + ". Either player or compound doesn't exist (See stacktrace for details)."); + IridiumSkyblock.getInstance().getLogger().warning(e.getMessage()); + } } } diff --git a/src/main/java/com/iridium/iridiumskyblock/managers/tablemanagers/TableManager.java b/src/main/java/com/iridium/iridiumskyblock/managers/tablemanagers/TableManager.java index a1f66aee2..3e8254f3e 100644 --- a/src/main/java/com/iridium/iridiumskyblock/managers/tablemanagers/TableManager.java +++ b/src/main/java/com/iridium/iridiumskyblock/managers/tablemanagers/TableManager.java @@ -1,5 +1,6 @@ package com.iridium.iridiumskyblock.managers.tablemanagers; +import com.iridium.iridiumskyblock.IridiumSkyblock; import com.iridium.iridiumskyblock.managers.DatabaseKey; import com.iridium.iridiumteams.database.DatabaseObject; import com.j256.ormlite.dao.Dao; @@ -15,6 +16,9 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -22,6 +26,7 @@ public class TableManager { private final ConcurrentHashMap entries = new ConcurrentHashMap<>(); private final Dao dao; private final DatabaseKey databaseKey; + private final static Lock lock = new ReentrantLock(); private final ConnectionSource connectionSource; @@ -38,29 +43,83 @@ public TableManager(DatabaseKey databaseKey, ConnectionSource connec public void save() { try { - List entryList = new ArrayList<>(entries.values()); - for (Value t : entryList) { - if (!t.isChanged()) continue; - dao.createOrUpdate(t); - t.setChanged(false); + if (!lock.tryLock(5, TimeUnit.SECONDS)) { + IridiumSkyblock.getInstance().getLogger().warning("Warning: Lock acquisition took more than 5 second in save() method."); } - dao.commit(getDatabaseConnection()); - } catch (SQLException throwables) { - throwables.printStackTrace(); + try { + List entryList = new ArrayList<>(entries.values()); + boolean modified = false; + for (Value t : entryList) { + if (!t.isChanged()) continue; + modified = true; + dao.createOrUpdate(t); + t.setChanged(false); + } + if (modified) dao.commit(getDatabaseConnection()); + } finally { + lock.unlock(); + } + } catch (InterruptedException | SQLException e) { + e.printStackTrace(); } } public void save(Value value) { try { - if (!value.isChanged()) return; - dao.createOrUpdate(value); - dao.commit(getDatabaseConnection()); - value.setChanged(false); - } catch (SQLException throwables) { - throwables.printStackTrace(); + if (!lock.tryLock(5, TimeUnit.SECONDS)) { + IridiumSkyblock.getInstance().getLogger().warning("Warning: Lock acquisition took more than 5 second in save(value) method."); + } + try { + if (!value.isChanged()) return; + dao.createOrUpdate(value); + dao.commit(getDatabaseConnection()); + value.setChanged(false); + } finally { + lock.unlock(); + } + } catch (InterruptedException | SQLException e) { + e.printStackTrace(); } } + public CompletableFuture delete(Value value) { + entries.remove(databaseKey.getKey(value)); + return CompletableFuture.runAsync(() -> { + try { + if (!lock.tryLock(5, TimeUnit.SECONDS)) { + IridiumSkyblock.getInstance().getLogger().warning("Warning: Lock acquisition took more than 5 second in delete(value) method."); + } + try { + dao.delete(value); + dao.commit(getDatabaseConnection()); + } finally { + lock.unlock(); + } + } catch (InterruptedException | SQLException e) { + e.printStackTrace(); + } + }); + } + + public CompletableFuture delete(Collection values) { + values.forEach(value -> entries.remove(databaseKey.getKey(value))); + return CompletableFuture.runAsync(() -> { + try { + if (!lock.tryLock(5, TimeUnit.SECONDS)) { + IridiumSkyblock.getInstance().getLogger().warning("Warning: Lock acquisition took more than 5 second in delete(Collection) method."); + } + try { + dao.delete(values); + dao.commit(getDatabaseConnection()); + } finally { + lock.unlock(); + } + } catch (InterruptedException | SQLException e) { + e.printStackTrace(); + } + }); + } + public void addEntry(Value value) { entries.put(databaseKey.getKey(value), value); } @@ -85,30 +144,6 @@ public Optional getEntry(Function searchFunction) return entries.values().stream().filter(searchFunction::apply).findFirst(); } - public CompletableFuture delete(Value value) { - entries.remove(databaseKey.getKey(value)); - return CompletableFuture.runAsync(() -> { - try { - dao.delete(value); - dao.commit(getDatabaseConnection()); - } catch (SQLException throwables) { - throwables.printStackTrace(); - } - }); - } - - public CompletableFuture delete(Collection values) { - values.forEach(value -> entries.remove(databaseKey.getKey(value))); - return CompletableFuture.runAsync(() -> { - try { - dao.delete(values); - dao.commit(getDatabaseConnection()); - } catch (SQLException throwables) { - throwables.printStackTrace(); - } - }); - } - private DatabaseConnection getDatabaseConnection() throws SQLException { return connectionSource.getReadWriteConnection(null); } diff --git a/src/main/java/com/iridium/iridiumskyblock/placeholders/IslandPlaceholderBuilder.java b/src/main/java/com/iridium/iridiumskyblock/placeholders/IslandPlaceholderBuilder.java index 99435f036..051d53737 100644 --- a/src/main/java/com/iridium/iridiumskyblock/placeholders/IslandPlaceholderBuilder.java +++ b/src/main/java/com/iridium/iridiumskyblock/placeholders/IslandPlaceholderBuilder.java @@ -50,7 +50,7 @@ public List getPlaceholders(Island island) { .orElse(IridiumSkyblock.getInstance().getMessages().nullPlaceholder)), new Placeholder("island_create", () -> island.getCreateTime().format(DateTimeFormatter.ofPattern(IridiumSkyblock.getInstance().getConfiguration().dateTimeFormat))), new Placeholder("island_description", island::getDescription), - new Placeholder("island_value", () -> String.valueOf(IridiumSkyblock.getInstance().getTeamManager().getTeamValue(island))), + new Placeholder("island_value", () -> formatDouble(IridiumSkyblock.getInstance().getTeamManager().getTeamValue(island))), new Placeholder("island_level", () -> String.valueOf(island.getLevel())), new Placeholder("island_experience", String.valueOf(island.getExperience())), new Placeholder("island_experienceToLevelUp", String.valueOf(IridiumSkyblock.getInstance().getIslandManager().getTeamExperienceForNextLevel(island))), @@ -87,7 +87,7 @@ public List getPlaceholders(Island island) { } for (BankItem bankItem : IridiumSkyblock.getInstance().getBankItemList()) { - placeholderList.add(new Placeholder("island_bank_" + bankItem.getName().toLowerCase(), () -> String.valueOf(IridiumSkyblock.getInstance().getTeamManager().getTeamBank(island, bankItem.getName()).getNumber()))); + placeholderList.add(new Placeholder("island_bank_" + bankItem.getName().toLowerCase(), () -> formatDouble(IridiumSkyblock.getInstance().getTeamManager().getTeamBank(island, bankItem.getName()).getNumber()))); } for (XMaterial xMaterial : XMaterial.values()) { placeholderList.add(new Placeholder("island_" + xMaterial.name().toLowerCase() + "_amount", () -> String.valueOf(IridiumSkyblock.getInstance().getTeamManager().getTeamBlock(island, xMaterial).getAmount()))); @@ -99,8 +99,11 @@ public List getPlaceholders(Island island) { }); } - private List initializeDefaultPlaceholders() { + private String formatDouble(double value) { + return IridiumSkyblock.getInstance().getConfiguration().numberFormatter.format(value); + } + private List initializeDefaultPlaceholders() { List placeholderList = new ArrayList<>(Arrays.asList( new Placeholder("island_name", IridiumSkyblock.getInstance().getMessages().nullPlaceholder), new Placeholder("island_owner", IridiumSkyblock.getInstance().getMessages().nullPlaceholder),