From b3e1abd1f35c2295e159a4dedf8009304520b359 Mon Sep 17 00:00:00 2001 From: "BT (calcastor/mame)" <43831917+calcastor@users.noreply.github.com> Date: Thu, 22 Jan 2026 21:02:57 -0800 Subject: [PATCH] Treewide cleanup and use of modern Java features Signed-off-by: BT (calcastor/mame) <43831917+calcastor@users.noreply.github.com> --- buildSrc/build.gradle.kts | 4 +- .../buildlogic.java-conventions.gradle.kts | 25 +- core/build.gradle.kts | 1 - .../dev/pgm/community/CommunityCommand.java | 58 +- .../assistance/AssistanceRequest.java | 4 +- .../dev/pgm/community/assistance/Report.java | 5 +- .../commands/PlayerHelpCommand.java | 4 +- .../assistance/commands/ReportCommands.java | 58 +- .../feature/types/AssistanceFeatureCore.java | 8 +- .../assistance/menu/ReportCategoryMenu.java | 10 +- .../assistance/menu/ReportReasonsMenu.java | 6 +- .../assistance/services/AssistanceQuery.java | 24 +- .../services/SQLAssistanceService.java | 14 +- .../management/ChatManagementFeature.java | 56 +- .../chat/network/NetworkChatFeature.java | 2 +- .../chat/network/NetworkChatMessage.java | 8 +- .../community/commands/ContainerCommand.java | 35 +- .../pgm/community/commands/FlightCommand.java | 35 +- .../community/commands/GamemodeCommand.java | 37 +- .../pgm/community/commands/SudoCommand.java | 21 +- .../commands/providers/GameModeParser.java | 4 +- .../providers/TargetPlayerParser.java | 12 +- .../events/UserProfileLoadEvent.java | 2 +- .../pgm/community/freeze/FreezeCommand.java | 19 +- .../pgm/community/freeze/FreezeFeature.java | 19 +- .../pgm/community/freeze/FreezeManager.java | 14 +- .../friends/FriendRequestStatus.java | 2 +- .../dev/pgm/community/friends/Friendship.java | 17 +- .../friends/commands/FriendshipCommand.java | 102 ++-- .../friends/feature/PGMFriendIntegration.java | 2 +- .../friends/services/FriendshipQuery.java | 26 +- .../services/SQLFriendshipService.java | 17 +- .../community/history/MatchHistoryEntry.java | 2 +- .../pgm/community/info/InfoCommandData.java | 30 +- .../community/info/InfoCommandsFeature.java | 3 +- .../menu/CommunityInventoryProvider.java | 15 +- .../pgm/community/menu/MapSelectionMenu.java | 16 +- .../java/dev/pgm/community/menu/MenuItem.java | 2 +- .../menu/PlayerSelectionProvider.java | 2 +- .../dev/pgm/community/mobs/MobFeature.java | 28 +- .../moderation/ModerationConfig.java | 20 +- .../feature/PGMPunishmentIntegration.java | 4 +- .../feature/types/ModerationFeatureCore.java | 8 +- .../punishments/NetworkPunishment.java | 19 +- .../moderation/punishments/Punishment.java | 43 +- .../punishments/PunishmentType.java | 4 +- .../types/ExpirablePunishment.java | 10 +- .../moderation/services/ModerationQuery.java | 22 +- .../services/SQLModerationService.java | 17 +- .../moderation/tools/ModerationTools.java | 6 +- .../community/moderation/tools/ToolBase.java | 4 +- .../tools/buttons/ToolButtonBase.java | 10 +- .../tools/buttons/TranslatableToolButton.java | 6 +- .../tools/buttons/types/GamemodeButton.java | 13 +- .../types/ObserverVisibilityButton.java | 13 +- .../tools/buttons/types/SpeedButton.java | 2 +- .../tools/menu/ModerationToolsMenu.java | 4 +- .../tools/types/ModerationMenuTool.java | 2 +- .../pgm/community/mutations/MutationType.java | 6 +- .../mutations/feature/MutationFeature.java | 31 +- .../mutations/menu/MutationOptionsMenu.java | 36 +- .../mutations/menu/MutationToggleMenu.java | 12 +- .../options/MutationBooleanOption.java | 2 +- .../mutations/options/MutationListOption.java | 6 +- .../options/MutationRangeOption.java | 6 +- .../mutations/types/KitMutationBase.java | 11 +- .../types/arrows/WebSlingersMutation.java | 12 +- .../types/gameplay/BlitzMutation.java | 2 +- .../types/gameplay/GhostMutation.java | 6 +- .../mutations/types/items/BreadMutation.java | 14 +- .../types/items/ExplosionMutation.java | 30 +- .../types/items/FireworkMutation.java | 13 +- .../types/items/GrapplingHookMutation.java | 3 +- .../mutations/types/items/PotionMutation.java | 2 +- .../types/mechanics/DoubleJumpMutation.java | 7 +- .../types/mechanics/FlyMutation.java | 60 +- .../types/mechanics/FriendlyFireMutation.java | 6 +- .../types/mechanics/MobMutation.java | 6 +- .../types/world/BlockDecayMutation.java | 21 +- .../mutations/types/world/StormMutation.java | 9 +- .../types/world/TNTRainMutation.java | 9 +- .../dev/pgm/community/network/Channels.java | 2 +- .../network/subs/NetworkSubscriber.java | 4 +- .../subs/types/AssistanceSubscriber.java | 2 +- .../network/subs/types/ChatSubscriber.java | 2 +- .../subs/types/PunishmentSubscriber.java | 2 +- .../types/RefreshPunishmentSubscriber.java | 7 +- .../network/types/RedisNetworkFeature.java | 57 +- .../network/updates/NetworkUpdateBase.java | 6 +- .../types/RefreshPunishmentUpdate.java | 8 +- .../java/dev/pgm/community/nick/Nick.java | 2 +- .../java/dev/pgm/community/nick/NickImpl.java | 2 +- .../community/nick/commands/NickCommands.java | 68 +-- .../community/nick/data/NickSelection.java | 4 +- .../nick/feature/PGMNickIntegration.java | 12 +- .../nick/feature/types/NickFeatureCore.java | 28 +- .../community/nick/services/NickQuery.java | 12 +- .../nick/services/SQLNickService.java | 7 +- .../pgm/community/nick/skin/SkinCache.java | 3 +- .../pgm/community/nick/skin/SkinManager.java | 2 +- .../dev/pgm/community/party/MapPartyBase.java | 4 +- .../pgm/community/party/MapPartyCommands.java | 2 +- .../pgm/community/party/MapPartyConfig.java | 2 +- .../community/party/MapPartyStatusType.java | 4 +- .../dev/pgm/community/party/MapPartyType.java | 6 +- .../broadcasts/MapPartyBroadcastManager.java | 12 +- .../party/exceptions/MapPartyException.java | 2 +- .../party/feature/MapPartyFeature.java | 49 +- .../party/history/MapPartyHistoryEntry.java | 3 +- .../community/party/hosts/MapPartyHosts.java | 13 +- .../party/menu/MapPartyMainMenu.java | 67 +- .../community/party/menu/MapPartyMenu.java | 9 +- .../party/menu/hosts/HostAddMenu.java | 8 +- .../community/party/menu/hosts/HostMenu.java | 6 +- .../community/party/menu/maps/MapAddMenu.java | 26 +- .../community/party/menu/maps/MapMenu.java | 23 +- .../menu/modifiers/MapPartyModifierMenu.java | 22 +- .../menu/settings/MapPartySettingsMenu.java | 5 +- .../party/presets/MapPartyPreset.java | 40 +- .../party/settings/MapPartySettings.java | 6 +- .../party/settings/PartyBooleanSetting.java | 4 +- .../party/settings/PartySetting.java | 4 +- .../party/types/CustomPoolParty.java | 2 +- .../dev/pgm/community/polls/PollBuilder.java | 77 ++- .../pgm/community/polls/PollComponents.java | 244 ++++---- .../pgm/community/polls/PollEditAlerter.java | 29 +- .../polls/ending/types/CommandEndAction.java | 8 +- .../ending/types/KickPlayerEndAction.java | 36 +- .../polls/ending/types/MapEndAction.java | 36 +- .../polls/ending/types/NullEndAction.java | 25 +- .../community/polls/events/PollVoteEvent.java | 2 +- .../SingleChoiceResponseConverter.java | 23 +- .../pgm/community/requests/MapCooldown.java | 8 +- .../community/requests/SponsorRequest.java | 25 +- .../commands/sponsor/SponsorCommands.java | 20 +- .../commands/sponsor/TokenCommands.java | 26 +- .../requests/feature/RequestFeature.java | 8 +- .../feature/SponsorVotingBookCreator.java | 6 +- .../feature/types/RequestFeatureCore.java | 44 +- .../requests/services/RequestQuery.java | 12 +- .../requests/services/SQLRequestService.java | 15 +- .../requests/sponsor/SponsorComponents.java | 4 +- .../requests/sponsor/SponsorManager.java | 10 +- .../requests/supervotes/SuperVoteManager.java | 14 +- .../pgm/community/sessions/SessionQuery.java | 27 +- .../sessions/VanishedSessionListener.java | 19 +- .../sessions/services/SQLSessionService.java | 12 +- .../sessions/services/SessionDataQuery.java | 21 +- .../community/teleports/TeleportCommand.java | 12 +- .../teleports/TeleportFeatureBase.java | 7 +- .../dev/pgm/community/text/UTF8Control.java | 3 +- .../pgm/community/users/UserProfileImpl.java | 2 +- .../users/UserProfileWithSessionCallback.java | 2 +- .../users/commands/UserInfoCommands.java | 574 ++++++++---------- .../community/users/feature/UsersFeature.java | 16 +- .../listeners/UserProfileLoginListener.java | 10 +- .../users/services/AddressHistoryService.java | 50 +- .../users/services/AddressQuery.java | 97 ++- .../users/services/SQLUserService.java | 13 +- .../community/users/services/UserQuery.java | 14 +- .../pgm/community/utils/BroadcastUtils.java | 8 +- .../pgm/community/utils/CommandAudience.java | 8 +- .../dev/pgm/community/utils/ImportUtils.java | 24 +- .../dev/pgm/community/utils/MessageUtils.java | 12 +- .../dev/pgm/community/utils/NameUtils.java | 2 +- .../dev/pgm/community/utils/PGMUtils.java | 26 +- .../utils/PaginatedComponentResults.java | 6 +- .../pgm/community/utils/ranks/RankUtils.java | 9 +- .../community/utils/ranks/RanksConfig.java | 48 +- gradle/wrapper/gradle-wrapper.jar | Bin 45633 -> 46175 bytes .../platform/modern/ModernInventoryUtils.java | 3 +- .../platform/sportpaper/SpInventoryUtils.java | 3 +- .../dev/pgm/community/util/Attributes.java | 3 +- 173 files changed, 1435 insertions(+), 2083 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index dbcc0909..e7470114 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -9,7 +9,7 @@ repositories { } dependencies { - implementation("com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.3.0") - implementation("com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin:8.1.0") + implementation("com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.3.1") + implementation("com.diffplug.gradle.spotless:com.diffplug.gradle.spotless.gradle.plugin:8.2.0") implementation("de.skuzzle.restrictimports:de.skuzzle.restrictimports.gradle.plugin:3.0.0") } diff --git a/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts index 0d2b340e..e3600a5f 100644 --- a/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/buildlogic.java-conventions.gradle.kts @@ -19,21 +19,24 @@ repositories { } dependencies { - implementation("com.zaxxer:HikariCP:2.4.1") { isTransitive = false } - implementation("fr.minuskube.inv:smart-invs:1.2.7") { isTransitive = false } + api("com.zaxxer:HikariCP:2.4.1") { isTransitive = false } + api("fr.minuskube.inv:smart-invs:1.2.7") { isTransitive = false } + api("redis.clients:jedis:3.5.1") + api("net.kyori:adventure-api:4.26.1") + api("net.kyori:adventure-text-serializer-plain:4.26.1") + api("net.kyori:adventure-platform-bukkit:4.4.1") + api("org.reflections:reflections:0.10.2") - implementation("redis.clients:jedis:3.5.1") - implementation("net.kyori:adventure-api:4.25.0") - implementation("net.kyori:adventure-text-serializer-plain:4.25.0") - implementation("net.kyori:adventure-platform-bukkit:4.4.1") - implementation("org.reflections:reflections:0.10.2") + // Annotations + api("org.jspecify:jspecify:1.0.0") + compileOnly("org.jetbrains:annotations:26.0.2-1") + // Runtime dependencies compileOnly("tc.oc.pgm:core:0.16-SNAPSHOT") compileOnly("tc.oc.pgm:util:0.16-SNAPSHOT") compileOnly("tc.oc.occ:AFK:1.0.0-SNAPSHOT") compileOnly("tc.oc.occ:Environment:1.0.0-SNAPSHOT") compileOnly("org.incendo:cloud-annotations:2.0.0") - compileOnly("org.jetbrains:annotations:26.0.2") compileOnly("net.dmulloy2:ProtocolLib:5.4.0") // Minecraft includes these (or equivalents) @@ -60,13 +63,15 @@ spotless { ratchetFrom = "origin/dev" java { removeUnusedImports() - palantirJavaFormat("2.83.0").style("GOOGLE").formatJavadoc(true) + trimTrailingWhitespace() + formatAnnotations() + palantirJavaFormat("2.85.0").style("GOOGLE").formatJavadoc(true) } } restrictImports { group { - reason = "Use org.jetbrains.annotations to add annotations" + reason = "Use org.jspecify.annotations to add annotations, or org.jetbrains.annotations if needed" bannedImports = listOf("javax.annotation.**") } group { diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ba4df199..3052b7d8 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -32,7 +32,6 @@ tasks.named("shadowJar") { } dependencies { - exclude(dependency("org.jspecify:jspecify")) exclude(dependency("org.jetbrains:annotations")) } diff --git a/core/src/main/java/dev/pgm/community/CommunityCommand.java b/core/src/main/java/dev/pgm/community/CommunityCommand.java index 8acc194a..c9360168 100644 --- a/core/src/main/java/dev/pgm/community/CommunityCommand.java +++ b/core/src/main/java/dev/pgm/community/CommunityCommand.java @@ -10,6 +10,7 @@ import dev.pgm.community.utils.NameUtils; import dev.pgm.community.utils.PGMUtils; import dev.pgm.community.utils.VisibilityUtils; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; @@ -24,7 +25,7 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.api.match.Match; import tc.oc.pgm.api.player.MatchPlayer; import tc.oc.pgm.teams.Team; @@ -46,7 +47,7 @@ protected CompletableFuture> getTarget(String target, UsersFeatur boolean username = NameUtils.isMinecraftName(target); if (!username) { try { - return CompletableFuture.completedFuture(Optional.ofNullable(UUID.fromString(target))); + return CompletableFuture.completedFuture(Optional.of(UUID.fromString(target))); } catch (IllegalArgumentException e) { throw TextException.exception(target + " is not a valid UUID."); } @@ -54,19 +55,7 @@ protected CompletableFuture> getTarget(String target, UsersFeatur return service.getStoredId(target); } - public class PlayerSelection { - - private final Set players; - private final Component selectionText; - - public PlayerSelection(Set players, Component selectionText) { - this.players = players; - this.selectionText = selectionText; - } - - public Set getPlayers() { - return players; - } + public record PlayerSelection(Set players, Component selectionText) { public Component getText() { List names = players.stream() @@ -75,9 +64,9 @@ public Component getText() { .collect(Collectors.toList()); Component hover = TextFormatter.list(names, NamedTextColor.GRAY); - if (getPlayers().size() > names.size()) { - int leftOver = getPlayers().size() - names.size(); - hover + if (players().size() > names.size()) { + int leftOver = players().size() - names.size(); + hover = hover .append(text(" plus ")) .append(text(leftOver, NamedTextColor.YELLOW)) .append(text(" other player" + (leftOver != 1 ? "s" : ""))) @@ -106,7 +95,7 @@ protected PlayerSelection getPlayers(CommandAudience viewer, String input) { String[] parts = input.split("="); - List allOnline = Bukkit.getOnlinePlayers().stream().collect(Collectors.toList()); + List allOnline = new ArrayList<>(Bukkit.getOnlinePlayers()); Set targets = Sets.newHashSet(); Component text; @@ -141,16 +130,14 @@ protected PlayerSelection getPlayers(CommandAudience viewer, String input) { // Allow Observers to be selected if (teamName.toLowerCase().startsWith("obs")) { text = text("Observers", NamedTextColor.AQUA); - targets.addAll(match.getObservers().stream() - .map(MatchPlayer::getBukkit) - .collect(Collectors.toList())); + targets.addAll( + match.getObservers().stream().map(MatchPlayer::getBukkit).toList()); } else { Team team = teams.bestFuzzyMatch(teamName); if (team == null) { throw TextException.exception(teamName + " is not a valid team name"); } - targets.addAll( - team.getPlayers().stream().map(MatchPlayer::getBukkit).collect(Collectors.toList())); + targets.addAll(team.getPlayers().stream().map(MatchPlayer::getBukkit).toList()); text = text() .append(text(team.getNameLegacy(), TextFormatter.convert(team.getColor()))) .build(); @@ -176,9 +163,7 @@ protected PlayerSelection getPlayers(CommandAudience viewer, String input) { // If no permission for multiple, get a random single entry Player random = targets.stream().findAny().get(); targets.clear(); - if (random != null) { - targets.add(random); - } + targets.add(random); } } @@ -189,8 +174,7 @@ private int parseInputInt(String input, int def) { int value = def; try { value = Integer.parseInt(input); - } catch (NumberFormatException e) { - value = def; + } catch (NumberFormatException ignored) { } return value; } @@ -210,8 +194,8 @@ protected Player getSinglePlayer(CommandAudience viewer, String target, boolean } if (player == null - || (player != null && !canViewVanished(viewer, player)) - || (player != null && nicked == null && isNicked(viewer, player))) { + || !canViewVanished(viewer, player) + || nicked == null && isNicked(viewer, player)) { viewer.sendWarning(formatNotFoundComponent(target)); return null; } @@ -234,7 +218,7 @@ protected UUID getOnlineTarget(String target, UsersFeature service) { // priority now Optional cachedId = service.getId( target); // If user is online or was online recently, we will have their UUID. - if (!cachedId.isPresent()) { + if (cachedId.isEmpty()) { throw TextException.exception(formatNotFoundMsg(target)); } else { id = cachedId.get(); @@ -257,13 +241,9 @@ private boolean isVanished(@Nullable Player player) { } public boolean canViewVanished(CommandAudience viewer, Player player) { - boolean vanished = isVanished(player); - if (vanished - && viewer.isPlayer() - && !viewer.getPlayer().hasPermission(CommunityPermissions.VIEW_VANISHED)) { - return false; - } - return true; + return !isVanished(player) + || !viewer.isPlayer() + || viewer.getPlayer().hasPermission(CommunityPermissions.VIEW_VANISHED); } protected String formatNotFoundMsg(String target) { diff --git a/core/src/main/java/dev/pgm/community/assistance/AssistanceRequest.java b/core/src/main/java/dev/pgm/community/assistance/AssistanceRequest.java index 158f8fa3..a6bad06a 100644 --- a/core/src/main/java/dev/pgm/community/assistance/AssistanceRequest.java +++ b/core/src/main/java/dev/pgm/community/assistance/AssistanceRequest.java @@ -49,9 +49,9 @@ public RequestType getType() { return type; } - public static enum RequestType { + public enum RequestType { PLAYER_HELP, - REPORT; + REPORT } @Override diff --git a/core/src/main/java/dev/pgm/community/assistance/Report.java b/core/src/main/java/dev/pgm/community/assistance/Report.java index 45cbbbb6..0715965c 100644 --- a/core/src/main/java/dev/pgm/community/assistance/Report.java +++ b/core/src/main/java/dev/pgm/community/assistance/Report.java @@ -14,7 +14,7 @@ public class Report extends AssistanceRequest implements Comparable { * @param reporterId UUID of reporting player * @param reason reason for report * @param time time reported - * @param name of current server + * @param server name of current server */ public Report(UUID reportedId, UUID reporterId, String reason, long time, String server) { this(UUID.randomUUID(), reportedId, reporterId, reason, time, server); @@ -51,8 +51,7 @@ public int compareTo(Report o) { @Override public boolean equals(Object other) { - if (!(other instanceof Report)) return false; - Report otherReport = (Report) other; + if (!(other instanceof Report otherReport)) return false; return getId().equals(otherReport.getId()); } } diff --git a/core/src/main/java/dev/pgm/community/assistance/commands/PlayerHelpCommand.java b/core/src/main/java/dev/pgm/community/assistance/commands/PlayerHelpCommand.java index 0e3ee51b..2fa1a6c3 100644 --- a/core/src/main/java/dev/pgm/community/assistance/commands/PlayerHelpCommand.java +++ b/core/src/main/java/dev/pgm/community/assistance/commands/PlayerHelpCommand.java @@ -15,8 +15,8 @@ public class PlayerHelpCommand extends CommunityCommand { - private AssistanceFeature assistance; - private ModerationFeature moderation; + private final AssistanceFeature assistance; + private final ModerationFeature moderation; public PlayerHelpCommand() { this.assistance = Community.get().getFeatures().getReports(); diff --git a/core/src/main/java/dev/pgm/community/assistance/commands/ReportCommands.java b/core/src/main/java/dev/pgm/community/assistance/commands/ReportCommands.java index 97f0d33b..c3c09733 100644 --- a/core/src/main/java/dev/pgm/community/assistance/commands/ReportCommands.java +++ b/core/src/main/java/dev/pgm/community/assistance/commands/ReportCommands.java @@ -89,17 +89,14 @@ public void recentReports( checkEnabled(); if (player != null) { - reports - .query(player) - .thenAcceptAsync( - reports -> { - if (reports.isEmpty()) { - audience.sendWarning( - text("No reports found for ").append(text(player, NamedTextColor.AQUA))); - return; - } - sendReportHistory(audience, reports, page); - }); + reports.query(player).thenAcceptAsync(reports -> { + if (reports.isEmpty()) { + audience.sendWarning( + text("No reports found for ").append(text(player, NamedTextColor.AQUA))); + return; + } + sendReportHistory(audience, reports, page); + }); return; } @@ -113,16 +110,15 @@ public void sendReportHistory(CommandAudience audience, Collection repor int pages = (reportData.size() + perPage - 1) / perPage; page = Math.max(1, Math.min(page, pages)); - Component pageNum = - translatable( - "command.simplePageHeader", - NamedTextColor.GRAY, - text(Integer.toString(page), NamedTextColor.RED), - text(Integer.toString(pages), NamedTextColor.RED)); + Component pageNum = translatable( + "command.simplePageHeader", + NamedTextColor.GRAY, + text(Integer.toString(page), NamedTextColor.RED), + text(Integer.toString(pages), NamedTextColor.RED)); - Component header = - translatable("moderation.reports.header", NamedTextColor.GRAY, headerResultCount, pageNum) - .append(text(" (").append(headerResultCount).append(text(") » ")).append(pageNum)); + Component header = translatable( + "moderation.reports.header", NamedTextColor.GRAY, headerResultCount, pageNum) + .append(text(" (").append(headerResultCount).append(text(") » ")).append(pageNum)); Component formattedHeader = TextFormatter.horizontalLineHeading(audience.getSender(), header, NamedTextColor.DARK_GRAY); @@ -132,23 +128,19 @@ public Component format(Report data, int index) { Component reporterName = getReportFormatName(data.getSenderId()).join(); Component reportedName = getReportFormatName(data.getTargetId()).join(); - Component serverName = - text("Server ", NamedTextColor.GRAY) - .append(text(": ", NamedTextColor.DARK_GRAY)) - .append(text(data.getServer(), NamedTextColor.AQUA)); + Component serverName = text("Server ", NamedTextColor.GRAY) + .append(text(": ", NamedTextColor.DARK_GRAY)) + .append(text(data.getServer(), NamedTextColor.AQUA)); - TextComponent.Builder reporter = - text() - .append( - translatable("moderation.reports.hover", NamedTextColor.GRAY, reporterName)); + TextComponent.Builder reporter = text() + .append(translatable("moderation.reports.hover", NamedTextColor.GRAY, reporterName)); if (!data.getServer().equalsIgnoreCase(Community.get().getServerConfig().getServerId())) { reporter.append(newline()).append(serverName); } - Component timeAgo = - TemporalComponent.relativePastApproximate(data.getTime()) - .color(NamedTextColor.DARK_GREEN); + Component timeAgo = TemporalComponent.relativePastApproximate(data.getTime()) + .color(NamedTextColor.DARK_GREEN); return text() .append(timeAgo.hoverEvent(HoverEvent.showText(reporter.build()))) @@ -171,9 +163,7 @@ private CompletableFuture getReportFormatName(UUID id) { return usernames .getStoredUsername(id) .thenApplyAsync( - name -> { - return PlayerComponent.player(Bukkit.getPlayer(id), name, NameStyle.FANCY); - }); + name -> PlayerComponent.player(Bukkit.getPlayer(id), name, NameStyle.FANCY)); } private void checkEnabled() { diff --git a/core/src/main/java/dev/pgm/community/assistance/feature/types/AssistanceFeatureCore.java b/core/src/main/java/dev/pgm/community/assistance/feature/types/AssistanceFeatureCore.java index aeca843b..0da4b66e 100644 --- a/core/src/main/java/dev/pgm/community/assistance/feature/types/AssistanceFeatureCore.java +++ b/core/src/main/java/dev/pgm/community/assistance/feature/types/AssistanceFeatureCore.java @@ -47,7 +47,7 @@ import org.bukkit.configuration.Configuration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.bukkit.BukkitUtils; import tc.oc.pgm.util.named.NameStyle; @@ -110,7 +110,7 @@ private boolean isPersistent() { @Override public boolean canRequest(UUID uuid) { - return isCooldownEnabled() ? cooldown.getIfPresent(uuid) == null : true; + return !isCooldownEnabled() || cooldown.getIfPresent(uuid) == null; } @Override @@ -346,9 +346,9 @@ public void onPunishment(PlayerPunishmentEvent event) { .getReporyNotifyTime() .minus(Duration.between(r.getTime(), Instant.now())) .isNegative()) - .collect(Collectors.toList()); + .toList(); Set reporters = - relatedReports.stream().map(r -> r.getSenderId()).collect(Collectors.toSet()); + relatedReports.stream().map(AssistanceRequest::getSenderId).collect(Collectors.toSet()); for (UUID reporterId : reporters) { Player onlineReporter = Bukkit.getPlayer(reporterId); if (onlineReporter != null) { diff --git a/core/src/main/java/dev/pgm/community/assistance/menu/ReportCategoryMenu.java b/core/src/main/java/dev/pgm/community/assistance/menu/ReportCategoryMenu.java index 51ae13de..3b331731 100644 --- a/core/src/main/java/dev/pgm/community/assistance/menu/ReportCategoryMenu.java +++ b/core/src/main/java/dev/pgm/community/assistance/menu/ReportCategoryMenu.java @@ -19,9 +19,9 @@ public class ReportCategoryMenu extends CommunityInventoryProvider { - private InventoryManager manager; - private AssistanceFeature assistance; - private Player target; + private final InventoryManager manager; + private final AssistanceFeature assistance; + private final Player target; public ReportCategoryMenu( InventoryManager manager, @@ -47,9 +47,7 @@ private void openReasonMenu(Player player, Player target, ReportCategory categor @Override public Consumer getClickAction( ReportCategory category, Player viewer, InventoryContents contents) { - return e -> { - openReasonMenu(viewer, target, category); - }; + return e -> openReasonMenu(viewer, target, category); } @Override diff --git a/core/src/main/java/dev/pgm/community/assistance/menu/ReportReasonsMenu.java b/core/src/main/java/dev/pgm/community/assistance/menu/ReportReasonsMenu.java index 922b168b..6570aeed 100644 --- a/core/src/main/java/dev/pgm/community/assistance/menu/ReportReasonsMenu.java +++ b/core/src/main/java/dev/pgm/community/assistance/menu/ReportReasonsMenu.java @@ -15,9 +15,9 @@ public class ReportReasonsMenu extends CommunityInventoryProvider { - private AssistanceFeature feature; - private ReportCategory category; - private Player target; + private final AssistanceFeature feature; + private final ReportCategory category; + private final Player target; public ReportReasonsMenu(AssistanceFeature feature, Player target, ReportCategory category) { super(category.getReasons()); diff --git a/core/src/main/java/dev/pgm/community/assistance/services/AssistanceQuery.java b/core/src/main/java/dev/pgm/community/assistance/services/AssistanceQuery.java index ec671820..4cd1eaff 100644 --- a/core/src/main/java/dev/pgm/community/assistance/services/AssistanceQuery.java +++ b/core/src/main/java/dev/pgm/community/assistance/services/AssistanceQuery.java @@ -2,18 +2,16 @@ public interface AssistanceQuery { - static final String TABLE_NAME = "reports"; - static final String TABLE_FIELDS = - "(id VARCHAR(36) PRIMARY KEY, " - + "sender VARCHAR(36), " - + "reported VARCHAR(36), " - + "reason VARCHAR(255), " - + "time LONG, " - + "server VARCHAR(255))"; - static final String INSERT_REPORT_QUERY = - "INSERT INTO " - + TABLE_NAME - + "(id, sender, reported, reason, time, server) VALUES (?, ?, ?, ?, ?, ?)"; - static final String SELECT_REPORT_QUERY = + String TABLE_NAME = "reports"; + String TABLE_FIELDS = "(id VARCHAR(36) PRIMARY KEY, " + + "sender VARCHAR(36), " + + "reported VARCHAR(36), " + + "reason VARCHAR(255), " + + "time LONG, " + + "server VARCHAR(255))"; + String INSERT_REPORT_QUERY = "INSERT INTO " + + TABLE_NAME + + "(id, sender, reported, reason, time, server) VALUES (?, ?, ?, ?, ?, ?)"; + String SELECT_REPORT_QUERY = "SELECT id, sender, reason, time FROM " + TABLE_NAME + " WHERE reported = ?"; } diff --git a/core/src/main/java/dev/pgm/community/assistance/services/SQLAssistanceService.java b/core/src/main/java/dev/pgm/community/assistance/services/SQLAssistanceService.java index 8d1eb1eb..5f918516 100644 --- a/core/src/main/java/dev/pgm/community/assistance/services/SQLAssistanceService.java +++ b/core/src/main/java/dev/pgm/community/assistance/services/SQLAssistanceService.java @@ -15,18 +15,12 @@ public class SQLAssistanceService extends SQLFeatureBase implements AssistanceQuery { - private LoadingCache cachedReports; + private final LoadingCache cachedReports; public SQLAssistanceService() { super(TABLE_NAME, TABLE_FIELDS); - this.cachedReports = CacheBuilder.newBuilder() - .maximumSize(1000) - .build(new CacheLoader() { - @Override - public PlayerReports load(UUID key) throws Exception { - return new PlayerReports(key); - } - }); + this.cachedReports = + CacheBuilder.newBuilder().maximumSize(1000).build(CacheLoader.from(PlayerReports::new)); } @Override @@ -83,7 +77,7 @@ public CompletableFuture query(String target) { return CompletableFuture.completedFuture(null); // Noop atm } - private class PlayerReports { + private static class PlayerReports { private final UUID playerId; private final List reports; private boolean loaded; diff --git a/core/src/main/java/dev/pgm/community/chat/management/ChatManagementFeature.java b/core/src/main/java/dev/pgm/community/chat/management/ChatManagementFeature.java index 9cd7f1f4..5efabd23 100644 --- a/core/src/main/java/dev/pgm/community/chat/management/ChatManagementFeature.java +++ b/core/src/main/java/dev/pgm/community/chat/management/ChatManagementFeature.java @@ -34,16 +34,14 @@ public class ChatManagementFeature extends FeatureBase { private boolean lockdown; private boolean slowmode; - private Cache lastMessageCache; + private final Cache lastMessageCache; public ChatManagementFeature(Configuration config, Logger logger) { super(new ChatManagementConfig(config), logger, "Chat Management"); - this.lastMessageCache = - CacheBuilder.newBuilder() - .expireAfterWrite( - getChatConfig().getRepeatedMessagesExpireDuration().toMillis(), - TimeUnit.MILLISECONDS) - .build(); + this.lastMessageCache = CacheBuilder.newBuilder() + .expireAfterWrite( + getChatConfig().getRepeatedMessagesExpireDuration().toMillis(), TimeUnit.MILLISECONDS) + .build(); if (getConfig().isEnabled()) { enable(); } @@ -70,17 +68,14 @@ public void toggleSlowmode(CommandSender sender) { } private void broadcastModeChange(Component modeName, Component hover, boolean enabled) { - Component message = - text() - .append(modeName) - .append(text(" has been ")) - .append( - enabled - ? text("enabled", NamedTextColor.GREEN) - : text("disabled", NamedTextColor.RED)) - .color(NamedTextColor.GRAY) - .hoverEvent(HoverEvent.showText(hover)) - .build(); + Component message = text() + .append(modeName) + .append(text(" has been ")) + .append( + enabled ? text("enabled", NamedTextColor.GREEN) : text("disabled", NamedTextColor.RED)) + .color(NamedTextColor.GRAY) + .hoverEvent(HoverEvent.showText(hover)) + .build(); BroadcastUtils.sendGlobalWarning(message); } @@ -104,7 +99,7 @@ private Component getSlowmodeHover() { Component builder = text("Slowmode has been "); if (isSlowmode()) { - builder + builder = builder .append(text("enabled", NamedTextColor.GREEN)) .append(text(" in order to reduce spam.")) .append(newline()) @@ -113,7 +108,7 @@ private Component getSlowmodeHover() { .append(text(getChatConfig().getSlowmodeSpeed(), NamedTextColor.YELLOW)) .append(formatSeconds(getChatConfig().getSlowmodeSpeed())); } else { - builder + builder = builder .append(text("disabled", NamedTextColor.RED)) .append(text(". There is no longer a chat speed restriction in place")); } @@ -166,12 +161,11 @@ public void onPlayerChat(AsyncPlayerChatEvent event) { if (timeSince.getSeconds() < getChatConfig().getSlowmodeSpeed()) { long seconds = (getChatConfig().getSlowmodeSpeed() - timeSince.getSeconds()); - Component cooldownMsg = - text("Please wait ") - .append(text(seconds, NamedTextColor.RED, TextDecoration.BOLD)) - .append(formatSeconds(seconds)) - .append(text(" before sending another message")) - .color(NamedTextColor.GRAY); + Component cooldownMsg = text("Please wait ") + .append(text(seconds, NamedTextColor.RED, TextDecoration.BOLD)) + .append(formatSeconds(seconds)) + .append(text(" before sending another message")) + .color(NamedTextColor.GRAY); viewer.sendWarning(cooldownMsg); event.setCancelled(true); @@ -208,15 +202,7 @@ public void onPlayerJoin(PlayerJoinEvent event) { private void sendDelayedMessage(final Audience viewer, final Component message) { Bukkit.getScheduler() - .scheduleSyncDelayedTask( - Community.get(), - new Runnable() { - @Override - public void run() { - viewer.sendWarning(message); - } - }, - 30L); + .scheduleSyncDelayedTask(Community.get(), () -> viewer.sendWarning(message), 30L); } private Component formatSeconds(long seconds) { diff --git a/core/src/main/java/dev/pgm/community/chat/network/NetworkChatFeature.java b/core/src/main/java/dev/pgm/community/chat/network/NetworkChatFeature.java index 8e5d765e..4f67bb8d 100644 --- a/core/src/main/java/dev/pgm/community/chat/network/NetworkChatFeature.java +++ b/core/src/main/java/dev/pgm/community/chat/network/NetworkChatFeature.java @@ -23,7 +23,7 @@ public class NetworkChatFeature extends FeatureBase { public static final String ADMIN_CHANNEL = "admin"; - private NetworkFeature network; + private final NetworkFeature network; public NetworkChatFeature(Configuration config, Logger logger, NetworkFeature network) { super(new NetworkChatConfig(config), logger, "Network Chat (PGM)"); diff --git a/core/src/main/java/dev/pgm/community/chat/network/NetworkChatMessage.java b/core/src/main/java/dev/pgm/community/chat/network/NetworkChatMessage.java index dab098ab..ac97ed5b 100644 --- a/core/src/main/java/dev/pgm/community/chat/network/NetworkChatMessage.java +++ b/core/src/main/java/dev/pgm/community/chat/network/NetworkChatMessage.java @@ -12,10 +12,10 @@ public class NetworkChatMessage { - private String message; - private String sender; - private String server; - private String channel; + private final String message; + private final String sender; + private final String server; + private final String channel; public NetworkChatMessage(ChannelMessageEvent event, String server) { this.message = toMinecraftGson(text(event.getMessage())); diff --git a/core/src/main/java/dev/pgm/community/commands/ContainerCommand.java b/core/src/main/java/dev/pgm/community/commands/ContainerCommand.java index c2d7be6e..a1cf125f 100644 --- a/core/src/main/java/dev/pgm/community/commands/ContainerCommand.java +++ b/core/src/main/java/dev/pgm/community/commands/ContainerCommand.java @@ -30,8 +30,8 @@ public class ContainerCommand extends CommunityCommand implements Listener { - private Set clickingPlayers = Sets.newHashSet(); - private Set editingPlayers = Sets.newHashSet(); + private final Set clickingPlayers = Sets.newHashSet(); + private final Set editingPlayers = Sets.newHashSet(); private static final Component EXIT_MESSAGE = text("Exited container editing mode", NamedTextColor.GRAY); @@ -63,16 +63,10 @@ private boolean canOpen(Block block) { } private boolean isTypeAllowed(Material type) { - switch (type) { - case CHEST: - case ENDER_CHEST: - case FURNACE: - case DISPENSER: - case BEACON: - return true; - default: - return false; - } + return switch (type) { + case CHEST, ENDER_CHEST, FURNACE, DISPENSER, BEACON -> true; + default -> false; + }; } private Component formatCoords(Block block, NamedTextColor coordColor) { @@ -100,10 +94,9 @@ public void onContainerClick(PlayerInteractEvent event) { if (isChoosing(player) && canOpen(block) && event.getAction() == Action.LEFT_CLICK_BLOCK) { event.setCancelled(true); - viewer.sendMessage( - text() - .append(text("Now opening container at ", NamedTextColor.GRAY)) - .append(formatCoords(block, NamedTextColor.GREEN))); + viewer.sendMessage(text() + .append(text("Now opening container at ", NamedTextColor.GRAY)) + .append(formatCoords(block, NamedTextColor.GREEN))); InventoryHolder container = (InventoryHolder) block.getState(); editingPlayers.add(player.getUniqueId()); @@ -112,20 +105,18 @@ public void onContainerClick(PlayerInteractEvent event) { } } - @EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR) public void onInventoryClickEvent(InventoryClickEvent event) { - if (event.getWhoClicked() != null && event.getWhoClicked() instanceof Player) { - Player player = (Player) event.getWhoClicked(); + if (event.getWhoClicked() != null && event.getWhoClicked() instanceof Player player) { if (editingPlayers.contains(player.getUniqueId())) { event.setCancelled(false); } } } - @EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR) public void onInventoryClose(InventoryCloseEvent event) { - if (event.getPlayer() != null && event.getPlayer() instanceof Player) { - Player player = (Player) event.getPlayer(); + if (event.getPlayer() != null && event.getPlayer() instanceof Player player) { if (editingPlayers.contains(player.getUniqueId())) { editingPlayers.remove(player.getUniqueId()); Audience.get(player).sendWarning(EXIT_MESSAGE); diff --git a/core/src/main/java/dev/pgm/community/commands/FlightCommand.java b/core/src/main/java/dev/pgm/community/commands/FlightCommand.java index e08f8e7d..0fcd2bf9 100644 --- a/core/src/main/java/dev/pgm/community/commands/FlightCommand.java +++ b/core/src/main/java/dev/pgm/community/commands/FlightCommand.java @@ -24,14 +24,13 @@ public void fly(CommandAudience sender, @Argument("target") TargetPlayer target) toggleFlight(sender.getPlayer()); } else { PlayerSelection selection = getPlayers(sender, target.getIdentifier()); - if (!selection.getPlayers().isEmpty()) { - selection.getPlayers().forEach(this::toggleFlight); - sender.sendMessage( - text() - .append(text("Flight has been toggled for ")) - .append(selection.getText()) - .color(NamedTextColor.GRAY) - .build()); + if (!selection.players().isEmpty()) { + selection.players().forEach(this::toggleFlight); + sender.sendMessage(text() + .append(text("Flight has been toggled for ")) + .append(selection.getText()) + .color(NamedTextColor.GRAY) + .build()); } else { selection.sendNoPlayerComponent(sender); } @@ -43,15 +42,13 @@ public void fly(CommandAudience sender, @Argument("target") TargetPlayer target) @Permission(CommunityPermissions.FLIGHT_SPEED) public void flySpeed(CommandAudience audience, Player player, @Argument("speed") Float speed) { if (speed == null) { - audience.sendMessage( - text("Your flight speed is ", NamedTextColor.GRAY) - .append(text(player.getFlySpeed() * 100, NamedTextColor.GREEN))); + audience.sendMessage(text("Your flight speed is ", NamedTextColor.GRAY) + .append(text(player.getFlySpeed() * 100, NamedTextColor.GREEN))); return; } player.setFlySpeed(Math.abs(Math.min(speed, 10) / 10)); - audience.sendMessage( - text("Flight speed set to ", NamedTextColor.GRAY) - .append(text(player.getFlySpeed() * 100, NamedTextColor.GREEN))); + audience.sendMessage(text("Flight speed set to ", NamedTextColor.GRAY) + .append(text(player.getFlySpeed() * 100, NamedTextColor.GREEN))); } private void toggleFlight(Player player) { @@ -59,11 +56,9 @@ private void toggleFlight(Player player) { player.setAllowFlight(!fly); player.setFlying(!fly); Audience.get(player) - .sendMessage( - text("Toggled flying mode ", NamedTextColor.GRAY) - .append( - text( - player.isFlying() ? "On" : "Off", - player.isFlying() ? NamedTextColor.GREEN : NamedTextColor.RED))); + .sendMessage(text("Toggled flying mode ", NamedTextColor.GRAY) + .append(text( + player.isFlying() ? "On" : "Off", + player.isFlying() ? NamedTextColor.GREEN : NamedTextColor.RED))); } } diff --git a/core/src/main/java/dev/pgm/community/commands/GamemodeCommand.java b/core/src/main/java/dev/pgm/community/commands/GamemodeCommand.java index bfb2d7ce..e4911c1f 100644 --- a/core/src/main/java/dev/pgm/community/commands/GamemodeCommand.java +++ b/core/src/main/java/dev/pgm/community/commands/GamemodeCommand.java @@ -30,33 +30,30 @@ public void gamemode( // /gm if (gamemode == null && target == null) { // Send current gamemode - viewer.sendMessage( - text() - .append(text("Your current gamemode is ", NamedTextColor.GRAY)) - .append(getGamemodeName(player.getGameMode())) - .build()); + viewer.sendMessage(text() + .append(text("Your current gamemode is ", NamedTextColor.GRAY)) + .append(getGamemodeName(player.getGameMode())) + .build()); } else if (gamemode != null && target == null && !everyone) { // /gm player.setGameMode(gamemode); - viewer.sendMessage( - text() - .append(text("Set your gamemode to ", NamedTextColor.GRAY)) - .append(getGamemodeName(player.getGameMode())) - .build()); + viewer.sendMessage(text() + .append(text("Set your gamemode to ", NamedTextColor.GRAY)) + .append(getGamemodeName(player.getGameMode())) + .build()); } else { // /gm PlayerSelection selection = getPlayers(viewer, everyone ? "*" : target.getName()); - if (!selection.getPlayers().isEmpty()) { - selection.getPlayers().forEach(pl -> pl.setGameMode(gamemode)); - viewer.sendMessage( - text() - .append(text("Gamemode has been set to ")) - .append(getGamemodeName(gamemode)) - .append(text(" for ")) - .append(selection.getText()) - .color(NamedTextColor.GRAY) - .build()); + if (!selection.players().isEmpty()) { + selection.players().forEach(pl -> pl.setGameMode(gamemode)); + viewer.sendMessage(text() + .append(text("Gamemode has been set to ")) + .append(getGamemodeName(gamemode)) + .append(text(" for ")) + .append(selection.getText()) + .color(NamedTextColor.GRAY) + .build()); } else { selection.sendNoPlayerComponent(viewer); } diff --git a/core/src/main/java/dev/pgm/community/commands/SudoCommand.java b/core/src/main/java/dev/pgm/community/commands/SudoCommand.java index 3d08bda2..dc8c5c72 100644 --- a/core/src/main/java/dev/pgm/community/commands/SudoCommand.java +++ b/core/src/main/java/dev/pgm/community/commands/SudoCommand.java @@ -27,18 +27,17 @@ public void sudo( } PlayerSelection selection = getPlayers(sender, targets); - if (!selection.getPlayers().isEmpty()) { + if (!selection.players().isEmpty()) { final String targetCommand = command.startsWith("/") ? command.substring(1) : command; - selection.getPlayers().forEach(player -> player.performCommand(targetCommand)); - sender.sendMessage( - text() - .append(text("Forcing ")) - .append(selection.getText()) - .append(text(" to run ")) - .append(text("/", NamedTextColor.AQUA)) - .append(text(targetCommand, NamedTextColor.AQUA)) - .color(NamedTextColor.GRAY) - .build()); + selection.players().forEach(player -> player.performCommand(targetCommand)); + sender.sendMessage(text() + .append(text("Forcing ")) + .append(selection.getText()) + .append(text(" to run ")) + .append(text("/", NamedTextColor.AQUA)) + .append(text(targetCommand, NamedTextColor.AQUA)) + .color(NamedTextColor.GRAY) + .build()); } else { selection.sendNoPlayerComponent(sender); } diff --git a/core/src/main/java/dev/pgm/community/commands/providers/GameModeParser.java b/core/src/main/java/dev/pgm/community/commands/providers/GameModeParser.java index 7006662c..f12352f3 100644 --- a/core/src/main/java/dev/pgm/community/commands/providers/GameModeParser.java +++ b/core/src/main/java/dev/pgm/community/commands/providers/GameModeParser.java @@ -5,6 +5,7 @@ import org.apache.commons.lang.StringUtils; import org.bukkit.GameMode; import org.bukkit.command.CommandSender; +import org.jspecify.annotations.NonNull; import tc.oc.pgm.command.parsers.EnumParser; import tc.oc.pgm.lib.org.incendo.cloud.context.CommandContext; import tc.oc.pgm.lib.org.incendo.cloud.context.CommandInput; @@ -32,7 +33,8 @@ protected GameMode bestMatch(CommandContext context, String input } @Override - public List stringSuggestions(CommandContext context, CommandInput input) { + public @NonNull List stringSuggestions( + @NonNull CommandContext context, @NonNull CommandInput input) { int totalGamemodes = GameMode.values().length; List suggestions = super.stringSuggestions(context, input); List indexedSuggestions = new ArrayList<>(totalGamemodes * 2); diff --git a/core/src/main/java/dev/pgm/community/commands/providers/TargetPlayerParser.java b/core/src/main/java/dev/pgm/community/commands/providers/TargetPlayerParser.java index 0cbe5eb1..247d4e60 100644 --- a/core/src/main/java/dev/pgm/community/commands/providers/TargetPlayerParser.java +++ b/core/src/main/java/dev/pgm/community/commands/providers/TargetPlayerParser.java @@ -10,7 +10,7 @@ import java.util.List; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; import tc.oc.pgm.lib.org.incendo.cloud.context.CommandContext; import tc.oc.pgm.lib.org.incendo.cloud.context.CommandInput; import tc.oc.pgm.lib.org.incendo.cloud.parser.ArgumentParseResult; @@ -24,8 +24,8 @@ public final class TargetPlayerParser BlockingSuggestionProvider.Strings { @Override - public @NotNull ArgumentParseResult<@NotNull TargetPlayer> parse( - @NotNull CommandContext<@NotNull CommandSender> context, @NotNull CommandInput inputQueue) { + public @NonNull ArgumentParseResult<@NonNull TargetPlayer> parse( + @NonNull CommandContext<@NonNull CommandSender> context, @NonNull CommandInput inputQueue) { final String input = inputQueue.peekString(); CommandSender sender = context.sender(); @@ -33,7 +33,7 @@ public final class TargetPlayerParser if (input.equals(CURRENT)) { if (!(context.sender() instanceof Player)) return failure(playerOnly()); - player = (TargetPlayer) new TargetPlayer(sender, context.sender().getName()); + player = new TargetPlayer(sender, context.sender().getName()); } else { try { player = new TargetPlayer(sender, input); @@ -52,8 +52,8 @@ public final class TargetPlayerParser } @Override - public @NotNull List<@NotNull String> stringSuggestions( - @NotNull CommandContext context, @NotNull CommandInput input) { + public @NonNull List<@NonNull String> stringSuggestions( + @NonNull CommandContext context, @NonNull CommandInput input) { CommandSender sender = context.sender(); return Players.getPlayerNames(sender, input.readString()); diff --git a/core/src/main/java/dev/pgm/community/events/UserProfileLoadEvent.java b/core/src/main/java/dev/pgm/community/events/UserProfileLoadEvent.java index 47dc2df9..cfddb898 100644 --- a/core/src/main/java/dev/pgm/community/events/UserProfileLoadEvent.java +++ b/core/src/main/java/dev/pgm/community/events/UserProfileLoadEvent.java @@ -4,7 +4,7 @@ public class UserProfileLoadEvent extends CommunityEvent { - private UserProfile profile; + private final UserProfile profile; public UserProfileLoadEvent(UserProfile profile) { this.profile = profile; diff --git a/core/src/main/java/dev/pgm/community/freeze/FreezeCommand.java b/core/src/main/java/dev/pgm/community/freeze/FreezeCommand.java index 01e4f8f5..93b77464 100644 --- a/core/src/main/java/dev/pgm/community/freeze/FreezeCommand.java +++ b/core/src/main/java/dev/pgm/community/freeze/FreezeCommand.java @@ -3,6 +3,7 @@ import static net.kyori.adventure.text.Component.join; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.translatable; +import static net.kyori.adventure.text.JoinConfiguration.separator; import dev.pgm.community.Community; import dev.pgm.community.CommunityCommand; @@ -21,7 +22,7 @@ public class FreezeCommand extends CommunityCommand { - private FreezeFeature freeze; + private final FreezeFeature freeze; public FreezeCommand() { this.freeze = Community.get().getFeatures().getFreeze(); @@ -46,12 +47,11 @@ public void sendFrozenList(CommandAudience sender) { // Online Players if (freeze.getOnlineCount() > 0) { - Component names = - join( - text(", ", NamedTextColor.GRAY), - freeze.getFrozenPlayers().stream() - .map(p -> PlayerComponent.player(p, NameStyle.FANCY)) - .collect(Collectors.toList())); + Component names = join( + separator(text(", ", NamedTextColor.GRAY)), + freeze.getFrozenPlayers().stream() + .map(p -> PlayerComponent.player(p, NameStyle.FANCY)) + .collect(Collectors.toList())); sender.sendMessage( formatFrozenList("moderation.freeze.frozenList.online", freeze.getOnlineCount(), names)); @@ -60,9 +60,8 @@ public void sendFrozenList(CommandAudience sender) { // Offline Players if (freeze.getOfflineCount() > 0) { Component names = text(freeze.getOfflineFrozenNames()); - sender.sendMessage( - formatFrozenList( - "moderation.freeze.frozenList.offline", freeze.getOfflineCount(), names)); + sender.sendMessage(formatFrozenList( + "moderation.freeze.frozenList.offline", freeze.getOfflineCount(), names)); } } diff --git a/core/src/main/java/dev/pgm/community/freeze/FreezeFeature.java b/core/src/main/java/dev/pgm/community/freeze/FreezeFeature.java index 724bad43..3479fe7c 100644 --- a/core/src/main/java/dev/pgm/community/freeze/FreezeFeature.java +++ b/core/src/main/java/dev/pgm/community/freeze/FreezeFeature.java @@ -101,15 +101,12 @@ public void setFrozen(CommandAudience sender, Player freezee, boolean frozen, bo public static ItemStack getFreezeTool(CommandSender viewer) { ItemStack stack = new ItemStack(TOOL_MATERIAL); ItemMeta meta = stack.getItemMeta(); - meta.setDisplayName( - ChatColor.WHITE - + ChatColor.BOLD.toString() - + TextTranslations.translate("moderation.freeze.itemName", viewer)); + meta.setDisplayName(ChatColor.WHITE + + ChatColor.BOLD.toString() + + TextTranslations.translate("moderation.freeze.itemName", viewer)); meta.addItemFlags(ItemFlag.values()); - meta.setLore( - Collections.singletonList( - ChatColor.GRAY - + TextTranslations.translate("moderation.freeze.itemDescription", viewer))); + meta.setLore(Collections.singletonList( + ChatColor.GRAY + TextTranslations.translate("moderation.freeze.itemDescription", viewer))); stack.setItemMeta(meta); return stack; } @@ -153,11 +150,7 @@ public void onObserverToolFreeze(final ObserverInteractEvent event) { public void onPlayerCommand(final PlayerCommandPreprocessEvent event) { if (freeze.isFrozen(event.getPlayer()) && !event.getPlayer().hasPermission(CommunityPermissions.FREEZE)) { - boolean allow = - ALLOWED_CMDS.stream() - .filter(cmd -> event.getMessage().startsWith(cmd)) - .findAny() - .isPresent(); + boolean allow = ALLOWED_CMDS.stream().anyMatch(cmd -> event.getMessage().startsWith(cmd)); if (!allow) { // Don't allow commands except for those related to chat. diff --git a/core/src/main/java/dev/pgm/community/freeze/FreezeManager.java b/core/src/main/java/dev/pgm/community/freeze/FreezeManager.java index 5c78c2a8..fedd64ed 100644 --- a/core/src/main/java/dev/pgm/community/freeze/FreezeManager.java +++ b/core/src/main/java/dev/pgm/community/freeze/FreezeManager.java @@ -6,6 +6,7 @@ import static net.kyori.adventure.text.Component.space; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.translatable; +import static net.kyori.adventure.title.Title.Times.times; import static net.kyori.adventure.title.Title.title; import com.google.common.cache.Cache; @@ -14,6 +15,7 @@ import dev.pgm.community.CommunityPermissions; import dev.pgm.community.utils.BroadcastUtils; import dev.pgm.community.utils.CommandAudience; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -24,7 +26,6 @@ import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.title.Title.Times; import net.kyori.adventure.util.Ticks; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -52,7 +53,7 @@ public class FreezeManager { CacheBuilder.newBuilder().expireAfterWrite(3, TimeUnit.MINUTES).build(); public FreezeManager() { - this.frozenPlayers = new OnlinePlayerMapAdapter(Community.get()); + this.frozenPlayers = new OnlinePlayerMapAdapter<>(Community.get()); } public void cachePlayer(Player player) { @@ -82,7 +83,7 @@ public int getOnlineCount() { } public List getFrozenPlayers() { - return frozenPlayers.values().stream().collect(Collectors.toList()); + return new ArrayList<>(frozenPlayers.values()); } public boolean isFrozen(Entity player) { @@ -140,7 +141,7 @@ private void freeze(Player freezee, Component senderName, boolean silent) { .showTitle(title( empty(), freezeTitle.build(), - Times.of(Ticks.duration(5), Ticks.duration(9999), Ticks.duration(5)))); + times(Ticks.duration(5), Ticks.duration(9999), Ticks.duration(5)))); } Audience.get(freezee).playSound(FREEZE_SOUND); @@ -154,14 +155,13 @@ private void thaw(Player freezee, Component senderName, boolean silent) { Component thawed = translatable("moderation.freeze.unfrozen"); Component by = translatable("misc.by", senderName); - Component thawedTitle = thawed; if (!silent) { - thawedTitle.append(space()).append(by); + thawed = thawed.append(space()).append(by); } freezee.resetTitle(); Audience.get(freezee).playSound(THAW_SOUND); - Audience.get(freezee).sendMessage(thawedTitle.color(NamedTextColor.GREEN)); + Audience.get(freezee).sendMessage(thawed.color(NamedTextColor.GREEN)); BroadcastUtils.sendAdminChatMessage( createInteractiveBroadcast(senderName, freezee, false), CommunityPermissions.FREEZE); diff --git a/core/src/main/java/dev/pgm/community/friends/FriendRequestStatus.java b/core/src/main/java/dev/pgm/community/friends/FriendRequestStatus.java index 4011f9da..dff14bb3 100644 --- a/core/src/main/java/dev/pgm/community/friends/FriendRequestStatus.java +++ b/core/src/main/java/dev/pgm/community/friends/FriendRequestStatus.java @@ -4,5 +4,5 @@ public enum FriendRequestStatus { ACCEPTED_EXISTING, // The target had already sent a friend request, so request was auto accepted PENDING, // Target and sender have no prior requests - EXISTING; // The sender has already sent a friend request + EXISTING // The sender has already sent a friend request } diff --git a/core/src/main/java/dev/pgm/community/friends/Friendship.java b/core/src/main/java/dev/pgm/community/friends/Friendship.java index f63ce2a6..43b782ba 100644 --- a/core/src/main/java/dev/pgm/community/friends/Friendship.java +++ b/core/src/main/java/dev/pgm/community/friends/Friendship.java @@ -5,12 +5,12 @@ public class Friendship implements Comparable { - private UUID friendshipId; // ID of friendship + private final UUID friendshipId; // ID of friendship - private UUID requesterId; // UUID of player who requested friendship - private UUID requestedId; // UUID of target + private final UUID requesterId; // UUID of player who requested friendship + private final UUID requestedId; // UUID of target - private Instant requestDate; // Date the original request was sent + private final Instant requestDate; // Date the original request was sent private Instant requestUpdated; // Date request status was last updated @@ -117,7 +117,7 @@ public void setStatus(FriendshipStatus status) { /** * Sets the date in which the friendship status was last updated * - * @param time + * @param now */ public void setLastUpdated(Instant now) { this.requestUpdated = now; @@ -156,16 +156,15 @@ public UUID getOtherPlayer(UUID playerId) { return getRequesterId().equals(playerId) ? getRequestedId() : getRequesterId(); } - public static enum FriendshipStatus { + public enum FriendshipStatus { PENDING, // No decision has been more ACCEPTED, // Requested has accepted - REJECTED; // Requested has denied + REJECTED // Requested has denied } @Override public boolean equals(Object other) { - if (!(other instanceof Friendship)) return false; - Friendship otherFriendship = (Friendship) other; + if (!(other instanceof Friendship otherFriendship)) return false; return otherFriendship.getFriendshipId().equals(getFriendshipId()); } diff --git a/core/src/main/java/dev/pgm/community/friends/commands/FriendshipCommand.java b/core/src/main/java/dev/pgm/community/friends/commands/FriendshipCommand.java index c722844c..aa2c86bd 100644 --- a/core/src/main/java/dev/pgm/community/friends/commands/FriendshipCommand.java +++ b/core/src/main/java/dev/pgm/community/friends/commands/FriendshipCommand.java @@ -26,7 +26,13 @@ import dev.pgm.community.utils.VisibilityUtils; import java.time.Duration; import java.time.Instant; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import net.kyori.adventure.text.Component; @@ -63,9 +69,9 @@ public FriendshipCommand() { @Permission(CommunityPermissions.FRIENDSHIP) public void list( CommandAudience sender, Player player, @Argument("page") @Default("1") int page) { - friends.getFriends(sender.getPlayer().getUniqueId()).thenAcceptAsync(frs -> { - sendFriendList(sender, frs, page); - }); + friends + .getFriends(sender.getPlayer().getUniqueId()) + .thenAcceptAsync(frs -> sendFriendList(sender, frs, page)); } @Command("requests [page]") @@ -73,9 +79,9 @@ public void list( @Permission(CommunityPermissions.FRIENDSHIP) public void requests( CommandAudience sender, Player player, @Argument("page") @Default("1") int page) { - friends.getIncomingRequests(sender.getPlayer().getUniqueId()).thenAcceptAsync(requests -> { - sendRequestsList(sender, requests, page); - }); + friends + .getIncomingRequests(sender.getPlayer().getUniqueId()) + .thenAcceptAsync(requests -> sendRequestsList(sender, requests, page)); } @Command("add ") @@ -93,13 +99,12 @@ public void add(CommandAudience sender, Player player, @Argument("player") Targe sender.sendWarning(text("You have already sent a friend request to ") .append(fancyName) .color(NamedTextColor.GRAY)); - return; } else { fake.addRequest(fullName); sender.sendMessage( text("Friend request sent to ").append(fancyName).color(NamedTextColor.GRAY)); - return; } + return; } getTarget(target.getIdentifier(), users).thenAcceptAsync(storedId -> { @@ -111,42 +116,37 @@ public void add(CommandAudience sender, Player player, @Argument("player") Targe friends .addFriend(sender.getPlayer().getUniqueId(), storedId.get()) - .thenAcceptAsync(status -> { - users - .renderUsername(Optional.of(storedId.get()), NameStyle.FANCY) - .thenAcceptAsync(name -> { - switch (status) { - case ACCEPTED_EXISTING: - sender.sendMessage(text("You accepted ") - .append(name) - .append(text("'s friend request!")) - .color(NamedTextColor.GREEN)); - break; - case EXISTING: - if (friends - .areFriends(sender.getPlayer().getUniqueId(), storedId.get()) - .join()) { - sender.sendWarning( - text("You are already friends with ").append(name)); - } else { - sender.sendWarning(text("You have already sent a friend request to ") - .append(name) - .color(NamedTextColor.GRAY)); - } - break; - case PENDING: - sender.sendMessage(text("Friend request sent to ") + .thenAcceptAsync( + status -> users.renderUsername(storedId, NameStyle.FANCY).thenAcceptAsync(name -> { + switch (status) { + case ACCEPTED_EXISTING: + sender.sendMessage(text("You accepted ") + .append(name) + .append(text("'s friend request!")) + .color(NamedTextColor.GREEN)); + break; + case EXISTING: + if (friends + .areFriends(sender.getPlayer().getUniqueId(), storedId.get()) + .join()) { + sender.sendWarning(text("You are already friends with ").append(name)); + } else { + sender.sendWarning(text("You have already sent a friend request to ") .append(name) .color(NamedTextColor.GRAY)); - break; - default: - sender.sendWarning(text("Could not send a friend request to ") - .append(name) - .color(NamedTextColor.GRAY)); - break; - } - }); - }); + } + break; + case PENDING: + sender.sendMessage( + text("Friend request sent to ").append(name).color(NamedTextColor.GRAY)); + break; + default: + sender.sendWarning(text("Could not send a friend request to ") + .append(name) + .color(NamedTextColor.GRAY)); + break; + } + })); } else { sender.sendWarning(formatNotFoundComponent(target.getIdentifier())); } @@ -258,7 +258,6 @@ public void rejectRequest( .append(name) .append(text("'s friend request")) .color(NamedTextColor.GRAY)); - return; } else { sender.sendWarning(text("You don't have a pending friend request from ") .append(name) @@ -421,7 +420,7 @@ public Component formatEmpty() { private CompletableFuture renderOnlineStatus(UUID playerId, CommandAudience viewer) { boolean staff = viewer.getSender().hasPermission(CommunityPermissions.STAFF); - CompletableFuture future = new CompletableFuture(); + CompletableFuture future = new CompletableFuture<>(); users.findUserWithSession(playerId, !staff, (profile, session) -> { boolean online = !session.hasEnded(); boolean vanished = session.isDisguised(); @@ -455,18 +454,13 @@ private boolean canSee(Player player, CommandAudience viewer) { return true; } - private LoadingCache fakeRequests = CacheBuilder.newBuilder() + private final LoadingCache fakeRequests = CacheBuilder.newBuilder() .expireAfterAccess(3, TimeUnit.HOURS) - .build(new CacheLoader() { - @Override - public FakeRequests load(UUID key) throws Exception { - return new FakeRequests(); - } - }); + .build(CacheLoader.from(FakeRequests::new)); - private class FakeRequests { + private static class FakeRequests { - private Set nicknames = Sets.newHashSet(); + private final Set nicknames = Sets.newHashSet(); public boolean hasRequest(String nickname) { return nicknames.contains(nickname); diff --git a/core/src/main/java/dev/pgm/community/friends/feature/PGMFriendIntegration.java b/core/src/main/java/dev/pgm/community/friends/feature/PGMFriendIntegration.java index db2acb9a..239e2286 100644 --- a/core/src/main/java/dev/pgm/community/friends/feature/PGMFriendIntegration.java +++ b/core/src/main/java/dev/pgm/community/friends/feature/PGMFriendIntegration.java @@ -14,7 +14,7 @@ public class PGMFriendIntegration implements FriendIntegration { - private Map> friends; + private final Map> friends; public PGMFriendIntegration() { this.friends = Maps.newHashMap(); diff --git a/core/src/main/java/dev/pgm/community/friends/services/FriendshipQuery.java b/core/src/main/java/dev/pgm/community/friends/services/FriendshipQuery.java index 5f2f8b0c..36a348a8 100644 --- a/core/src/main/java/dev/pgm/community/friends/services/FriendshipQuery.java +++ b/core/src/main/java/dev/pgm/community/friends/services/FriendshipQuery.java @@ -2,23 +2,21 @@ public interface FriendshipQuery { - static final String TABLE_NAME = "friendships"; - static final String TABLE_FIELDS = - "(id VARCHAR(36) PRIMARY KEY, " - + "requester VARCHAR(36), " - + "requested VARCHAR(36), " - + "status VARCHAR(8), " - + "requestDate LONG, " - + "updateDate LONG)"; + String TABLE_NAME = "friendships"; + String TABLE_FIELDS = "(id VARCHAR(36) PRIMARY KEY, " + + "requester VARCHAR(36), " + + "requested VARCHAR(36), " + + "status VARCHAR(8), " + + "requestDate LONG, " + + "updateDate LONG)"; - static final String INSERT_FRIENDSHIP_QUERY = - "INSERT INTO " - + TABLE_NAME - + "(id, requester, requested, status, requestDate, updateDate) VALUES (?, ?, ?, ?, ?, ?)"; + String INSERT_FRIENDSHIP_QUERY = "INSERT INTO " + + TABLE_NAME + + "(id, requester, requested, status, requestDate, updateDate) VALUES (?, ?, ?, ?, ?, ?)"; - static final String SELECT_FRIENDSHIPS_QUERY = + String SELECT_FRIENDSHIPS_QUERY = "SELECT * from " + TABLE_NAME + " where (requester = ? OR requested = ?)"; - static final String UPDATE_FRIENDSHIP_QUERY = + String UPDATE_FRIENDSHIP_QUERY = "UPDATE " + TABLE_NAME + " SET status = ?, updateDate = ? WHERE id = ? "; } diff --git a/core/src/main/java/dev/pgm/community/friends/services/SQLFriendshipService.java b/core/src/main/java/dev/pgm/community/friends/services/SQLFriendshipService.java index 3f156f45..e4197080 100644 --- a/core/src/main/java/dev/pgm/community/friends/services/SQLFriendshipService.java +++ b/core/src/main/java/dev/pgm/community/friends/services/SQLFriendshipService.java @@ -18,17 +18,12 @@ public class SQLFriendshipService extends SQLFeatureBase implements FriendshipQuery { - private LoadingCache friendshipCache; + private final LoadingCache friendshipCache; public SQLFriendshipService() { super(TABLE_NAME, TABLE_FIELDS); - this.friendshipCache = CacheBuilder.newBuilder() - .build(new CacheLoader() { - @Override - public PlayerFriendships load(UUID key) throws Exception { - return new PlayerFriendships(key); - } - }); + this.friendshipCache = + CacheBuilder.newBuilder().build(CacheLoader.from(PlayerFriendships::new)); } @Override @@ -131,9 +126,9 @@ public CompletableFuture query(String target) { return null; // Use queryList } - private class PlayerFriendships { - private UUID playerId; - private Set friendships; + private static class PlayerFriendships { + private final UUID playerId; + private final Set friendships; private boolean loaded; public PlayerFriendships(UUID playerId) { diff --git a/core/src/main/java/dev/pgm/community/history/MatchHistoryEntry.java b/core/src/main/java/dev/pgm/community/history/MatchHistoryEntry.java index 0df72329..96a76d44 100644 --- a/core/src/main/java/dev/pgm/community/history/MatchHistoryEntry.java +++ b/core/src/main/java/dev/pgm/community/history/MatchHistoryEntry.java @@ -26,7 +26,7 @@ public class MatchHistoryEntry implements Comparable { private final Duration finalDuration; private final Instant endTime; - private List staff; + private final List staff; public MatchHistoryEntry(Match match) { this.matchID = match.getId(); diff --git a/core/src/main/java/dev/pgm/community/info/InfoCommandData.java b/core/src/main/java/dev/pgm/community/info/InfoCommandData.java index 60a77166..962e75f9 100644 --- a/core/src/main/java/dev/pgm/community/info/InfoCommandData.java +++ b/core/src/main/java/dev/pgm/community/info/InfoCommandData.java @@ -10,21 +10,11 @@ import org.bukkit.configuration.ConfigurationSection; import tc.oc.pgm.util.Audience; -public class InfoCommandData { +public record InfoCommandData(String name, List lines, String permission) { private static final String LINES_KEY = "lines"; private static final String PERMISSION_KEY = "permission"; - private String name; - private List lines; - private String permission; - - public InfoCommandData(String name, List lines, String permission) { - this.name = name; - this.lines = lines; - this.permission = permission; - } - public static InfoCommandData of(ConfigurationSection section) { return new InfoCommandData( section.getName(), @@ -34,28 +24,16 @@ public static InfoCommandData of(ConfigurationSection section) { section.getString(PERMISSION_KEY)); } - public String getName() { - return name; - } - - public List getLines() { - return lines; - } - - public String getPermission() { - return permission; - } - public void sendCommand(CommandSender sender) { Audience viewer = Audience.get(sender); - if (getPermission() != null && !getPermission().isEmpty()) { - if (!sender.hasPermission(getPermission())) { + if (permission() != null && !permission().isEmpty()) { + if (!sender.hasPermission(permission())) { viewer.sendWarning(text("You do not have permission for this command")); return; // TODO: Translate } } - getLines().forEach(viewer::sendMessage); + lines().forEach(viewer::sendMessage); } } diff --git a/core/src/main/java/dev/pgm/community/info/InfoCommandsFeature.java b/core/src/main/java/dev/pgm/community/info/InfoCommandsFeature.java index 6d2f2e7c..a293970b 100644 --- a/core/src/main/java/dev/pgm/community/info/InfoCommandsFeature.java +++ b/core/src/main/java/dev/pgm/community/info/InfoCommandsFeature.java @@ -25,8 +25,7 @@ public InfoCommandConfig getInfoConfig() { public void onPlayerCommandProcess(PlayerCommandPreprocessEvent event) { // We dynamically check for defined commands, and send the related feedback getInfoConfig().getInfoCommands().stream() - .filter( - c -> event.getMessage().toLowerCase().startsWith("/" + c.getName().toLowerCase())) + .filter(c -> event.getMessage().toLowerCase().startsWith("/" + c.name().toLowerCase())) .findAny() .ifPresent(command -> { command.sendCommand(event.getPlayer()); diff --git a/core/src/main/java/dev/pgm/community/menu/CommunityInventoryProvider.java b/core/src/main/java/dev/pgm/community/menu/CommunityInventoryProvider.java index 575fc1e9..4dcc109a 100644 --- a/core/src/main/java/dev/pgm/community/menu/CommunityInventoryProvider.java +++ b/core/src/main/java/dev/pgm/community/menu/CommunityInventoryProvider.java @@ -11,7 +11,7 @@ public abstract class CommunityInventoryProvider implements InventoryProvider { - private List items; + private final List items; public CommunityInventoryProvider(List items) { this.items = items; @@ -38,13 +38,10 @@ public abstract Consumer getClickAction( protected abstract ItemStack getNoResultsItem(); protected int getStartingSlot(int categorySize) { - switch (categorySize) { - case 3: - return 2; - case 4: - return 1; - default: - return 0; - } + return switch (categorySize) { + case 3 -> 2; + case 4 -> 1; + default -> 0; + }; } } diff --git a/core/src/main/java/dev/pgm/community/menu/MapSelectionMenu.java b/core/src/main/java/dev/pgm/community/menu/MapSelectionMenu.java index 302d3d9d..fa83165a 100644 --- a/core/src/main/java/dev/pgm/community/menu/MapSelectionMenu.java +++ b/core/src/main/java/dev/pgm/community/menu/MapSelectionMenu.java @@ -36,10 +36,10 @@ public abstract class MapSelectionMenu implements InventoryProvider, PageableInv private static final int ROWS = 6; - private String title; - private Player viewer; - private List maps; - private List tags; + private final String title; + private final Player viewer; + private final List maps; + private final List tags; private int filterIndex = 0; @@ -85,7 +85,6 @@ public void update(Player player, InventoryContents contents) { contents.setProperty("update", delay + 1); if (delay >= 5) { render(player, contents); - delay = 0; } } @@ -105,7 +104,7 @@ private void render(Player player, InventoryContents contents) { List mapItems = getFilteredMapItems(); Pagination page = contents.pagination(); - page.setItems(mapItems.toArray(new ClickableItem[mapItems.size()])); + page.setItems(mapItems.toArray(new ClickableItem[0])); page.setItemsPerPage(36); page.addToIterator(contents.newIterator(SlotIterator.Type.HORIZONTAL, 1, 0)); @@ -134,11 +133,10 @@ public Player getViewer() { } public Material getMapMaterial(MapInfo map) { - return map.getTags().isEmpty() - || !map.getTags().stream().filter(tag -> tag.isGamemode()).findAny().isPresent() + return map.getTags().isEmpty() || map.getTags().stream().noneMatch(MapTag::isGamemode) ? Material.MAP : mapTagMaterial( - map.getTags().stream().filter(tag -> tag.isGamemode()).findAny().get()); + map.getTags().stream().filter(MapTag::isGamemode).findAny().get()); } private List getMapItems(List maps) { diff --git a/core/src/main/java/dev/pgm/community/menu/MenuItem.java b/core/src/main/java/dev/pgm/community/menu/MenuItem.java index f82245d9..7d3a8cbf 100644 --- a/core/src/main/java/dev/pgm/community/menu/MenuItem.java +++ b/core/src/main/java/dev/pgm/community/menu/MenuItem.java @@ -18,7 +18,7 @@ public abstract class MenuItem { private final String[] description; public MenuItem(Material icon, String name, List description) { - this(icon, name, description.toArray(new String[description.size()])); + this(icon, name, description.toArray(new String[0])); } public MenuItem(Material icon, String name, String... description) { diff --git a/core/src/main/java/dev/pgm/community/menu/PlayerSelectionProvider.java b/core/src/main/java/dev/pgm/community/menu/PlayerSelectionProvider.java index 0b42bfe9..0903d402 100644 --- a/core/src/main/java/dev/pgm/community/menu/PlayerSelectionProvider.java +++ b/core/src/main/java/dev/pgm/community/menu/PlayerSelectionProvider.java @@ -61,7 +61,7 @@ public void init(Player player, InventoryContents contents) { @Override public void update(Player player, InventoryContents contents) {} - private final ItemStack getPageIcon(String text, int page) { + private ItemStack getPageIcon(String text, int page) { return getNamedItem(text, PAGE_MATERIAL, page); } diff --git a/core/src/main/java/dev/pgm/community/mobs/MobFeature.java b/core/src/main/java/dev/pgm/community/mobs/MobFeature.java index ae12f014..c4c60fbb 100644 --- a/core/src/main/java/dev/pgm/community/mobs/MobFeature.java +++ b/core/src/main/java/dev/pgm/community/mobs/MobFeature.java @@ -30,8 +30,8 @@ public class MobFeature extends FeatureBase { public static final float DEFAULT_SPEED = 1.2f; - private Map followTargets; - private Set attackers; + private final Map followTargets; + private final Set attackers; private BukkitTask task; private float speed; @@ -67,10 +67,8 @@ public void disable() { @EventHandler public void onDamage(EntityDamageByEntityEvent event) { if (event.getDamager() != null - && event.getDamager() instanceof Player - && event.getEntity() instanceof Player) { - Player damager = (Player) event.getDamager(); - Player target = (Player) event.getEntity(); + && event.getDamager() instanceof Player damager + && event.getEntity() instanceof Player target) { if (isAttacker(damager.getUniqueId())) { setTarget(damager, target); @@ -79,14 +77,13 @@ public void onDamage(EntityDamageByEntityEvent event) { } public void updateFollows() { - this.followTargets.entrySet().forEach(entry -> { - Player owner = Bukkit.getPlayer(entry.getKey()); - Player target = Bukkit.getPlayer(entry.getValue()); + this.followTargets.forEach((key, value) -> { + Player owner = Bukkit.getPlayer(key); + Player target = Bukkit.getPlayer(value); if (owner != null && target != null) { this.getOwnedMobs(owner).forEach(mob -> { ENTITY_UTILS.follow(mob, target.getLocation(), speed); - if (mob instanceof Creature && attackers.contains(owner.getUniqueId())) { - Creature creature = (Creature) mob; + if (mob instanceof Creature creature && attackers.contains(owner.getUniqueId())) { creature.setTarget(target); } }); @@ -127,8 +124,7 @@ public void spawn(Player sender, EntityType type, int amount, boolean canDie) { public void spawn(Player sender, EntityType type, boolean canDie) { Entity entity = sender.getLocation().getWorld().spawnEntity(sender.getLocation(), type); - if (entity instanceof LivingEntity) { - LivingEntity mob = (LivingEntity) entity; + if (entity instanceof LivingEntity mob) { if (!canDie) { mob.setMaxHealth(Integer.MAX_VALUE); mob.setHealth(mob.getMaxHealth()); @@ -164,7 +160,7 @@ public int heal(Player sender) { public int remove(Player sender) { List mobs = getOwnedMobs(sender); - mobs.forEach(mob -> mob.remove()); + mobs.forEach(Entity::remove); return mobs.size(); } @@ -172,9 +168,7 @@ public boolean toggleFollow(Player sender) { UUID playerId = sender.getUniqueId(); // Unset attackers when switching to follow - if (this.attackers.contains(playerId)) { - this.attackers.remove(playerId); - } + this.attackers.remove(playerId); if (this.followTargets.containsKey(playerId)) { this.followTargets.remove(playerId); diff --git a/core/src/main/java/dev/pgm/community/moderation/ModerationConfig.java b/core/src/main/java/dev/pgm/community/moderation/ModerationConfig.java index d544edb6..6232c709 100644 --- a/core/src/main/java/dev/pgm/community/moderation/ModerationConfig.java +++ b/core/src/main/java/dev/pgm/community/moderation/ModerationConfig.java @@ -175,19 +175,13 @@ public String getRulesLink() { * @return True if punishment should be visible publicly */ public boolean isPunishmentPublic(Punishment punishment) { - switch (punishment.getType()) { - case TEMP_BAN: - case BAN: - return banPublic; - case KICK: - return kickPublic; - case MUTE: - return mutePublic; - case WARN: - return warnPublic; - default: - return broadcast; - } + return switch (punishment.getType()) { + case TEMP_BAN, BAN -> banPublic; + case KICK -> kickPublic; + case MUTE -> mutePublic; + case WARN -> warnPublic; + default -> broadcast; + }; } /** diff --git a/core/src/main/java/dev/pgm/community/moderation/feature/PGMPunishmentIntegration.java b/core/src/main/java/dev/pgm/community/moderation/feature/PGMPunishmentIntegration.java index 27f229f2..5928e53d 100644 --- a/core/src/main/java/dev/pgm/community/moderation/feature/PGMPunishmentIntegration.java +++ b/core/src/main/java/dev/pgm/community/moderation/feature/PGMPunishmentIntegration.java @@ -26,9 +26,9 @@ public class PGMPunishmentIntegration implements PunishmentIntegration, Listener { - private ModerationFeature moderation; + private final ModerationFeature moderation; - private ModerationTools tools; + private final ModerationTools tools; public PGMPunishmentIntegration(ModerationFeature moderation) { this.moderation = moderation; diff --git a/core/src/main/java/dev/pgm/community/moderation/feature/types/ModerationFeatureCore.java b/core/src/main/java/dev/pgm/community/moderation/feature/types/ModerationFeatureCore.java index bd523bd4..b84fccaa 100644 --- a/core/src/main/java/dev/pgm/community/moderation/feature/types/ModerationFeatureCore.java +++ b/core/src/main/java/dev/pgm/community/moderation/feature/types/ModerationFeatureCore.java @@ -64,7 +64,7 @@ import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result; import org.bukkit.event.player.PlayerJoinEvent; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.named.NameStyle; @@ -485,10 +485,10 @@ public void sendUpdate(NetworkPunishment punishment) { @Override public void recieveUpdate(NetworkPunishment punishment) { - recieveRefresh(punishment.getPunishment().getTargetId()); - broadcastPunishment(punishment.getPunishment(), true, punishment.getServer()); + recieveRefresh(punishment.punishment().getTargetId()); + broadcastPunishment(punishment.punishment(), true, punishment.serverId()); // Extra step due to gson limitation (maybe look into type tokens) - Punishment typedPunishment = Punishment.of(punishment.getPunishment()); + Punishment typedPunishment = Punishment.of(punishment.punishment()); Community.get() .getServer() .getScheduler() diff --git a/core/src/main/java/dev/pgm/community/moderation/punishments/NetworkPunishment.java b/core/src/main/java/dev/pgm/community/moderation/punishments/NetworkPunishment.java index 4f39bcf7..a14bf431 100644 --- a/core/src/main/java/dev/pgm/community/moderation/punishments/NetworkPunishment.java +++ b/core/src/main/java/dev/pgm/community/moderation/punishments/NetworkPunishment.java @@ -1,20 +1,3 @@ package dev.pgm.community.moderation.punishments; -public class NetworkPunishment { - - private String serverId; - private Punishment punishment; - - public NetworkPunishment(Punishment punishment, String serverId) { - this.punishment = punishment; - this.serverId = serverId; - } - - public String getServer() { - return serverId; - } - - public Punishment getPunishment() { - return punishment; - } -} +public record NetworkPunishment(Punishment punishment, String serverId) {} diff --git a/core/src/main/java/dev/pgm/community/moderation/punishments/Punishment.java b/core/src/main/java/dev/pgm/community/moderation/punishments/Punishment.java index 91772b18..1e2930aa 100644 --- a/core/src/main/java/dev/pgm/community/moderation/punishments/Punishment.java +++ b/core/src/main/java/dev/pgm/community/moderation/punishments/Punishment.java @@ -3,6 +3,7 @@ import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.translatable; +import static net.kyori.adventure.title.Title.Times.times; import static net.kyori.adventure.title.Title.title; import static tc.oc.pgm.util.text.TemporalComponent.briefNaturalApproximate; import static tc.oc.pgm.util.text.TemporalComponent.duration; @@ -31,11 +32,10 @@ import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.title.Title.Times; import net.kyori.adventure.util.Ticks; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.named.NameStyle; import tc.oc.pgm.util.player.PlayerComponent; @@ -67,7 +67,7 @@ public Punishment( UUID targetId, @Nullable UUID issuerId, String reason, - Duration duration, + @Nullable Duration duration, long timeIssued, boolean active, long lastUpdated, @@ -139,7 +139,7 @@ public String getService() { return service; } - public Duration getDuration() { + public @Nullable Duration getDuration() { return duration; } @@ -202,8 +202,8 @@ public void sendWarning(Audience target, String reason) { subtitle = text(reason, NamedTextColor.GOLD); } - target.showTitle(title( - title, subtitle, Times.of(Ticks.duration(5), Ticks.duration(200), Ticks.duration(10)))); + target.showTitle( + title(title, subtitle, times(Ticks.duration(5), Ticks.duration(200), Ticks.duration(10)))); target.playSound(Sounds.WARN_SOUND); } @@ -250,7 +250,7 @@ public Component formatTimeComponent() { } public Component getExpireDateMessage() { - Duration banLength = ((ExpirablePunishment) this).getDuration(); + Duration banLength = this.getDuration(); Duration timeSince = Duration.between(getTimeIssued(), Instant.now()); Duration remaining = banLength.minus(timeSince); Component timeLeft = briefNaturalApproximate(remaining); @@ -350,26 +350,25 @@ public static Punishment of( long lastUpdated, @Nullable UUID lastUpdatedBy, String service) { - switch (type) { - case WARN: - return new WarnPunishment( + return switch (type) { + case WARN -> + new WarnPunishment( id, target, issuer, reason, time, active, lastUpdated, lastUpdatedBy, service); - case MUTE: - return new MutePunishment( + case MUTE -> + new MutePunishment( id, target, issuer, reason, time, length, active, lastUpdated, lastUpdatedBy, service); - case KICK: - return new KickPunishment( + case KICK -> + new KickPunishment( id, target, issuer, reason, time, active, lastUpdated, lastUpdatedBy, service); - case TEMP_BAN: - return new TempBanPunishment( + case TEMP_BAN -> + new TempBanPunishment( id, target, issuer, reason, time, length, active, lastUpdated, lastUpdatedBy, service); - case BAN: - return new BanPunishment( + case BAN -> + new BanPunishment( id, target, issuer, reason, time, active, lastUpdated, lastUpdatedBy, service); - case NAME_BAN: - return new UsernameBanPunishment( + case NAME_BAN -> + new UsernameBanPunishment( id, target, issuer, reason, time, active, lastUpdated, lastUpdatedBy, service); - } - return null; + }; } } diff --git a/core/src/main/java/dev/pgm/community/moderation/punishments/PunishmentType.java b/core/src/main/java/dev/pgm/community/moderation/punishments/PunishmentType.java index f7912389..406eb7b4 100644 --- a/core/src/main/java/dev/pgm/community/moderation/punishments/PunishmentType.java +++ b/core/src/main/java/dev/pgm/community/moderation/punishments/PunishmentType.java @@ -16,8 +16,8 @@ public enum PunishmentType { TEMP_BAN(true, true, true, true, "Temporary Ban"), NAME_BAN(true, true, true, false, "Username Ban"); - private String PREFIX_TRANSLATE_KEY = "moderation.type."; - private String SCREEN_TRANSLATE_KEY = "moderation.screen."; + private final String PREFIX_TRANSLATE_KEY = "moderation.type."; + private final String SCREEN_TRANSLATE_KEY = "moderation.screen."; private final boolean screen; private final boolean canRescind; diff --git a/core/src/main/java/dev/pgm/community/moderation/punishments/types/ExpirablePunishment.java b/core/src/main/java/dev/pgm/community/moderation/punishments/types/ExpirablePunishment.java index 8ca4218c..f33d59ea 100644 --- a/core/src/main/java/dev/pgm/community/moderation/punishments/types/ExpirablePunishment.java +++ b/core/src/main/java/dev/pgm/community/moderation/punishments/types/ExpirablePunishment.java @@ -5,7 +5,7 @@ import java.time.Duration; import java.time.Instant; import java.util.UUID; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; /** A punishment that can expire * */ public abstract class ExpirablePunishment extends Punishment { @@ -40,8 +40,8 @@ public ExpirablePunishment( public boolean isActive() { Instant expires = this.getTimeIssued().plus(this.getDuration()); return super.isActive() - ? Instant.now().isBefore(expires) - : false; // If expired return false, otherwise return true until expires + && Instant.now() + .isBefore(expires); // If expired return false, otherwise return true until expires } public Instant getExpireTime() { @@ -49,8 +49,6 @@ public Instant getExpireTime() { } public static @Nullable Duration getDuration(Punishment punishment) { - return punishment instanceof ExpirablePunishment - ? ExpirablePunishment.class.cast(punishment).getDuration() - : null; + return punishment instanceof ExpirablePunishment ? punishment.getDuration() : null; } } diff --git a/core/src/main/java/dev/pgm/community/moderation/services/ModerationQuery.java b/core/src/main/java/dev/pgm/community/moderation/services/ModerationQuery.java index a7ba2ec1..e86a99f5 100644 --- a/core/src/main/java/dev/pgm/community/moderation/services/ModerationQuery.java +++ b/core/src/main/java/dev/pgm/community/moderation/services/ModerationQuery.java @@ -2,29 +2,27 @@ public interface ModerationQuery { - static final String TABLE_NAME = "punishments"; - static final String TABLE_FIELDS = + String TABLE_NAME = "punishments"; + String TABLE_FIELDS = "(id VARCHAR(36) PRIMARY KEY, punished VARCHAR(36), issuer VARCHAR(36), reason VARCHAR(255), type VARCHAR(8), time LONG, expires LONG, active BOOL, last_updated LONG, updated_by VARCHAR(36), service VARCHAR(255))"; - static final String INSERT_PUNISHMENT_QUERY = "INSERT INTO " + String INSERT_PUNISHMENT_QUERY = "INSERT INTO " + TABLE_NAME + "(id, punished, issuer, reason, type, time, expires, active, last_updated, updated_by, service) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - static final String SELECT_PUNISHMENTS_QUERY = - "SELECT * from " + TABLE_NAME + " where punished = ?"; + String SELECT_PUNISHMENTS_QUERY = "SELECT * from " + TABLE_NAME + " where punished = ?"; - static final String SELECT_ACTIVE_PUNISHMENTS_QUERY = + String SELECT_ACTIVE_PUNISHMENTS_QUERY = "SELECT id, type, active, expires, time, service, reason, issuer from " + TABLE_NAME + " where punished = ? AND active = ?"; - static final String SINGLE_PARDON_TYPE = "AND type = ?"; - static final String MULTI_PARDON_TYPE = "AND (type = ? OR type = ? OR type = ?)"; - static final String PARDON_QUERY = "UPDATE " + String SINGLE_PARDON_TYPE = "AND type = ?"; + String MULTI_PARDON_TYPE = "AND (type = ? OR type = ? OR type = ?)"; + String PARDON_QUERY = "UPDATE " + TABLE_NAME + " SET active = ?, last_updated = ?, updated_by = ? WHERE active = ? AND punished = ? "; - static final String DEACTIVATE_QUERY = + String DEACTIVATE_QUERY = "UPDATE " + TABLE_NAME + " SET active = ? WHERE active = ? AND punished = ? "; - static final String SELECT_RECENT_QUERY = - "SELECT * from " + TABLE_NAME + " WHERE time > ? LIMIT ?"; + String SELECT_RECENT_QUERY = "SELECT * from " + TABLE_NAME + " WHERE time > ? LIMIT ?"; } diff --git a/core/src/main/java/dev/pgm/community/moderation/services/SQLModerationService.java b/core/src/main/java/dev/pgm/community/moderation/services/SQLModerationService.java index c30f80bf..4efde162 100644 --- a/core/src/main/java/dev/pgm/community/moderation/services/SQLModerationService.java +++ b/core/src/main/java/dev/pgm/community/moderation/services/SQLModerationService.java @@ -16,7 +16,7 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; public class SQLModerationService extends SQLFeatureBase implements ModerationQuery { @@ -26,20 +26,15 @@ public class SQLModerationService extends SQLFeatureBase private static final int RECENT_LIMIT = 50; - private LoadingCache punishmentCache; + private final LoadingCache punishmentCache; private final ModerationConfig config; public SQLModerationService(ModerationConfig config) { super(TABLE_NAME, TABLE_FIELDS); this.config = config; - this.punishmentCache = CacheBuilder.newBuilder() - .build(new CacheLoader() { - @Override - public PlayerPunishments load(UUID key) throws Exception { - return new PlayerPunishments(key); - } - }); + this.punishmentCache = + CacheBuilder.newBuilder().build(CacheLoader.from(PlayerPunishments::new)); } @Override @@ -114,7 +109,7 @@ private long getExpiration(Punishment punishment) { long expires = punishment.getTimeIssued().toEpochMilli(); if (punishment instanceof ExpirablePunishment) { - Duration time = ((ExpirablePunishment) punishment).getDuration(); + Duration time = punishment.getDuration(); expires = punishment.getTimeIssued().plusMillis(time.toMillis()).toEpochMilli(); } @@ -228,7 +223,7 @@ public void invalidate(UUID playerId) { } } - private class PlayerPunishments { + private static class PlayerPunishments { private final UUID playerId; private final List punishments; diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/ModerationTools.java b/core/src/main/java/dev/pgm/community/moderation/tools/ModerationTools.java index 13f0bcbc..03db2c85 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/ModerationTools.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/ModerationTools.java @@ -9,9 +9,9 @@ public class ModerationTools { - private ModerationMenuTool menu; - private TeleportHook tpHook; - private LookupSign sign; + private final ModerationMenuTool menu; + private final TeleportHook tpHook; + private final LookupSign sign; public ModerationTools(ModerationConfig config) { // TODO: allow reloads to enable/disable tools diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/ToolBase.java b/core/src/main/java/dev/pgm/community/moderation/tools/ToolBase.java index 4f642b7e..e48d5847 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/ToolBase.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/ToolBase.java @@ -12,8 +12,8 @@ public abstract class ToolBase implements Tool { - private int slot; - private boolean enabled; + private final int slot; + private final boolean enabled; public ToolBase(int slot, boolean enabled) { this.slot = slot; diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/ToolButtonBase.java b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/ToolButtonBase.java index e37cc786..1098aa6f 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/ToolButtonBase.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/ToolButtonBase.java @@ -11,12 +11,12 @@ public abstract class ToolButtonBase implements ToolButton { - private Player viewer; + private final Player viewer; - private String name; - private List lore; - private Material material; - private int amount; + private final String name; + private final List lore; + private final Material material; + private final int amount; public ToolButtonBase( Player viewer, String name, List lore, Material material, int amount) { diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/TranslatableToolButton.java b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/TranslatableToolButton.java index d644597a..9c670208 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/TranslatableToolButton.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/TranslatableToolButton.java @@ -13,9 +13,9 @@ public abstract class TranslatableToolButton extends ToolButtonBase { - private String nameKey; - private String loreKey; - private NamedTextColor nameColor; + private final String nameKey; + private final String loreKey; + private final NamedTextColor nameColor; public TranslatableToolButton( Player viewer, diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/GamemodeButton.java b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/GamemodeButton.java index 6c11ddfe..470ef0d5 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/GamemodeButton.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/GamemodeButton.java @@ -79,13 +79,10 @@ private boolean isCreative() { } private GameMode getOppositeMode(GameMode mode) { - switch (mode) { - case CREATIVE: - return GameMode.SPECTATOR; - case SPECTATOR: - return GameMode.CREATIVE; - default: - return mode; - } + return switch (mode) { + case CREATIVE -> GameMode.SPECTATOR; + case SPECTATOR -> GameMode.CREATIVE; + default -> mode; + }; } } diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/ObserverVisibilityButton.java b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/ObserverVisibilityButton.java index 0940096d..ac520550 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/ObserverVisibilityButton.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/ObserverVisibilityButton.java @@ -68,14 +68,11 @@ public boolean isVisible() { private String getStatusKey() { MatchPlayer matchPlayer = PGM.get().getMatchManager().getPlayer(getViewer()); SettingValue value = matchPlayer.getSettings().getValue(SettingKey.OBSERVERS); - switch (value) { - case OBSERVERS_FRIEND: - return "misc.friends"; - case OBSERVERS_ON: - return "misc.all"; - default: - return "misc.none"; - } + return switch (value) { + case OBSERVERS_FRIEND -> "misc.friends"; + case OBSERVERS_ON -> "misc.all"; + default -> "misc.none"; + }; } public void toggleObserverVisibility(Player player) { diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/SpeedButton.java b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/SpeedButton.java index c0a7dd03..6e3cfe0d 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/SpeedButton.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/buttons/types/SpeedButton.java @@ -51,7 +51,7 @@ public enum FlySpeed { private final TextColor color; private final float value; - private static FlySpeed[] speeds = values(); + private static final FlySpeed[] speeds = values(); FlySpeed(TextColor color, float value) { this.color = color; diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/menu/ModerationToolsMenu.java b/core/src/main/java/dev/pgm/community/moderation/tools/menu/ModerationToolsMenu.java index ce226b1f..e2542e79 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/menu/ModerationToolsMenu.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/menu/ModerationToolsMenu.java @@ -23,8 +23,8 @@ public class ModerationToolsMenu implements InventoryProvider { - private SmartInventory inventory; - private Random random; + private final SmartInventory inventory; + private final Random random; public ModerationToolsMenu() { this.inventory = SmartInventory.builder() diff --git a/core/src/main/java/dev/pgm/community/moderation/tools/types/ModerationMenuTool.java b/core/src/main/java/dev/pgm/community/moderation/tools/types/ModerationMenuTool.java index 7c275270..6cf34bc2 100644 --- a/core/src/main/java/dev/pgm/community/moderation/tools/types/ModerationMenuTool.java +++ b/core/src/main/java/dev/pgm/community/moderation/tools/types/ModerationMenuTool.java @@ -16,7 +16,7 @@ public class ModerationMenuTool extends ToolBase { private static final List LORE = Lists.newArrayList("&7Click to open the mod tools menu."); - private ModerationToolsMenu menu; + private final ModerationToolsMenu menu; public ModerationMenuTool(int slot, boolean enabled) { super(slot, enabled); diff --git a/core/src/main/java/dev/pgm/community/mutations/MutationType.java b/core/src/main/java/dev/pgm/community/mutations/MutationType.java index 591edfbd..f4fb37c3 100644 --- a/core/src/main/java/dev/pgm/community/mutations/MutationType.java +++ b/core/src/main/java/dev/pgm/community/mutations/MutationType.java @@ -42,9 +42,9 @@ public enum MutationType { "Give potion effects based on distance to Objectives", Material.GLASS_BOTTLE); - String displayName; - String description; - Material icon; + final String displayName; + final String description; + final Material icon; MutationType(String displayName, String description, Material icon) { this.displayName = displayName; diff --git a/core/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java b/core/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java index 3aabf977..04ab8b1d 100644 --- a/core/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java +++ b/core/src/main/java/dev/pgm/community/mutations/feature/MutationFeature.java @@ -58,7 +58,7 @@ public class MutationFeature extends FeatureBase { - private Set mutations; + private final Set mutations; private final InventoryManager inventory; @@ -226,22 +226,19 @@ public void onMatchStart(MatchStartEvent event) { Set names = mutations.stream().map(Mutation::getName).collect(Collectors.toSet()); boolean single = names.size() == 1; - Component broadcast = - text() - .append( - TextFormatter.horizontalLine( - NamedTextColor.DARK_GREEN, TextFormatter.MAX_CHAT_WIDTH)) - .append(newline()) - .append(TextFormatter.list(names, NamedTextColor.GRAY)) - .append(text(" mutation" + (single ? "" : "s"))) - .append(text(single ? " has " : " have ")) - .append(text("been enabled")) - .append(newline()) - .append( - TextFormatter.horizontalLine( - NamedTextColor.DARK_GREEN, TextFormatter.MAX_CHAT_WIDTH)) - .color(NamedTextColor.GRAY) - .build(); + Component broadcast = text() + .append( + TextFormatter.horizontalLine(NamedTextColor.DARK_GREEN, TextFormatter.MAX_CHAT_WIDTH)) + .append(newline()) + .append(TextFormatter.list(names, NamedTextColor.GRAY)) + .append(text(" mutation" + (single ? "" : "s"))) + .append(text(single ? " has " : " have ")) + .append(text("been enabled")) + .append(newline()) + .append( + TextFormatter.horizontalLine(NamedTextColor.DARK_GREEN, TextFormatter.MAX_CHAT_WIDTH)) + .color(NamedTextColor.GRAY) + .build(); if (!mutations.isEmpty()) { BroadcastUtils.sendGlobalMessage(broadcast, Sounds.ALERT); diff --git a/core/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java b/core/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java index f9545725..47a72f2f 100644 --- a/core/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java +++ b/core/src/main/java/dev/pgm/community/mutations/menu/MutationOptionsMenu.java @@ -12,21 +12,15 @@ import fr.minuskube.inv.ClickableItem; import fr.minuskube.inv.content.InventoryContents; import fr.minuskube.inv.content.InventoryProvider; +import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import tc.oc.pgm.util.inventory.ItemBuilder; -public class MutationOptionsMenu implements InventoryProvider { - - private final MutationFeature mutations; - - public MutationOptionsMenu(MutationFeature mutations) { - this.mutations = mutations; - } +public record MutationOptionsMenu(MutationFeature mutations) implements InventoryProvider { @Override public void init(Player player, InventoryContents contents) { @@ -43,8 +37,8 @@ private void render(Player player, InventoryContents contents) { List options = mutations.getMutations().stream() .map(Mutation::getOptions) - .flatMap(mo -> mo.stream()) - .collect(Collectors.toList()); + .flatMap(Collection::stream) + .toList(); if (options.isEmpty()) { contents.set(1, 4, getNoMutationsIcon()); @@ -73,22 +67,20 @@ private ClickableItem getReturnIcon(Player viewer) { .name(colorize("&eReturn to Mutations")) .flags(ItemFlag.values()) .build(), - c -> { - mutations.getMenu().open(viewer); - }); + c -> mutations.getMenu().open(viewer)); } private ClickableItem getOptionIcon(MutationOption option) { - if (option instanceof MutationBooleanOption) { - return getToggleIcon((MutationBooleanOption) option); + if (option instanceof MutationBooleanOption mutationBooleanOption) { + return getToggleIcon(mutationBooleanOption); } - if (option instanceof MutationRangeOption) { - return getRangeIcon((MutationRangeOption) option); + if (option instanceof MutationRangeOption mutationRangeOption) { + return getRangeIcon(mutationRangeOption); } - if (option instanceof MutationListOption) { - return getListIcon((MutationListOption) option); + if (option instanceof MutationListOption mutationListOption) { + return getListIcon(mutationListOption); } return null; // Option type not implemented yet @@ -110,9 +102,7 @@ private ClickableItem getToggleIcon(MutationBooleanOption option) { + ": " + getBooleanValue(option.getValue())) .build(), - c -> { - option.setValue(!option.getValue()); - }); + c -> option.setValue(!option.getValue())); } private ClickableItem getRangeIcon(MutationRangeOption option) { @@ -156,7 +146,7 @@ private ClickableItem getRangeIcon(MutationRangeOption option) { }); } - private ClickableItem getListIcon(MutationListOption option) { + private ClickableItem getListIcon(MutationListOption option) { return ClickableItem.of( getItem(option) .lore( diff --git a/core/src/main/java/dev/pgm/community/mutations/menu/MutationToggleMenu.java b/core/src/main/java/dev/pgm/community/mutations/menu/MutationToggleMenu.java index d6649aff..69d6e798 100644 --- a/core/src/main/java/dev/pgm/community/mutations/menu/MutationToggleMenu.java +++ b/core/src/main/java/dev/pgm/community/mutations/menu/MutationToggleMenu.java @@ -14,13 +14,7 @@ import org.bukkit.inventory.ItemFlag; import tc.oc.pgm.util.inventory.ItemBuilder; -public class MutationToggleMenu implements InventoryProvider { - - private MutationFeature mutations; - - public MutationToggleMenu(MutationFeature mutations) { - this.mutations = mutations; - } +public record MutationToggleMenu(MutationFeature mutations) implements InventoryProvider { @Override public void init(Player player, InventoryContents contents) { @@ -49,9 +43,7 @@ private ClickableItem getOptionIcon(Player player) { .lore(ChatColor.GRAY + "Click to view active mutation options") .flags(ItemFlag.values()) .build(), - c -> { - mutations.getOptionMenu().open(player); - }); + c -> mutations.getOptionMenu().open(player)); } @Override diff --git a/core/src/main/java/dev/pgm/community/mutations/options/MutationBooleanOption.java b/core/src/main/java/dev/pgm/community/mutations/options/MutationBooleanOption.java index 010339e7..651149de 100644 --- a/core/src/main/java/dev/pgm/community/mutations/options/MutationBooleanOption.java +++ b/core/src/main/java/dev/pgm/community/mutations/options/MutationBooleanOption.java @@ -5,7 +5,7 @@ public class MutationBooleanOption extends MutationOption { private boolean value; - private boolean def; + private final boolean def; public MutationBooleanOption( String name, String description, Material iconMaterial, boolean def, boolean prereq) { diff --git a/core/src/main/java/dev/pgm/community/mutations/options/MutationListOption.java b/core/src/main/java/dev/pgm/community/mutations/options/MutationListOption.java index f332452b..3d4c885b 100644 --- a/core/src/main/java/dev/pgm/community/mutations/options/MutationListOption.java +++ b/core/src/main/java/dev/pgm/community/mutations/options/MutationListOption.java @@ -6,9 +6,9 @@ public class MutationListOption extends MutationOption { - private List options; + private final List options; private int valueIndex; - private T def; + private final T def; public MutationListOption( String name, @@ -19,7 +19,7 @@ public MutationListOption( super(name, description, iconMaterial, prerequisite); this.options = options; this.valueIndex = 0; - this.def = options.get(0); + this.def = options.getFirst(); } public ImmutableList getOptions() { diff --git a/core/src/main/java/dev/pgm/community/mutations/options/MutationRangeOption.java b/core/src/main/java/dev/pgm/community/mutations/options/MutationRangeOption.java index ee959a09..978d7d8a 100644 --- a/core/src/main/java/dev/pgm/community/mutations/options/MutationRangeOption.java +++ b/core/src/main/java/dev/pgm/community/mutations/options/MutationRangeOption.java @@ -4,10 +4,10 @@ public class MutationRangeOption extends MutationOption { - private int min; - private int max; + private final int min; + private final int max; private int value; - private int def; + private final int def; public MutationRangeOption( String name, diff --git a/core/src/main/java/dev/pgm/community/mutations/types/KitMutationBase.java b/core/src/main/java/dev/pgm/community/mutations/types/KitMutationBase.java index ba4dfabd..43e5910c 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/KitMutationBase.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/KitMutationBase.java @@ -17,7 +17,7 @@ /** KitMutation - A base for mutations which grant kits * */ public abstract class KitMutationBase extends MutationBase { - private List kits; + private final List kits; public KitMutationBase(Match match, MutationType type, Kit... kits) { super(match, type); @@ -71,7 +71,7 @@ protected void giveAllKit(Kit... kit) { protected void removeAllKit(Kit kit) { if (kit.isRemovable()) { - match.getParticipants().forEach(player -> kit.remove(player)); + match.getParticipants().forEach(kit::remove); } } @@ -84,11 +84,6 @@ protected void givePlayerKit(MatchPlayer player, List kits) { } protected void removeItems(ItemStack... items) { - match - .getParticipants() - .forEach( - player -> { - player.getInventory().removeItem(items); - }); + match.getParticipants().forEach(player -> player.getInventory().removeItem(items)); } } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java index 1c1628d5..6a9d4f9b 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/arrows/WebSlingersMutation.java @@ -34,7 +34,7 @@ public class WebSlingersMutation extends KitMutationBase implements BowMutation { - private static MutationRangeOption WEB_LIFE = new MutationRangeOption( + private static final MutationRangeOption WEB_LIFE = new MutationRangeOption( "Web Life", "Length of time before webs are removed", MutationType.WEB_SLINGERS.getMaterial(), @@ -45,7 +45,7 @@ public class WebSlingersMutation extends KitMutationBase implements BowMutation private int cleanupTask; - private Map webLocations = Maps.newHashMap(); + private final Map webLocations; public WebSlingersMutation(Match match) { super(match, MutationType.WEB_SLINGERS, getWebBowKit()); @@ -87,9 +87,8 @@ public ItemStack[] getAllItems() { @EventHandler public void onShootWeb(final EntityShootBowEvent event) { - if (!(event.getEntity() instanceof Player)) return; - Player player = (Player) event.getEntity(); - if (player == null || match.getParticipant(player) == null) return; + if (!(event.getEntity() instanceof Player player)) return; + if (match.getParticipant(player) == null) return; ItemStack bow = event.getBow(); if (!bow.isSimilar(getWebBow())) return; @@ -104,8 +103,7 @@ public void onShootWeb(final EntityShootBowEvent event) { @EventHandler public void onWebLand(final EntityChangeBlockEvent event) { - if (!(event.getEntity() instanceof FallingBlock)) return; - FallingBlock block = (FallingBlock) event.getEntity(); + if (!(event.getEntity() instanceof FallingBlock block)) return; if (block.getMaterial() != Materials.WEB) return; Location location = block.getLocation(); diff --git a/core/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java index eca018e7..309df94e 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/gameplay/BlitzMutation.java @@ -19,7 +19,7 @@ /** BlitzMutation - Enables blitz on a non-blitz match * */ public class BlitzMutation extends MutationBase { - private static MutationRangeOption BLITZ_LIVES = new MutationRangeOption( + private static final MutationRangeOption BLITZ_LIVES = new MutationRangeOption( "Blitz Lives", "The number of lives per-user", Material.EGG, true, 1, 1, 999); private BlitzMatchModule blitz; diff --git a/core/src/main/java/dev/pgm/community/mutations/types/gameplay/GhostMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/gameplay/GhostMutation.java index bd5e467b..36de1b9c 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/gameplay/GhostMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/gameplay/GhostMutation.java @@ -27,10 +27,8 @@ public void enable() { super.enable(); match.getParties().stream() .filter(party -> party instanceof Competitor) - .forEach( - party -> - ((Competitor) party).setNameTagVisibility(NameTagVisibility.HIDE_FOR_OTHER_TEAMS)); - ; + .forEach(party -> + ((Competitor) party).setNameTagVisibility(NameTagVisibility.HIDE_FOR_OTHER_TEAMS)); } @Override diff --git a/core/src/main/java/dev/pgm/community/mutations/types/items/BreadMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/items/BreadMutation.java index a697f86c..5e2e53a0 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/items/BreadMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/items/BreadMutation.java @@ -38,7 +38,7 @@ import org.bukkit.plugin.PluginManager; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; import tc.oc.pgm.api.match.Match; import tc.oc.pgm.api.player.MatchPlayer; import tc.oc.pgm.events.PlayerJoinMatchEvent; @@ -85,8 +85,8 @@ public class BreadMutation extends KitMutationBase { private final WeightedRandomChooser breadChooser; private final WeightedRandomChooser badBreadChooser; private final Random random; - private WeightedRandomChooser potionChooser; - private Set badBreadSet; + private final WeightedRandomChooser potionChooser; + private final Set badBreadSet; public BreadMutation(Match match) { super(match, MutationType.BREAD); @@ -240,9 +240,8 @@ protected void givePlayerKit(MatchPlayer player, List kits) { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerDamageByEntity(EntityDamageByEntityEvent event) { - if (event.getDamager() instanceof Player && event.getEntity() instanceof Player) { + if (event.getDamager() instanceof Player && event.getEntity() instanceof Player hitPlayer) { ItemStack itemInHand = ((Player) event.getDamager()).getItemInHand(); - Player hitPlayer = (Player) event.getEntity(); if (itemInHand.isSimilar(POTION_BREAD)) { hitPlayer.addPotionEffect(new PotionEffect( potionChooser.choose(random), 20 * random.nextInt(7) + 3, random.nextInt(2) + 1)); @@ -330,7 +329,7 @@ private Location chooseStartingLocation(Player hitPlayer) { return origin; } - @NotNull + @NonNull private static Location copyLocation(Location origin, int x, int y, int z) { Location possibleLocation = new Location(origin.getWorld(), origin.getX() + x, origin.getY() + y, origin.getZ() + z); @@ -359,8 +358,7 @@ private boolean isSafe(Location location, int blockHeight) { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerDamage(EntityDamageEvent event) { - if (event.getEntity() instanceof Player) { - Player player = (Player) event.getEntity(); + if (event.getEntity() instanceof Player player) { if (player.getItemInHand().isSimilar(ARMORED_BREAD)) { event.setDamage(event.getDamage() * 0.5); } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java index 136962dc..3729f040 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/items/ExplosionMutation.java @@ -50,7 +50,7 @@ /** ExplosionMutation - TNT, Fireballs, and random explosions when mining blocks * */ public class ExplosionMutation extends KitMutationBase { - private static MutationRangeOption FIREBALL_POWER = new MutationRangeOption( + private static final MutationRangeOption FIREBALL_POWER = new MutationRangeOption( "Fireball Power", "Power of fireball explosion", MutationType.EXPLOSION.getMaterial(), @@ -59,14 +59,14 @@ public class ExplosionMutation extends KitMutationBase { 0, 10); - private static MutationBooleanOption FIREBALL_FIRE = new MutationBooleanOption( + private static final MutationBooleanOption FIREBALL_FIRE = new MutationBooleanOption( "Fireball Fire", "Whether fireballs are incendiary", MutationType.EXPLOSION.getMaterial(), true, false); - private static MutationRangeOption LAUNCH_COOLDOWN = new MutationRangeOption( + private static final MutationRangeOption LAUNCH_COOLDOWN = new MutationRangeOption( "Explosive Cooldown", "Delay between fireball or TNT shots", MutationType.EXPLOSION.getMaterial(), @@ -75,14 +75,14 @@ public class ExplosionMutation extends KitMutationBase { 0, 60); - private static MutationBooleanOption MYSTERY_TNT = new MutationBooleanOption( + private static final MutationBooleanOption MYSTERY_TNT = new MutationBooleanOption( "Mystery TNT", "Whether TNT should have a random effect", MutationType.EXPLOSION.getMaterial(), true, false); - private static MutationRangeOption TNT_SIZE = new MutationRangeOption( + private static final MutationRangeOption TNT_SIZE = new MutationRangeOption( "TNT Amount", "Amount of TNT given per player", MutationType.EXPLOSION.getMaterial(), @@ -98,7 +98,7 @@ public class ExplosionMutation extends KitMutationBase { private static final String EXPLOSION_METADATA = "mutation_explosion"; private static final ItemTag EXPLOSION_KIT = ItemTag.newString(EXPLOSION_METADATA); - private Map lastLaunch = Maps.newHashMap(); + private final Map lastLaunch = Maps.newHashMap(); public ExplosionMutation(Match match) { super(match, MutationType.EXPLOSION); @@ -119,7 +119,6 @@ public void onBlockPlace(BlockPlaceEvent event) { if (!isParticipant(event.getPlayer())) return; if (!MYSTERY_TNT.getValue()) return; - Player player = event.getPlayer(); ItemStack block = event.getItemInHand(); if (block == null) return; if (!isFromKit(block)) return; @@ -221,14 +220,11 @@ private void explode(Block block) { } private static Kit getRandomKit() { - switch (Community.get().getRandom().nextInt(3)) { - case 0: - return getTNTKit(); - case 1: - return getTNTLauncherKit(); - default: - return getFireballKit(); - } + return switch (Community.get().getRandom().nextInt(3)) { + case 0 -> getTNTKit(); + case 1 -> getTNTLauncherKit(); + default -> getFireballKit(); + }; } private static Kit getTNTKit() { @@ -248,7 +244,7 @@ public ItemStack[] getAllItems() { List items = getTNTItems(); items.add(getFireballItem()); items.add(getTNTLauncherItem()); - return items.toArray(new ItemStack[items.size()]); + return items.toArray(new ItemStack[0]); } private static List getTNTItems() { @@ -338,7 +334,7 @@ public void launchTNT(Player player, double length) { Location loc = player.getEyeLocation(); // Get the player's eye location Vector direction = loc.getDirection().normalize(); - TNTPrimed tnt = (TNTPrimed) player.getWorld().spawn(loc, TNTPrimed.class); + TNTPrimed tnt = player.getWorld().spawn(loc, TNTPrimed.class); tnt.setVelocity(direction.multiply(4)); tnt.setFuseTicks(60); } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/items/FireworkMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/items/FireworkMutation.java index f89b256b..4734ae21 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/items/FireworkMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/items/FireworkMutation.java @@ -35,7 +35,7 @@ import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.potion.PotionEffect; import org.bukkit.util.Vector; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.api.match.Match; import tc.oc.pgm.api.match.MatchScope; import tc.oc.pgm.api.player.MatchPlayer; @@ -53,9 +53,9 @@ public class FireworkMutation extends KitMutationBase { private static final ItemTag FIREWORK_TAG = ItemTag.newString(FIREWORK_METADATA); private static final int FIREWORK_POWER = 2; - private Cache lastFirework = + private final Cache lastFirework = CacheBuilder.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build(); - private Set fireworks; + private final Set fireworks; private ScheduledFuture task; @@ -102,8 +102,7 @@ public void task() { private void fling(Firework firework) { if (!firework.hasMetadata(FIREWORK_METADATA)) return; - if (firework.getPassenger() != null && firework.getPassenger() instanceof Player) { - Player player = (Player) firework.getPassenger(); + if (firework.getPassenger() != null && firework.getPassenger() instanceof Player player) { Vector velocity = player.getLocation().getDirection().multiply(7).setY(0); player.setVelocity(velocity); player.addPotionEffect(new PotionEffect(PotionEffects.RESISTANCE, 20 * 5, 5)); @@ -137,11 +136,9 @@ public void onFireworkItemLaunch(PlayerInteractEvent event) { @EventHandler public void onFireworkArrow(ProjectileHitEvent event) { if (event.getEntity() == null) return; - if (!(event.getEntity().getShooter() instanceof Player)) return; + if (!(event.getEntity().getShooter() instanceof Player shooter)) return; if (event.getEntity().getShooter() == null) return; - Player shooter = (Player) event.getEntity().getShooter(); - if (lastFirework.getIfPresent(shooter.getUniqueId()) == null) { launchFirework(shooter, event.getEntity().getLocation()); } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/items/GrapplingHookMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/items/GrapplingHookMutation.java index d9923a5d..d404789c 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/items/GrapplingHookMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/items/GrapplingHookMutation.java @@ -107,8 +107,7 @@ public void onPlayerFishEvent(PlayerFishEvent event) { @EventHandler(ignoreCancelled = true) public void onDamage(EntityDamageByEntityEvent event) { - if (!(event.getDamager() instanceof FishHook)) return; - FishHook fishHook = (FishHook) event.getDamager(); + if (!(event.getDamager() instanceof FishHook fishHook)) return; if (!(fishHook.getShooter() instanceof Player)) return; // Cancel damage if caused by a grappling hook diff --git a/core/src/main/java/dev/pgm/community/mutations/types/items/PotionMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/items/PotionMutation.java index 7a1b15ec..2ac78fbd 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/items/PotionMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/items/PotionMutation.java @@ -25,7 +25,7 @@ /** PotionMutation - Random potions given on spawn and when mining blocks * */ public class PotionMutation extends KitMutationBase { - private static double SPLASH_CHANCE = 0.05; + private static final double SPLASH_CHANCE = 0.05; public PotionMutation(Match match) { super(match, MutationType.POTION); diff --git a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java index a6323f57..67419d78 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/DoubleJumpMutation.java @@ -18,11 +18,10 @@ /** DoubleJumpMutation - Enables {@link DoubleJumpKit} and no fall damage for all players * */ public class DoubleJumpMutation extends KitMutationBase { - private static MutationRangeOption JUMP_POWER = - new MutationRangeOption( - "Jump Power", "Power of double jump", MutationType.JUMP.getMaterial(), true, 2, 1, 10); + private static final MutationRangeOption JUMP_POWER = new MutationRangeOption( + "Jump Power", "Power of double jump", MutationType.JUMP.getMaterial(), true, 2, 1, 10); - private DoubleJumpKit disabledKit = getJumpKit(false); + private final DoubleJumpKit disabledKit; public DoubleJumpMutation(Match match) { super(match, MutationType.JUMP, getJumpKit(true)); diff --git a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java index 3ecf9926..69c79545 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FlyMutation.java @@ -2,6 +2,7 @@ import static net.kyori.adventure.text.Component.space; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.title.Title.Times.times; import static net.kyori.adventure.title.Title.title; import com.google.common.collect.Sets; @@ -17,7 +18,6 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.title.Title.Times; import net.kyori.adventure.util.Ticks; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -28,19 +28,17 @@ /** FlyMutation - Enables the {@link FlyKit} for all players */ public class FlyMutation extends KitMutationBase { - private static MutationRangeOption FLY_DISABLE_DELAY = - new MutationRangeOption( - "Flight Disable countdown", - "Delay before flight is disabled", - MutationType.FLY.getMaterial(), - false, - 5, - 0, - 20); + private static final MutationRangeOption FLY_DISABLE_DELAY = new MutationRangeOption( + "Flight Disable countdown", + "Delay before flight is disabled", + MutationType.FLY.getMaterial(), + false, + 5, + 0, + 20); - private static MutationRangeOption FLY_SPEED = - new MutationRangeOption( - "Flight Speed", "Speed of flight", MutationType.FLY.getMaterial(), true, 1, 1, 5); + private static final MutationRangeOption FLY_SPEED = new MutationRangeOption( + "Flight Speed", "Speed of flight", MutationType.FLY.getMaterial(), true, 1, 1, 5); private int disableTaskID; private boolean disableTaskEnabled; @@ -57,12 +55,11 @@ public Collection getOptions() { @Override public void disable() { if (!match.isFinished()) { - this.disableTaskID = - Community.get() - .getServer() - .getScheduler() - .scheduleSyncRepeatingTask( - Community.get(), new DisableFlightTask(FLY_DISABLE_DELAY.getValue()), 0L, 20L); + this.disableTaskID = Community.get() + .getServer() + .getScheduler() + .scheduleSyncRepeatingTask( + Community.get(), new DisableFlightTask(FLY_DISABLE_DELAY.getValue()), 0L, 20L); this.disableTaskEnabled = true; } else { super.disable(); @@ -104,23 +101,18 @@ public void run() { remove(); } else { Component time = text(seconds, NamedTextColor.RED, TextDecoration.BOLD); - Component left = - text() - .append(text("second")) - .append(text(seconds != 1 ? "s" : "")) - .append(text(" left to land")) - .color(NamedTextColor.GRAY) - .build(); - BroadcastUtils.sendGlobalMessage(text().append(time).append(space()).append(left).build()); + Component left = text() + .append(text("second")) + .append(text(seconds != 1 ? "s" : "")) + .append(text(" left to land")) + .color(NamedTextColor.GRAY) + .build(); + BroadcastUtils.sendGlobalMessage( + text().append(time).append(space()).append(left).build()); match .getParticipants() - .forEach( - player -> - player.showTitle( - title( - time, - left, - Times.of(Ticks.duration(0), Ticks.duration(20), Ticks.duration(5))))); + .forEach(player -> player.showTitle(title( + time, left, times(Ticks.duration(0), Ticks.duration(20), Ticks.duration(5))))); seconds--; } } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FriendlyFireMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FriendlyFireMutation.java index 4557cd0f..a9095274 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FriendlyFireMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/FriendlyFireMutation.java @@ -36,9 +36,7 @@ private void forceTeamUpdate() { ScoreboardMatchModule smm = match.getModule(ScoreboardMatchModule.class); if (smm == null) return; smm.getScoreboards() - .forEach( - board -> { - board.getTeams().forEach(team -> team.setAllowFriendlyFire(match.getFriendlyFire())); - }); + .forEach(board -> + board.getTeams().forEach(team -> team.setAllowFriendlyFire(match.getFriendlyFire()))); } } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java index edcfe7cf..28a79205 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/mechanics/MobMutation.java @@ -24,7 +24,7 @@ import org.bukkit.entity.Skeleton.SkeletonType; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.util.Vector; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.api.match.Match; import tc.oc.pgm.api.party.Party; import tc.oc.pgm.api.player.MatchPlayer; @@ -41,7 +41,7 @@ public class MobMutation extends ScheduledMutationBase { private static final int RANDOM_DISTANCE = 45; private static final String MOB_METADATA = "mob-mutation"; - private static MutationListOption TOTAL_MOBS = new MutationListOption<>( + private static final MutationListOption TOTAL_MOBS = new MutationListOption<>( "Total Mobs", "Total number of mobs spawned", MutationType.MOBS.getMaterial(), @@ -101,7 +101,7 @@ private RandomPointProvider getPointProvider() { return null; } - private EntityType[] MOB_TYPES = { + private final EntityType[] MOB_TYPES = { EntityType.ZOMBIE, EntityType.SKELETON, EntityType.SPIDER, diff --git a/core/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java index f4704270..f25b0b49 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/world/BlockDecayMutation.java @@ -23,17 +23,16 @@ public class BlockDecayMutation extends ScheduledMutationBase { - private static MutationRangeOption DECAY_SECONDS = - new MutationRangeOption( - "Decay Delay", - "Delay of time before blocks decay", - MutationType.BLOCK_DECAY.getMaterial(), - false, - 5, - 1, - 60); + private static final MutationRangeOption DECAY_SECONDS = new MutationRangeOption( + "Decay Delay", + "Delay of time before blocks decay", + MutationType.BLOCK_DECAY.getMaterial(), + false, + 5, + 1, + 60); - private Map placedBlocks = Maps.newHashMap(); + private final Map placedBlocks = Maps.newHashMap(); public BlockDecayMutation(Match match) { super(match, MutationType.BLOCK_DECAY, 1); @@ -51,7 +50,7 @@ public boolean canEnable(Set existing) { @Override public void disable() { - if (this.placedBlocks != null && !this.placedBlocks.isEmpty()) { + if (!this.placedBlocks.isEmpty()) { this.placedBlocks.keySet().forEach(location -> location.getBlock().setType(Material.AIR)); this.placedBlocks.clear(); } diff --git a/core/src/main/java/dev/pgm/community/mutations/types/world/StormMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/world/StormMutation.java index 2d0b3ef4..0d303323 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/world/StormMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/world/StormMutation.java @@ -7,7 +7,6 @@ import dev.pgm.community.mutations.types.ScheduledMutationBase; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.event.EventHandler; @@ -67,10 +66,8 @@ private void delayedStrike(final MatchPlayer player, int delay) { Bukkit.getScheduler() .scheduleSyncDelayedTask( Community.get(), - () -> { - match.getWorld().spigot().strikeLightning(player.getLocation(), false); - }, - 20 * delay); + () -> match.getWorld().spigot().strikeLightning(player.getLocation(), false), + 20L * delay); } @EventHandler(priority = EventPriority.HIGH) @@ -80,7 +77,7 @@ public void onWeatherChange(WeatherChangeEvent event) { private Set selectRandomPlayers(int amount) { Set chosen = Sets.newHashSet(); - List everyone = match.getParticipants().stream().collect(Collectors.toList()); + List everyone = match.getParticipants().stream().toList(); if (!everyone.isEmpty()) { int retrys = 0; while (chosen.size() < amount && retrys < 5) { diff --git a/core/src/main/java/dev/pgm/community/mutations/types/world/TNTRainMutation.java b/core/src/main/java/dev/pgm/community/mutations/types/world/TNTRainMutation.java index bf06564d..bde4f199 100644 --- a/core/src/main/java/dev/pgm/community/mutations/types/world/TNTRainMutation.java +++ b/core/src/main/java/dev/pgm/community/mutations/types/world/TNTRainMutation.java @@ -26,6 +26,7 @@ * @deprecated Keeping for future use... TNTRainMutation - Spawns falling primed TNT on a scheduled * interval, with no damage to players */ +@Deprecated public class TNTRainMutation extends ScheduledMutationBase { private static final int TASK_SECONDS = 30; @@ -56,7 +57,7 @@ public boolean canEnable(Set existing) { @Override public void run() { - List players = new ArrayList(match.getParticipants()); + List players = new ArrayList<>(match.getParticipants()); if (players.isEmpty()) return; List spawned = Lists.newArrayList(); while (spawned.size() < Math.min(MAX_PLAYERS_PER_RUN, players.size())) { @@ -70,8 +71,7 @@ public void run() { @EventHandler public void onTNTDamagePrevention(EntityDamageByEntityEvent event) { - if (event.getDamager() instanceof TNTPrimed && event.getEntity() instanceof Player) { - TNTPrimed tnt = (TNTPrimed) event.getDamager(); + if (event.getDamager() instanceof TNTPrimed tnt && event.getEntity() instanceof Player) { if (tnt.hasMetadata(TNT_META)) { event.setDamage(0); } @@ -80,8 +80,7 @@ public void onTNTDamagePrevention(EntityDamageByEntityEvent event) { @EventHandler public void onTNTExplode(EntityExplodeEvent event) { - if (event.getEntity() instanceof TNTPrimed) { - TNTPrimed tnt = (TNTPrimed) event.getEntity(); + if (event.getEntity() instanceof TNTPrimed tnt) { if (tnt.hasMetadata(TNT_META)) { event.setYield(random.nextFloat() + 1f); diff --git a/core/src/main/java/dev/pgm/community/network/Channels.java b/core/src/main/java/dev/pgm/community/network/Channels.java index dfc16eb2..aadb9407 100644 --- a/core/src/main/java/dev/pgm/community/network/Channels.java +++ b/core/src/main/java/dev/pgm/community/network/Channels.java @@ -15,7 +15,7 @@ public class Channels { // PUNISHMENT_UPDATE - Used to alert servers of unmuted or unbanned players public static final String PUNISHMENT_UPDATE = formatChannel("punishment_update"); - private static final String formatChannel(String name) { + private static String formatChannel(String name) { return "community_" + name; } } diff --git a/core/src/main/java/dev/pgm/community/network/subs/NetworkSubscriber.java b/core/src/main/java/dev/pgm/community/network/subs/NetworkSubscriber.java index 4a6e88e7..334ce022 100644 --- a/core/src/main/java/dev/pgm/community/network/subs/NetworkSubscriber.java +++ b/core/src/main/java/dev/pgm/community/network/subs/NetworkSubscriber.java @@ -7,8 +7,8 @@ public abstract class NetworkSubscriber extends JedisPubSub { - private String channel; - private String networkId; + private final String channel; + private final String networkId; protected Logger logger; protected Gson gson; diff --git a/core/src/main/java/dev/pgm/community/network/subs/types/AssistanceSubscriber.java b/core/src/main/java/dev/pgm/community/network/subs/types/AssistanceSubscriber.java index 27a930df..cc1acfb4 100644 --- a/core/src/main/java/dev/pgm/community/network/subs/types/AssistanceSubscriber.java +++ b/core/src/main/java/dev/pgm/community/network/subs/types/AssistanceSubscriber.java @@ -9,7 +9,7 @@ /** AssistanceSubscriber - Listens for {@link AssistanceRequest} */ public class AssistanceSubscriber extends NetworkSubscriber { - private AssistanceFeature assist; + private final AssistanceFeature assist; public AssistanceSubscriber(AssistanceFeature assist, String networkId, Logger logger) { super(Channels.ASSISTANCE, networkId, logger); diff --git a/core/src/main/java/dev/pgm/community/network/subs/types/ChatSubscriber.java b/core/src/main/java/dev/pgm/community/network/subs/types/ChatSubscriber.java index 46c201aa..1e32df50 100644 --- a/core/src/main/java/dev/pgm/community/network/subs/types/ChatSubscriber.java +++ b/core/src/main/java/dev/pgm/community/network/subs/types/ChatSubscriber.java @@ -9,7 +9,7 @@ /** ChatSubscriber - Listens for {@link NetworkChatMessage} */ public class ChatSubscriber extends NetworkSubscriber { - private NetworkChatFeature chat; + private final NetworkChatFeature chat; public ChatSubscriber(NetworkChatFeature chat, String networkId, Logger logger) { super(Channels.CHAT, networkId, logger); diff --git a/core/src/main/java/dev/pgm/community/network/subs/types/PunishmentSubscriber.java b/core/src/main/java/dev/pgm/community/network/subs/types/PunishmentSubscriber.java index d1d17c83..0cf9925e 100644 --- a/core/src/main/java/dev/pgm/community/network/subs/types/PunishmentSubscriber.java +++ b/core/src/main/java/dev/pgm/community/network/subs/types/PunishmentSubscriber.java @@ -9,7 +9,7 @@ /** PunishmentSubscriber - Listens for {@link NetworkPunishment} */ public class PunishmentSubscriber extends NetworkSubscriber { - private ModerationFeature moderation; + private final ModerationFeature moderation; public PunishmentSubscriber(ModerationFeature moderation, String networkId, Logger logger) { super(Channels.PUNISHMENTS, networkId, logger); diff --git a/core/src/main/java/dev/pgm/community/network/subs/types/RefreshPunishmentSubscriber.java b/core/src/main/java/dev/pgm/community/network/subs/types/RefreshPunishmentSubscriber.java index 88d28e8e..b9d568a2 100644 --- a/core/src/main/java/dev/pgm/community/network/subs/types/RefreshPunishmentSubscriber.java +++ b/core/src/main/java/dev/pgm/community/network/subs/types/RefreshPunishmentSubscriber.java @@ -9,7 +9,7 @@ /** RefreshPunishmentSubscriber - Invalidates punishment cache for unbans/unmutes */ public class RefreshPunishmentSubscriber extends NetworkSubscriber { - private ModerationFeature moderation; + private final ModerationFeature moderation; public RefreshPunishmentSubscriber( ModerationFeature moderation, String networkId, Logger logger) { @@ -24,9 +24,8 @@ public void onReceiveUpdate(String data) { moderation.recieveRefresh(playerId); logger.info(String.format("Refreshed punishment data for %s", data)); } catch (IllegalArgumentException e) { - logger.warning( - String.format( - "Invalid UUID (%s) recieved for message channel (%s)", Channels.PUNISHMENTS, data)); + logger.warning(String.format( + "Invalid UUID (%s) recieved for message channel (%s)", Channels.PUNISHMENTS, data)); } } } diff --git a/core/src/main/java/dev/pgm/community/network/types/RedisNetworkFeature.java b/core/src/main/java/dev/pgm/community/network/types/RedisNetworkFeature.java index ad95622c..c686b8ab 100644 --- a/core/src/main/java/dev/pgm/community/network/types/RedisNetworkFeature.java +++ b/core/src/main/java/dev/pgm/community/network/types/RedisNetworkFeature.java @@ -19,7 +19,7 @@ public class RedisNetworkFeature extends NetworkFeatureBase { private JedisPool pool; - private Set subscribers; + private final Set subscribers; public RedisNetworkFeature(Configuration config, Logger logger) { super(config, logger, "Network (Redis)"); @@ -33,19 +33,18 @@ public void registerSubscriber(NetworkSubscriber sub) { @Override public void enable() { super.enable(); - this.pool = - new JedisPool( - new JedisPoolConfig(), - getNetworkConfig().getHost(), - getNetworkConfig().getPort(), - Protocol.DEFAULT_TIMEOUT, - getNetworkConfig().getPassword(), - getNetworkConfig().isSSL()); + this.pool = new JedisPool( + new JedisPoolConfig(), + getNetworkConfig().getHost(), + getNetworkConfig().getPort(), + Protocol.DEFAULT_TIMEOUT, + getNetworkConfig().getPassword(), + getNetworkConfig().isSSL()); testConnection(); // Delay subscriber so all features can register - Community.get().getServer().getScheduler().runTaskLater(Community.get(), this::subscribe, 20l); + Community.get().getServer().getScheduler().runTaskLater(Community.get(), this::subscribe, 20L); } @Override @@ -72,34 +71,24 @@ private void subscribe() { } private void asyncSubscribe(NetworkSubscriber sub) { - Community.get() - .getServer() - .getScheduler() - .runTaskAsynchronously( - Community.get(), - () -> { - try (Jedis jedi = pool.getResource()) { - jedi.subscribe(sub, sub.getChannel()); - } - }); + Community.get().getServer().getScheduler().runTaskAsynchronously(Community.get(), () -> { + try (Jedis jedi = pool.getResource()) { + jedi.subscribe(sub, sub.getChannel()); + } + }); } @Override public void sendUpdate(NetworkUpdate update) { if (!isEnabled()) return; - Community.get() - .getServer() - .getScheduler() - .runTaskAsynchronously( - Community.get(), - () -> { - if (pool != null) { - try (Jedis jedi = pool.getResource()) { - jedi.publish( - update.getChannel(), - String.format("%s;%s", getNetworkConfig().getNetworkId(), update.getData())); - } - } - }); + Community.get().getServer().getScheduler().runTaskAsynchronously(Community.get(), () -> { + if (pool != null) { + try (Jedis jedi = pool.getResource()) { + jedi.publish( + update.getChannel(), + String.format("%s;%s", getNetworkConfig().getNetworkId(), update.getData())); + } + } + }); } } diff --git a/core/src/main/java/dev/pgm/community/network/updates/NetworkUpdateBase.java b/core/src/main/java/dev/pgm/community/network/updates/NetworkUpdateBase.java index a83eec07..bcc59f48 100644 --- a/core/src/main/java/dev/pgm/community/network/updates/NetworkUpdateBase.java +++ b/core/src/main/java/dev/pgm/community/network/updates/NetworkUpdateBase.java @@ -5,9 +5,9 @@ public abstract class NetworkUpdateBase implements NetworkUpdate { - private T item; - private String channel; - private Gson gson; + private final T item; + private final String channel; + private final Gson gson; public NetworkUpdateBase(T item, String channel) { this.item = item; diff --git a/core/src/main/java/dev/pgm/community/network/updates/types/RefreshPunishmentUpdate.java b/core/src/main/java/dev/pgm/community/network/updates/types/RefreshPunishmentUpdate.java index e6ae1b10..ae3ea667 100644 --- a/core/src/main/java/dev/pgm/community/network/updates/types/RefreshPunishmentUpdate.java +++ b/core/src/main/java/dev/pgm/community/network/updates/types/RefreshPunishmentUpdate.java @@ -5,13 +5,7 @@ import java.util.UUID; /** RefreshPunishmentUpdate - Called on ban pardon or unmute */ -public class RefreshPunishmentUpdate implements NetworkUpdate { - - private final UUID playerId; - - public RefreshPunishmentUpdate(UUID playerId) { - this.playerId = playerId; - } +public record RefreshPunishmentUpdate(UUID playerId) implements NetworkUpdate { @Override public String getChannel() { diff --git a/core/src/main/java/dev/pgm/community/nick/Nick.java b/core/src/main/java/dev/pgm/community/nick/Nick.java index c41e8c8b..f4a6cdb2 100644 --- a/core/src/main/java/dev/pgm/community/nick/Nick.java +++ b/core/src/main/java/dev/pgm/community/nick/Nick.java @@ -48,7 +48,7 @@ default void clear() { setEnabled(false); } - public static Nick of(UUID playerId, String nick) { + static Nick of(UUID playerId, String nick) { return new NickImpl(playerId, nick, Instant.now(), true); } } diff --git a/core/src/main/java/dev/pgm/community/nick/NickImpl.java b/core/src/main/java/dev/pgm/community/nick/NickImpl.java index 42700c33..2e08b15b 100644 --- a/core/src/main/java/dev/pgm/community/nick/NickImpl.java +++ b/core/src/main/java/dev/pgm/community/nick/NickImpl.java @@ -5,7 +5,7 @@ public class NickImpl implements Nick { - private UUID playerId; + private final UUID playerId; private String nickName; private Instant date; private boolean enabled; diff --git a/core/src/main/java/dev/pgm/community/nick/commands/NickCommands.java b/core/src/main/java/dev/pgm/community/nick/commands/NickCommands.java index 75284c72..4c503336 100644 --- a/core/src/main/java/dev/pgm/community/nick/commands/NickCommands.java +++ b/core/src/main/java/dev/pgm/community/nick/commands/NickCommands.java @@ -25,7 +25,7 @@ import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.api.integration.Integration; import tc.oc.pgm.lib.org.incendo.cloud.annotations.Argument; import tc.oc.pgm.lib.org.incendo.cloud.annotations.Command; @@ -59,10 +59,10 @@ public void checkNickStatus( if (viewer.hasPermission(CommunityPermissions.NICKNAME_OTHER) && target != null) { getTarget(target, users).thenAcceptAsync(uuid -> { if (uuid.isPresent()) { - users.renderUsername(uuid, NameStyle.FANCY).thenAcceptAsync(name -> { - sendNickStatus(viewer, viewer.getPlayer(), uuid.get(), name); - return; - }); + users + .renderUsername(uuid, NameStyle.FANCY) + .thenAcceptAsync( + name -> sendNickStatus(viewer, viewer.getPlayer(), uuid.get(), name)); } else { viewer.sendWarning(formatNotFoundComponent(target)); } @@ -239,15 +239,15 @@ public void setOtherNick( if (uuid.isPresent()) { nicks.setNick(uuid.get(), nick).thenAcceptAsync(success -> { if (success) { - users.renderUsername(uuid, NameStyle.FANCY).thenAcceptAsync(name -> { - viewer.sendMessage(text() - .append(text("Nickname for ")) - .append(name) - .append(text(" set to ")) - .append(text(nick, NamedTextColor.AQUA, TextDecoration.BOLD)) - .color(NamedTextColor.GRAY) - .build()); - }); + users + .renderUsername(uuid, NameStyle.FANCY) + .thenAcceptAsync(name -> viewer.sendMessage(text() + .append(text("Nickname for ")) + .append(name) + .append(text(" set to ")) + .append(text(nick, NamedTextColor.AQUA, TextDecoration.BOLD)) + .color(NamedTextColor.GRAY) + .build())); } else { viewer.sendWarning(text() .append(text("Could not set nickname for ")) @@ -269,21 +269,21 @@ public void clearNick(CommandAudience viewer, @Argument("target") TargetPlayer t if (viewer.hasPermission(CommunityPermissions.NICKNAME_CLEAR) && target != null) { getTarget(target.getIdentifier(), users).thenAcceptAsync(uuid -> { if (uuid.isPresent()) { - users.renderUsername(uuid, NameStyle.FANCY).thenAcceptAsync(name -> { - nicks.clearNick(uuid.get()).thenAcceptAsync(success -> { - Component setName = text() - .append(text("You have reset the nickname of ")) - .append(name) - .color(NamedTextColor.GREEN) - .build(); - Component noName = text() - .append(name) - .append(text(" does not have a nickname set")) - .color(NamedTextColor.RED) - .build(); - viewer.sendWarning(success ? setName : noName); - }); - }); + users + .renderUsername(uuid, NameStyle.FANCY) + .thenAcceptAsync(name -> nicks.clearNick(uuid.get()).thenAcceptAsync(success -> { + Component setName = text() + .append(text("You have reset the nickname of ")) + .append(name) + .color(NamedTextColor.GREEN) + .build(); + Component noName = text() + .append(name) + .append(text(" does not have a nickname set")) + .color(NamedTextColor.RED) + .build(); + viewer.sendWarning(success ? setName : noName); + })); } else { viewer.sendWarning(formatNotFoundComponent(target.getIdentifier())); } @@ -294,11 +294,11 @@ public void clearNick(CommandAudience viewer, @Argument("target") TargetPlayer t if (!viewer.isPlayer()) return; // Reset own nickname - nicks.clearNick(viewer.getPlayer().getUniqueId()).thenAcceptAsync(success -> { - viewer.sendWarning(text( - success ? "You have reset your nickname" : "You do not have a nickname set", - success ? NamedTextColor.GRAY : NamedTextColor.RED)); - }); + nicks + .clearNick(viewer.getPlayer().getUniqueId()) + .thenAcceptAsync(success -> viewer.sendWarning(text( + success ? "You have reset your nickname" : "You do not have a nickname set", + success ? NamedTextColor.GRAY : NamedTextColor.RED))); } @Command("toggle") diff --git a/core/src/main/java/dev/pgm/community/nick/data/NickSelection.java b/core/src/main/java/dev/pgm/community/nick/data/NickSelection.java index 09c82b1f..d5854156 100644 --- a/core/src/main/java/dev/pgm/community/nick/data/NickSelection.java +++ b/core/src/main/java/dev/pgm/community/nick/data/NickSelection.java @@ -6,8 +6,8 @@ public class NickSelection { - private List names; - private Instant lastRefresh; + private final List names; + private final Instant lastRefresh; public NickSelection(List names) { this.names = names; diff --git a/core/src/main/java/dev/pgm/community/nick/feature/PGMNickIntegration.java b/core/src/main/java/dev/pgm/community/nick/feature/PGMNickIntegration.java index 593c761e..827353d7 100644 --- a/core/src/main/java/dev/pgm/community/nick/feature/PGMNickIntegration.java +++ b/core/src/main/java/dev/pgm/community/nick/feature/PGMNickIntegration.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; @@ -21,9 +20,9 @@ public class PGMNickIntegration implements NickIntegration { private boolean hotbarColor = false; - private NickFeature nick; + private final NickFeature nick; - private Future hotbarTask; + private final Future hotbarTask; public PGMNickIntegration(NickFeature nick) { this.nick = nick; @@ -44,10 +43,9 @@ public void cancelTask() { private void updateHotbars() { Match match = PGMUtils.getMatch(); if (match != null) { - List nicked = - match.getPlayers().stream() - .filter(p -> nick.isNicked(p.getId()) && !Integration.isVanished(p.getBukkit())) - .collect(Collectors.toList()); + List nicked = match.getPlayers().stream() + .filter(p -> nick.isNicked(p.getId()) && !Integration.isVanished(p.getBukkit())) + .toList(); nicked.forEach(mp -> sendHotbarNicked(mp, hotbarColor)); } hotbarColor = !hotbarColor; diff --git a/core/src/main/java/dev/pgm/community/nick/feature/types/NickFeatureCore.java b/core/src/main/java/dev/pgm/community/nick/feature/types/NickFeatureCore.java index 07f4c0eb..ba270e41 100644 --- a/core/src/main/java/dev/pgm/community/nick/feature/types/NickFeatureCore.java +++ b/core/src/main/java/dev/pgm/community/nick/feature/types/NickFeatureCore.java @@ -41,7 +41,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.text.TextFormatter; @@ -121,7 +121,7 @@ public Player getPlayerFromNick(String nickName) { .filter((e) -> e.getValue().equalsIgnoreCase(nickName)) .map(Entry::getKey) .findAny(); - return player.isPresent() ? Bukkit.getPlayer(player.get()) : null; + return player.map(Bukkit::getPlayer).orElse(null); } @Override @@ -179,18 +179,18 @@ public void onJoin(PlayerJoinEvent event) { sendLoginNotification(player, nick.getName(), false); } else { // Auto apply a random name if none set - WebUtils.getRandomName().thenAcceptAsync(name -> { - this.setNick(player.getUniqueId(), name).thenAcceptAsync(success -> { - if (success) { - nickedPlayers.put(player.getUniqueId(), nick.getName()); - Audience.get(player) - .sendWarning(text( - "You had no nickname, so a random one has been assigned", - NamedTextColor.GREEN)); - sendLoginNotification(player, nick.getName(), true); - } - }); - }); + WebUtils.getRandomName() + .thenAcceptAsync( + name -> this.setNick(player.getUniqueId(), name).thenAcceptAsync(success -> { + if (success) { + nickedPlayers.put(player.getUniqueId(), nick.getName()); + Audience.get(player) + .sendWarning(text( + "You had no nickname, so a random one has been assigned", + NamedTextColor.GREEN)); + sendLoginNotification(player, nick.getName(), true); + } + })); } } else { diff --git a/core/src/main/java/dev/pgm/community/nick/services/NickQuery.java b/core/src/main/java/dev/pgm/community/nick/services/NickQuery.java index 9dde8307..2eeaeaa3 100644 --- a/core/src/main/java/dev/pgm/community/nick/services/NickQuery.java +++ b/core/src/main/java/dev/pgm/community/nick/services/NickQuery.java @@ -2,19 +2,19 @@ public interface NickQuery { - static final String TABLE_NAME = "nicknames"; - static final String TABLE_FIELDS = + String TABLE_NAME = "nicknames"; + String TABLE_FIELDS = "(playerId VARCHAR(36) PRIMARY KEY, nickname VARCHAR(16), date LONG, enabled BOOL)"; - static final String INSERT_NICKNAME_QUERY = + String INSERT_NICKNAME_QUERY = "INSERT INTO " + TABLE_NAME + "(playerId, nickname, date, enabled) VALUES (?,?,?,?)"; - static final String SELECT_NICKNAME_BY_ID_QUERY = + String SELECT_NICKNAME_BY_ID_QUERY = "SELECT * from " + TABLE_NAME + " where playerId = ? LIMIT 1"; - static final String UPDATE_NICKNAME_QUERY = + String UPDATE_NICKNAME_QUERY = "UPDATE " + TABLE_NAME + " set nickname = ?, enabled = ?, date = ? where playerId = ?"; - static final String SELECT_NICKNAME_BY_NAME_QUERY = + String SELECT_NICKNAME_BY_NAME_QUERY = "SELECT * from " + TABLE_NAME + " where LOWER(nickname) = LOWER(?)"; } diff --git a/core/src/main/java/dev/pgm/community/nick/services/SQLNickService.java b/core/src/main/java/dev/pgm/community/nick/services/SQLNickService.java index 8cec5f75..45a45d30 100644 --- a/core/src/main/java/dev/pgm/community/nick/services/SQLNickService.java +++ b/core/src/main/java/dev/pgm/community/nick/services/SQLNickService.java @@ -10,12 +10,13 @@ import dev.pgm.community.nick.NickImpl; import java.time.Instant; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.concurrent.CompletableFuture; public class SQLNickService extends SQLFeatureBase implements NickQuery { - private LoadingCache nickCache; + private final LoadingCache nickCache; public SQLNickService(NickConfig config) { super(TABLE_NAME, TABLE_FIELDS); @@ -87,7 +88,7 @@ public CompletableFuture update(Nick nick) { } public CompletableFuture isNameAvailable(String name) { - return queryByName(name).thenApplyAsync(results -> results == null); + return queryByName(name).thenApplyAsync(Objects::isNull); } public CompletableFuture queryByName(String name) { @@ -103,7 +104,7 @@ public CompletableFuture queryByName(String name) { name); } - private class NickInfo { + private static class NickInfo { private final UUID playerId; private Nick nick; diff --git a/core/src/main/java/dev/pgm/community/nick/skin/SkinCache.java b/core/src/main/java/dev/pgm/community/nick/skin/SkinCache.java index 2d3a97cb..2469719f 100644 --- a/core/src/main/java/dev/pgm/community/nick/skin/SkinCache.java +++ b/core/src/main/java/dev/pgm/community/nick/skin/SkinCache.java @@ -12,7 +12,6 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -42,7 +41,7 @@ private Skin getRandomSkin() { if (offlineSkins.size() == 0) { return Skin.EMPTY; // TODO: Warning, this may be bad for 1.16 clients... } - List skins = offlineSkins.asMap().values().stream().collect(Collectors.toList()); + List skins = offlineSkins.asMap().values().stream().toList(); return skins.get(random.nextInt(skins.size())); } diff --git a/core/src/main/java/dev/pgm/community/nick/skin/SkinManager.java b/core/src/main/java/dev/pgm/community/nick/skin/SkinManager.java index 406e52af..a2cbb56b 100644 --- a/core/src/main/java/dev/pgm/community/nick/skin/SkinManager.java +++ b/core/src/main/java/dev/pgm/community/nick/skin/SkinManager.java @@ -6,7 +6,7 @@ public class SkinManager { - private SkinCache cache; + private final SkinCache cache; public SkinManager() { this.cache = new SkinCache(); diff --git a/core/src/main/java/dev/pgm/community/party/MapPartyBase.java b/core/src/main/java/dev/pgm/community/party/MapPartyBase.java index 1d9eb591..b932f1e9 100644 --- a/core/src/main/java/dev/pgm/community/party/MapPartyBase.java +++ b/core/src/main/java/dev/pgm/community/party/MapPartyBase.java @@ -23,8 +23,8 @@ public abstract class MapPartyBase implements MapParty { private String name; private String description; private Duration length; - private MapPartyHosts hosts; - private MapPartySettings settings; + private final MapPartyHosts hosts; + private final MapPartySettings settings; private boolean running; private boolean setup; diff --git a/core/src/main/java/dev/pgm/community/party/MapPartyCommands.java b/core/src/main/java/dev/pgm/community/party/MapPartyCommands.java index 6bd96486..c1316779 100644 --- a/core/src/main/java/dev/pgm/community/party/MapPartyCommands.java +++ b/core/src/main/java/dev/pgm/community/party/MapPartyCommands.java @@ -196,7 +196,7 @@ public void addHost(CommandAudience viewer, @Argument("targets") String targets) if (isPartyMissing(viewer)) return; MapPartyHosts hosts = party.getParty().getHosts(); PlayerSelection selection = getPlayers(viewer, targets); - selection.getPlayers().forEach(player -> { + selection.players().forEach(player -> { if (!party.canHost(player)) { viewer.sendWarning(MapPartyMessages.getAddHostError(player)); return; diff --git a/core/src/main/java/dev/pgm/community/party/MapPartyConfig.java b/core/src/main/java/dev/pgm/community/party/MapPartyConfig.java index 4beb01b4..3808ce49 100644 --- a/core/src/main/java/dev/pgm/community/party/MapPartyConfig.java +++ b/core/src/main/java/dev/pgm/community/party/MapPartyConfig.java @@ -195,7 +195,7 @@ private Permission parsePermissions(List permissions) { // Register permission try { Community.get().getServer().getPluginManager().addPermission(permission); - } catch (Throwable t) { + } catch (Throwable ignored) { } return permission; } diff --git a/core/src/main/java/dev/pgm/community/party/MapPartyStatusType.java b/core/src/main/java/dev/pgm/community/party/MapPartyStatusType.java index cc2be7fa..824695a1 100644 --- a/core/src/main/java/dev/pgm/community/party/MapPartyStatusType.java +++ b/core/src/main/java/dev/pgm/community/party/MapPartyStatusType.java @@ -10,8 +10,8 @@ public enum MapPartyStatusType { END("stopped", NamedTextColor.RED), RESTART("restarted", NamedTextColor.DARK_GREEN); - String name; - NamedTextColor color; + final String name; + final NamedTextColor color; MapPartyStatusType(String name, NamedTextColor color) { this.name = name; diff --git a/core/src/main/java/dev/pgm/community/party/MapPartyType.java b/core/src/main/java/dev/pgm/community/party/MapPartyType.java index 931f470e..4cab411b 100644 --- a/core/src/main/java/dev/pgm/community/party/MapPartyType.java +++ b/core/src/main/java/dev/pgm/community/party/MapPartyType.java @@ -7,8 +7,8 @@ public enum MapPartyType { REGULAR(Material.IRON_INGOT, "Use an existing map pool"), CUSTOM(Material.GOLD_INGOT, "Select a custom list of maps"); - private Material material; - private String description; + private final Material material; + private final String description; MapPartyType(Material material, String description) { this.material = material; @@ -28,7 +28,7 @@ public Material getMaterial() { } public static MapPartyType parse(String name) { - if (name.toLowerCase().equalsIgnoreCase("custom")) { + if (name.equalsIgnoreCase("custom")) { return MapPartyType.CUSTOM; } return MapPartyType.REGULAR; diff --git a/core/src/main/java/dev/pgm/community/party/broadcasts/MapPartyBroadcastManager.java b/core/src/main/java/dev/pgm/community/party/broadcasts/MapPartyBroadcastManager.java index 7c6e27c7..abb3802c 100644 --- a/core/src/main/java/dev/pgm/community/party/broadcasts/MapPartyBroadcastManager.java +++ b/core/src/main/java/dev/pgm/community/party/broadcasts/MapPartyBroadcastManager.java @@ -22,8 +22,8 @@ public class MapPartyBroadcastManager { - private MapPartyFeature feature; - private MapPartyConfig config; + private final MapPartyFeature feature; + private final MapPartyConfig config; private int taskId = -1; private int lineIndex; @@ -143,10 +143,10 @@ private static boolean hasTimePassed(Instant last, Duration duration) { private class EventBroadcastLine { - private String message; - private String command; - private String hover; - private Duration interval; + private final String message; + private final String command; + private final String hover; + private final Duration interval; private Instant lastBroadcast; private final Component DEFAULT_HOVER = text("Click to view more info", NamedTextColor.GRAY); diff --git a/core/src/main/java/dev/pgm/community/party/exceptions/MapPartyException.java b/core/src/main/java/dev/pgm/community/party/exceptions/MapPartyException.java index 71f05a5e..5616eb66 100644 --- a/core/src/main/java/dev/pgm/community/party/exceptions/MapPartyException.java +++ b/core/src/main/java/dev/pgm/community/party/exceptions/MapPartyException.java @@ -4,7 +4,7 @@ public abstract class MapPartyException extends Exception { - private MapParty party; + private final MapParty party; public MapPartyException(MapParty party, String error) { super(error); diff --git a/core/src/main/java/dev/pgm/community/party/feature/MapPartyFeature.java b/core/src/main/java/dev/pgm/community/party/feature/MapPartyFeature.java index 27527e71..4f23e858 100644 --- a/core/src/main/java/dev/pgm/community/party/feature/MapPartyFeature.java +++ b/core/src/main/java/dev/pgm/community/party/feature/MapPartyFeature.java @@ -1,7 +1,6 @@ package dev.pgm.community.party.feature; import static dev.pgm.community.party.MapPartyMessages.formatTime; -import static dev.pgm.community.utils.PGMUtils.parseMapText; import static net.kyori.adventure.text.Component.text; import static tc.oc.pgm.util.bukkit.BukkitUtils.colorize; import static tc.oc.pgm.util.player.PlayerComponent.player; @@ -127,7 +126,7 @@ public Optional getMostRecentHistory() { public MapPartyPreset getPreset(String presetName) { return getPresets().stream() - .filter(preset -> cleanName(preset.getName()).equalsIgnoreCase(presetName)) + .filter(preset -> cleanName(preset.name()).equalsIgnoreCase(presetName)) .findAny() .orElse(null); } @@ -143,24 +142,22 @@ public void create(CommandAudience viewer, Player sender, MapPartyPreset preset, return; } - if (preset.getName() != null) { - setName(viewer, preset.getName()); + if (preset.name() != null) { + setName(viewer, preset.name()); } - if (preset.getDescription() != null) { - setDescription(viewer, preset.getDescription()); + if (preset.description() != null) { + setDescription(viewer, preset.description()); } - if (preset.getDuration() != null) { - setTimelimit(viewer, preset.getDuration(), false); + if (preset.duration() != null) { + setTimelimit(viewer, preset.duration(), false); } if (type == MapPartyType.REGULAR) { - setMapPool(viewer, preset.getPool()); + setMapPool(viewer, preset.pool()); } else { - preset.getMaps().stream() - .map(mapName -> parseMapText(mapName)) - .forEach(map -> addMap(viewer, map)); + preset.maps().stream().map(PGMUtils::parseMapText).forEach(map -> addMap(viewer, map)); } } @@ -171,9 +168,10 @@ public boolean create(CommandAudience viewer, Player sender, MapPartyType type, } if (getEventConfig().restrictSingleSession() && historyStore.hasAnyEndedEvents() && !force) { - historyStore.mostRecent().ifPresent(lastParty -> { - viewer.sendWarning(MapPartyMessages.getPreviousPartyWarning(lastParty)); - }); + historyStore + .mostRecent() + .ifPresent( + lastParty -> viewer.sendWarning(MapPartyMessages.getPreviousPartyWarning(lastParty))); return false; } @@ -247,9 +245,8 @@ public boolean restart(CommandSender sender) { private boolean canModify(CommandSender sender) { if (party == null) return false; - if (!(sender instanceof Player)) return true; + if (!(sender instanceof Player player)) return true; - Player player = (Player) sender; return party.getHosts().isHost(player.getUniqueId()) || player.hasPermission(CommunityPermissions.PARTY_ADMIN); } @@ -334,7 +331,6 @@ public void setTimelimit(CommandAudience viewer, Duration timeLimit, boolean for .color(NamedTextColor.GREEN)) .color(NamedTextColor.GRAY) .build()); - ; } } @@ -528,10 +524,8 @@ public void onPartyStart(MapPartyStartEvent event) { Bukkit.getScheduler() .runTaskLater( Community.get(), - () -> { - Bukkit.dispatchCommand( - Bukkit.getConsoleSender(), getEventConfig().getRaindropActivateCommand()); - }, + () -> Bukkit.dispatchCommand( + Bukkit.getConsoleSender(), getEventConfig().getRaindropActivateCommand()), 20L * 8); } @@ -595,11 +589,7 @@ public void onPlayerJoin(PlayerJoinEvent event) { .getServer() .getScheduler() .scheduleSyncDelayedTask( - Community.get(), - () -> { - sendPartyWelcome(event.getPlayer()); - }, - 30L); + Community.get(), () -> sendPartyWelcome(event.getPlayer()), 30L); } } } @@ -716,10 +706,7 @@ public void sendHistoryEntry(CommandAudience sender, int sequence, boolean verbo historyStore .getBySequence(sequence) .ifPresentOrElse( - entry -> { - sender.getAudience().sendMessage(entry.format(verbose)); - }, - () -> sender + entry -> sender.getAudience().sendMessage(entry.format(verbose)), () -> sender .getAudience() .sendWarning(text("No party history found for #" + sequence, NamedTextColor.RED))); } diff --git a/core/src/main/java/dev/pgm/community/party/history/MapPartyHistoryEntry.java b/core/src/main/java/dev/pgm/community/party/history/MapPartyHistoryEntry.java index 56c04633..5fe85cfb 100644 --- a/core/src/main/java/dev/pgm/community/party/history/MapPartyHistoryEntry.java +++ b/core/src/main/java/dev/pgm/community/party/history/MapPartyHistoryEntry.java @@ -226,7 +226,7 @@ public Component format(boolean verbose) { .append(text(matches.size(), NamedTextColor.AQUA)) .build(); - Component verboseBlock = text() + Component combined = text() .append(top) .appendNewline() .append(text(" ")) @@ -251,7 +251,6 @@ public Component format(boolean verbose) { .append(matchHeader) .build(); - Component combined = verboseBlock; for (int i = 0; i < matches.size(); i++) { Component line = matches.get(i).formatLine(i + 1); combined = combined.appendNewline().append(text(" ")).append(line); diff --git a/core/src/main/java/dev/pgm/community/party/hosts/MapPartyHosts.java b/core/src/main/java/dev/pgm/community/party/hosts/MapPartyHosts.java index 83d6dc5e..b775472f 100644 --- a/core/src/main/java/dev/pgm/community/party/hosts/MapPartyHosts.java +++ b/core/src/main/java/dev/pgm/community/party/hosts/MapPartyHosts.java @@ -8,11 +8,11 @@ import dev.pgm.community.Community; import dev.pgm.community.CommunityPermissions; import dev.pgm.community.utils.BroadcastUtils; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; @@ -66,11 +66,10 @@ public void addSubHost(Player player) { } public boolean removeSubHost(String name) { - Entry cachedEntry = - nameCache.entrySet().stream() - .filter(e -> e.getValue().equalsIgnoreCase(name)) - .findAny() - .orElse(null); + Entry cachedEntry = nameCache.entrySet().stream() + .filter(e -> e.getValue().equalsIgnoreCase(name)) + .findAny() + .orElse(null); if (cachedEntry != null) { UUID playerId = cachedEntry.getKey(); @@ -106,7 +105,7 @@ public Set getSubHostIds() { } public Set getHostNames() { - return this.nameCache.values().stream().collect(Collectors.toSet()); + return new HashSet<>(this.nameCache.values()); } public String getCachedName(UUID playerId) { diff --git a/core/src/main/java/dev/pgm/community/party/menu/MapPartyMainMenu.java b/core/src/main/java/dev/pgm/community/party/menu/MapPartyMainMenu.java index cc9cad28..9493431a 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/MapPartyMainMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/MapPartyMainMenu.java @@ -99,9 +99,7 @@ private void renderPartyCreation(Player player, InventoryContents contents) { .material(Material.CAKE) .name(colorize("&aCreate a new map party")) .build(), - c -> { - selectTypeSub.open(this); - })); + c -> selectTypeSub.open(this))); List presets = getFeature().getPresets(); int[] SLOTS = {1, 3, 5, 7}; @@ -126,28 +124,21 @@ private Optional getParty() { } private ClickableItem getStartIcon() { - return ClickableItem.of(START_ITEM, c -> { - getParty().ifPresent(party -> { - Bukkit.dispatchCommand(getViewer(), "event start " + (c.isLeftClick() ? "false" : "true")); - }); - }); + return ClickableItem.of(START_ITEM, c -> getParty() + .ifPresent(party -> Bukkit.dispatchCommand( + getViewer(), "event start " + (c.isLeftClick() ? "false" : "true")))); } private ClickableItem getRestartIcon() { - return ClickableItem.of(RESTART_ITEM, c -> { - getParty().ifPresent(party -> { - Bukkit.dispatchCommand(getViewer(), "event restart"); - }); - }); + return ClickableItem.of(RESTART_ITEM, c -> getParty() + .ifPresent(party -> Bukkit.dispatchCommand(getViewer(), "event restart"))); } private ClickableItem getEndIcon() { - return ClickableItem.of(END_ITEM, c -> { - getParty().ifPresent(party -> { - Bukkit.dispatchCommand(getViewer(), "event stop"); - close(); - }); - }); + return ClickableItem.of(END_ITEM, c -> getParty().ifPresent(party -> { + Bukkit.dispatchCommand(getViewer(), "event stop"); + close(); + })); } private ClickableItem getHostIcon(MapPartyHosts hosts) { @@ -159,9 +150,7 @@ private ClickableItem getHostIcon(MapPartyHosts hosts) { .lore(colorize("&7Click to manage party hosts")) .flags(ItemFlag.values()) .build(), - c -> { - new HostMenu(getFeature(), getViewer()); - }); + c -> new HostMenu(getFeature(), getViewer())); } private ClickableItem getMapsIcon(MapPartyType type) { @@ -173,9 +162,7 @@ private ClickableItem getMapsIcon(MapPartyType type) { "&7Click to manage party " + (type == MapPartyType.REGULAR ? "pool" : "maps"))) .flags(ItemFlag.values()) .build(), - c -> { - Bukkit.dispatchCommand(getViewer(), "event maps"); - }); + c -> Bukkit.dispatchCommand(getViewer(), "event maps")); } private ClickableItem getSettingsIcon() { @@ -186,9 +173,7 @@ private ClickableItem getSettingsIcon() { .lore(colorize("&7Click to manage party settings")) .flags(ItemFlag.values()) .build(), - c -> { - new MapPartySettingsMenu(getFeature(), getViewer()); - }); + c -> new MapPartySettingsMenu(getFeature(), getViewer())); } private ClickableItem getModifierMenu() { @@ -199,20 +184,18 @@ private ClickableItem getModifierMenu() { .lore(colorize("&7Click to manage party modifiers")) .flags(ItemFlag.values()) .build(), - c -> { - new MapPartyModifierMenu(getFeature(), getViewer()); - }); + c -> new MapPartyModifierMenu(getFeature(), getViewer())); } private ClickableItem getPresetIcon(MapPartyPreset preset) { List lore = Lists.newArrayList(); - lore.add(colorize("&6Description&7: &3" + preset.getDescription())); + lore.add(colorize("&6Description&7: &3" + preset.description())); lore.add(colorize("&6Mode&7: &a" + preset.getType().getName())); if (preset.getType() == MapPartyType.REGULAR) { - lore.add(colorize("&6Pool&7: &b" + preset.getPool())); + lore.add(colorize("&6Pool&7: &b" + preset.pool())); } else { - lore.add(colorize("&6Maps: &b" + preset.getMaps().size())); + lore.add(colorize("&6Maps: &b" + preset.maps().size())); } lore.add(""); @@ -222,17 +205,17 @@ private ClickableItem getPresetIcon(MapPartyPreset preset) { new ItemBuilder() .material(Materials.STAINED_GLASS_PANE) .color(DyeColor.CYAN) - .name(colorize(preset.getName())) - .lore(lore.toArray(new String[lore.size()])) + .name(colorize(preset.name())) + .lore(lore.toArray(new String[0])) .build(), c -> { - String command = "event preset " + preset.getName(); + String command = "event preset " + preset.name(); if (getFeature().requiresForceForCreate()) { new MapPartyCreateConfirmMenu( getFeature(), getViewer(), - "event preset --force " + preset.getName(), - preset.getName()) + "event preset --force " + preset.name(), + preset.name()) .open(this); } else { Bukkit.dispatchCommand(getViewer(), command); @@ -249,11 +232,11 @@ private ClickableItem getEmptyItem(int i) { } private static final String START_PARTY_SKIN = - "http://textures.minecraft.net/texture/4ae29422db4047efdb9bac2cdae5a0719eb772fccc88a66d912320b343c341"; + "https://textures.minecraft.net/texture/4ae29422db4047efdb9bac2cdae5a0719eb772fccc88a66d912320b343c341"; private static final String RESTART_PARTY_SKIN = - "http://textures.minecraft.net/texture/479e8cf21b839b255a2836e251941c5fdc99af01559e3733d5325ccfa3d922aa"; + "https://textures.minecraft.net/texture/479e8cf21b839b255a2836e251941c5fdc99af01559e3733d5325ccfa3d922aa"; private static final String END_PARTY_SKIN = - "http://textures.minecraft.net/texture/e9cdb9af38cf41daa53bc8cda7665c509632d14e678f0f19f263f46e541d8a30"; + "https://textures.minecraft.net/texture/e9cdb9af38cf41daa53bc8cda7665c509632d14e678f0f19f263f46e541d8a30"; private static final ItemStack START_ITEM = PLAYER_UTILS.customSkull( START_PARTY_SKIN, diff --git a/core/src/main/java/dev/pgm/community/party/menu/MapPartyMenu.java b/core/src/main/java/dev/pgm/community/party/menu/MapPartyMenu.java index 5f048f37..6dc620a0 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/MapPartyMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/MapPartyMenu.java @@ -123,7 +123,7 @@ protected ClickableItem getBorderItem() { } protected static final String ADD_SKIN = - "http://textures.minecraft.net/texture/b056bc1244fcff99344f12aba42ac23fee6ef6e3351d27d273c1572531f"; + "https://textures.minecraft.net/texture/b056bc1244fcff99344f12aba42ac23fee6ef6e3351d27d273c1572531f"; protected DyeColor getBorderColor() { return getFeature().getParty() == null @@ -133,9 +133,8 @@ protected DyeColor getBorderColor() { protected ClickableItem getMainMenuIcon() { return ClickableItem.of( - getNamedItem("&7Return to &dMap Party Manager", Material.CAKE, 1), c -> { - Bukkit.dispatchCommand(getViewer(), "event"); - }); + getNamedItem("&7Return to &dMap Party Manager", Material.CAKE, 1), + c -> Bukkit.dispatchCommand(getViewer(), "event")); } protected ItemStack getPlayerHead( @@ -161,7 +160,7 @@ private ClickableItem getPageItem(Player player, int page, ItemStack icon) { return ClickableItem.of(icon, c -> getInventory().open(player, page)); } - private final ItemStack getPageIcon(String text, int page) { + private ItemStack getPageIcon(String text, int page) { return getNamedItem(text, Material.ARROW, page); } diff --git a/core/src/main/java/dev/pgm/community/party/menu/hosts/HostAddMenu.java b/core/src/main/java/dev/pgm/community/party/menu/hosts/HostAddMenu.java index 6a60cc2c..5b865d76 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/hosts/HostAddMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/hosts/HostAddMenu.java @@ -37,9 +37,11 @@ public HostAddMenu(MapPartyHosts hosts) { public void init(Player player, InventoryContents contents) { super.init(player, contents); contents.set( - 5, 4, ClickableItem.of(getNamedItem("&7Return to &aEvent Hosts", Material.CAKE, 1), c -> { - Bukkit.dispatchCommand(player, "event hosts"); - })); + 5, + 4, + ClickableItem.of( + getNamedItem("&7Return to &aEvent Hosts", Material.CAKE, 1), + c -> Bukkit.dispatchCommand(player, "event hosts"))); } @Override diff --git a/core/src/main/java/dev/pgm/community/party/menu/hosts/HostMenu.java b/core/src/main/java/dev/pgm/community/party/menu/hosts/HostMenu.java index 6fe162b8..2a9cfcd0 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/hosts/HostMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/hosts/HostMenu.java @@ -49,7 +49,7 @@ public void render(Player player, InventoryContents contents) { .collect(Collectors.toSet()); Pagination page = contents.pagination(); - page.setItems(players.toArray(new ClickableItem[players.size()])); + page.setItems(players.toArray(new ClickableItem[0])); page.setItemsPerPage(7); page.addToIterator(contents.newIterator(SlotIterator.Type.HORIZONTAL, 2, 1)); @@ -75,9 +75,7 @@ public void render(Player player, InventoryContents contents) { 4, ClickableItem.of( PLAYER_UTILS.customSkull(ADD_SKIN, "&a&lAdd Host", "&7Click to add event host"), - c -> { - new HostAddMenu(hosts).open(getViewer()); - })); + c -> new HostAddMenu(hosts).open(getViewer()))); // Return to party menu contents.set(5, 4, getMainMenuIcon()); diff --git a/core/src/main/java/dev/pgm/community/party/menu/maps/MapAddMenu.java b/core/src/main/java/dev/pgm/community/party/menu/maps/MapAddMenu.java index 088970f6..63310084 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/maps/MapAddMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/maps/MapAddMenu.java @@ -39,8 +39,8 @@ public class MapAddMenu extends MapPartyMenu { private static final int ROWS = 6; private static final boolean HOST_ONLY = true; - private List maps; - private List tags; + private final List maps; + private final List tags; private int filterIndex = 0; @@ -75,7 +75,7 @@ private void render(Player player, InventoryContents contents) { List mapItems = getFilteredMapItems(); Pagination page = contents.pagination(); - page.setItems(mapItems.toArray(new ClickableItem[mapItems.size()])); + page.setItems(mapItems.toArray(new ClickableItem[0])); page.setItemsPerPage(36); page.addToIterator(contents.newIterator(SlotIterator.Type.HORIZONTAL, 1, 0)); @@ -96,9 +96,12 @@ private void render(Player player, InventoryContents contents) { } // Return to party menu - contents.set(5, 4, ClickableItem.of(getNamedItem("&7Return to &6Maps", Material.CAKE, 1), c -> { - Bukkit.dispatchCommand(player, "event maps"); - })); + contents.set( + 5, + 4, + ClickableItem.of( + getNamedItem("&7Return to &6Maps", Material.CAKE, 1), + c -> Bukkit.dispatchCommand(player, "event maps"))); } private ClickableItem getAllIcon() { @@ -167,7 +170,6 @@ public void update(Player player, InventoryContents contents) { contents.setProperty("update", delay + 1); if (delay >= 5) { render(player, contents); - delay = 0; } } @@ -190,11 +192,10 @@ private ClickableItem getMapIcon(MapInfo map) { boolean isAdded = getFeature().getParty().isMapAdded(map); Material icon; - icon = map.getTags().isEmpty() - || !map.getTags().stream().filter(t -> t.isGamemode()).findAny().isPresent() + icon = map.getTags().isEmpty() || map.getTags().stream().noneMatch(MapTag::isGamemode) ? Material.MAP : mapTagMaterial( - map.getTags().stream().filter(tag -> tag.isGamemode()).findAny().get()); + map.getTags().stream().filter(MapTag::isGamemode).findAny().get()); ItemBuilder builder = new ItemBuilder() .material(icon) @@ -210,9 +211,8 @@ private ClickableItem getMapIcon(MapInfo map) { builder.enchant(Enchantments.LUCK_OF_THE_SEA, 1); } - return ClickableItem.of(builder.build(), c -> { - Bukkit.dispatchCommand(getViewer(), "event addmap " + map.getName()); - }); + return ClickableItem.of( + builder.build(), c -> Bukkit.dispatchCommand(getViewer(), "event addmap " + map.getName())); } private ClickableItem getNoMapsIcon() { diff --git a/core/src/main/java/dev/pgm/community/party/menu/maps/MapMenu.java b/core/src/main/java/dev/pgm/community/party/menu/maps/MapMenu.java index 9d56cab9..e831ab9b 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/maps/MapMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/maps/MapMenu.java @@ -15,7 +15,6 @@ import fr.minuskube.inv.content.Pagination; import fr.minuskube.inv.content.SlotIterator; import java.util.List; -import java.util.stream.Collectors; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.DyeColor; @@ -42,15 +41,14 @@ public MapMenu(MapPartyFeature feature, Player viewer) { private void render(Player player, InventoryContents contents) { contents.fillBorders(getBorderItem()); - if (getFeature().getParty() != null && getFeature().getParty() instanceof CustomPoolParty) { - CustomPoolParty party = (CustomPoolParty) getFeature().getParty(); + if (getFeature().getParty() != null + && getFeature().getParty() instanceof CustomPoolParty party) { List maps = party.getMaps(); - List mapItems = - maps.stream().map(this::getMapIcon).collect(Collectors.toList()); + List mapItems = maps.stream().map(this::getMapIcon).toList(); Pagination page = contents.pagination(); - page.setItems(mapItems.toArray(new ClickableItem[mapItems.size()])); + page.setItems(mapItems.toArray(new ClickableItem[0])); page.setItemsPerPage(27); page.addToIterator(contents.newIterator(SlotIterator.Type.HORIZONTAL, 1, 0)); @@ -77,9 +75,7 @@ private void render(Player player, InventoryContents contents) { ClickableItem.of( PLAYER_UTILS.customSkull( ADD_SKIN, "&a&lAdd Map", "&7Click to add a map to the selection"), - c -> { - new MapAddMenu(getFeature(), getViewer()); - })); + c -> new MapAddMenu(getFeature(), getViewer()))); } else { RegularPoolParty party = (RegularPoolParty) getFeature().getParty(); MapPoolManager poolManager = PGMUtils.getMapPoolManager(); @@ -123,9 +119,7 @@ private ClickableItem getMapIcon(MapInfo map) { .lore(colorize("&7Click to remove")) .flags(ItemFlag.values()) .build(), - c -> { - Bukkit.dispatchCommand(getViewer(), "event removemap " + map.getName()); - }); + c -> Bukkit.dispatchCommand(getViewer(), "event removemap " + map.getName())); } private ClickableItem getPoolIcon(MapPool pool, boolean active) { @@ -140,9 +134,8 @@ private ClickableItem getPoolIcon(MapPool pool, boolean active) { if (active) { icon.enchant(Enchantments.LUCK_OF_THE_SEA, 1); } - return ClickableItem.of(icon.build(), c -> { - Bukkit.dispatchCommand(getViewer(), "event setpool " + pool.getName()); - }); + return ClickableItem.of( + icon.build(), c -> Bukkit.dispatchCommand(getViewer(), "event setpool " + pool.getName())); } private ClickableItem getNoMapsIcon() { diff --git a/core/src/main/java/dev/pgm/community/party/menu/modifiers/MapPartyModifierMenu.java b/core/src/main/java/dev/pgm/community/party/menu/modifiers/MapPartyModifierMenu.java index 7a2b2e1e..824c98c1 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/modifiers/MapPartyModifierMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/modifiers/MapPartyModifierMenu.java @@ -54,9 +54,8 @@ private ClickableItem getRaindropMultiplierIcon() { .lore( colorize("&7Click to toggle multiplier"), "", - colorize( - "&7Status&8: " - + (getFeature().isRaindropMultiplierActive() ? "&aEnabled" : "&cDisabled"))) + colorize("&7Status&8: " + + (getFeature().isRaindropMultiplierActive() ? "&aEnabled" : "&cDisabled"))) .flags(ItemFlag.values()) .build(), c -> { @@ -74,17 +73,14 @@ private ClickableItem getMutationIcon() { .lore(colorize("&7Click to view match mutations")) .flags(ItemFlag.values()) .build(), - c -> { - Bukkit.dispatchCommand(getViewer(), "mutation"); - }); + c -> Bukkit.dispatchCommand(getViewer(), "mutation")); } - return ClickableItem.empty( - new ItemBuilder() - .material(Material.BARRIER) - .name(colorize("&cDisabled")) - .lore(colorize("&7Mutations are disabled! You can enable then in the config")) - .flags(ItemFlag.values()) - .build()); + return ClickableItem.empty(new ItemBuilder() + .material(Material.BARRIER) + .name(colorize("&cDisabled")) + .lore(colorize("&7Mutations are disabled! You can enable then in the config")) + .flags(ItemFlag.values()) + .build()); } } diff --git a/core/src/main/java/dev/pgm/community/party/menu/settings/MapPartySettingsMenu.java b/core/src/main/java/dev/pgm/community/party/menu/settings/MapPartySettingsMenu.java index d7fe744a..56f3e25e 100644 --- a/core/src/main/java/dev/pgm/community/party/menu/settings/MapPartySettingsMenu.java +++ b/core/src/main/java/dev/pgm/community/party/menu/settings/MapPartySettingsMenu.java @@ -172,9 +172,8 @@ private ClickableItem getPoolModeItem(CustomPoolParty party) { colorize("&7Click to toggle mode")) .flags(ItemFlag.values()); - return ClickableItem.of(builder.build(), c -> { - Bukkit.dispatchCommand(getViewer(), "event mode"); - }); + return ClickableItem.of( + builder.build(), c -> Bukkit.dispatchCommand(getViewer(), "event mode")); } private ClickableItem getSettingItem(PartyBooleanSetting setting) { diff --git a/core/src/main/java/dev/pgm/community/party/presets/MapPartyPreset.java b/core/src/main/java/dev/pgm/community/party/presets/MapPartyPreset.java index 20d16bc3..5e18d062 100644 --- a/core/src/main/java/dev/pgm/community/party/presets/MapPartyPreset.java +++ b/core/src/main/java/dev/pgm/community/party/presets/MapPartyPreset.java @@ -7,13 +7,8 @@ import java.util.List; import org.bukkit.configuration.ConfigurationSection; -public class MapPartyPreset { - - private final String name; - private final String description; - private final Duration duration; - private final String pool; - private final List maps; +public record MapPartyPreset( + String name, String description, Duration duration, String pool, List maps) { public static MapPartyPreset of(ConfigurationSection section) { return new MapPartyPreset( @@ -24,36 +19,7 @@ public static MapPartyPreset of(ConfigurationSection section) { section.getStringList("maps")); } - public MapPartyPreset( - String name, String description, Duration duration, String pool, List maps) { - this.name = name; - this.description = description; - this.duration = duration; - this.pool = pool; - this.maps = maps; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public Duration getDuration() { - return duration; - } - - public String getPool() { - return pool; - } - - public List getMaps() { - return maps; - } - public MapPartyType getType() { - return (getPool() == null || getPool().isEmpty()) ? MapPartyType.CUSTOM : MapPartyType.REGULAR; + return (pool() == null || pool().isEmpty()) ? MapPartyType.CUSTOM : MapPartyType.REGULAR; } } diff --git a/core/src/main/java/dev/pgm/community/party/settings/MapPartySettings.java b/core/src/main/java/dev/pgm/community/party/settings/MapPartySettings.java index 839e8054..cd2bd6a3 100644 --- a/core/src/main/java/dev/pgm/community/party/settings/MapPartySettings.java +++ b/core/src/main/java/dev/pgm/community/party/settings/MapPartySettings.java @@ -6,9 +6,9 @@ public class MapPartySettings { - private PartyBooleanSetting showLoginMessage; - private PartyBooleanSetting showPartyNotifications; - private PartyBooleanSetting autoscalingTeams; + private final PartyBooleanSetting showLoginMessage; + private final PartyBooleanSetting showPartyNotifications; + private final PartyBooleanSetting autoscalingTeams; public MapPartySettings(MapPartyConfig config) { this.showLoginMessage = new PartyBooleanSetting( diff --git a/core/src/main/java/dev/pgm/community/party/settings/PartyBooleanSetting.java b/core/src/main/java/dev/pgm/community/party/settings/PartyBooleanSetting.java index 6509c709..4af687fd 100644 --- a/core/src/main/java/dev/pgm/community/party/settings/PartyBooleanSetting.java +++ b/core/src/main/java/dev/pgm/community/party/settings/PartyBooleanSetting.java @@ -4,8 +4,8 @@ public class PartyBooleanSetting extends PartySetting { - private Material trueIcon; - private Material falseIcon; + private final Material trueIcon; + private final Material falseIcon; private boolean value; diff --git a/core/src/main/java/dev/pgm/community/party/settings/PartySetting.java b/core/src/main/java/dev/pgm/community/party/settings/PartySetting.java index 9b387f17..6c5c1785 100644 --- a/core/src/main/java/dev/pgm/community/party/settings/PartySetting.java +++ b/core/src/main/java/dev/pgm/community/party/settings/PartySetting.java @@ -4,8 +4,8 @@ public abstract class PartySetting { - private String name; - private String description; + private final String name; + private final String description; public PartySetting(String name, String description) { this.name = name; diff --git a/core/src/main/java/dev/pgm/community/party/types/CustomPoolParty.java b/core/src/main/java/dev/pgm/community/party/types/CustomPoolParty.java index 9cf1316b..2e35dd8e 100644 --- a/core/src/main/java/dev/pgm/community/party/types/CustomPoolParty.java +++ b/core/src/main/java/dev/pgm/community/party/types/CustomPoolParty.java @@ -25,7 +25,7 @@ public class CustomPoolParty extends MapPartyBase { private boolean voted; - private List maps; + private final List maps; public CustomPoolParty(Player creator, Duration length, MapPartyConfig config) { this( diff --git a/core/src/main/java/dev/pgm/community/polls/PollBuilder.java b/core/src/main/java/dev/pgm/community/polls/PollBuilder.java index ed4a4552..cd3538d3 100644 --- a/core/src/main/java/dev/pgm/community/polls/PollBuilder.java +++ b/core/src/main/java/dev/pgm/community/polls/PollBuilder.java @@ -22,23 +22,23 @@ import java.util.UUID; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.api.map.MapInfo; public class PollBuilder { private static final int MAX_POLL_OPTIONS = 4; - private PollEditAlerter alert; // Used to broadcast changes to values + private final PollEditAlerter alert; // Used to broadcast changes to values // Required private Component question; private UUID creator; - private PollThreshold threshold = PollThreshold.SIMPLE; + private PollThreshold threshold; private Duration duration; // Optional - private Set endActions = Sets.newHashSet(); + private final Set endActions = Sets.newHashSet(); public PollBuilder(PollConfig config, PollEditAlerter alert) { this.alert = alert; @@ -152,17 +152,14 @@ public Poll build() { endActions.add(new NullEndAction()); } - for (EndAction action : endActions) { - actions.add(action); - } + actions.addAll(endActions); if (question == null) { question = generateQuestion(actions); } if (actions.size() == 1) { - poll = new SingleChoicePoll( - question, creator, threshold, duration, actions.iterator().next()); + poll = new SingleChoicePoll(question, creator, threshold, duration, actions.getFirst()); } else if (endActions.size() > 1) { threshold = PollThreshold.SIMPLE; poll = new MultiChoicePoll(question, creator, threshold, duration, actions); @@ -200,7 +197,7 @@ public static Component generateQuestion(List actions) { } if (actions.size() == 1) { - return actions.iterator().next().getDefaultQuestion(); + return actions.getFirst().getDefaultQuestion(); } Set> uniqueActionTypes = new HashSet<>(); @@ -211,39 +208,35 @@ public static Component generateQuestion(List actions) { } } - if (uniqueActionTypes.size() == 1) { - Class singleActionType = uniqueActionTypes.iterator().next(); - NamedTextColor textColor = NamedTextColor.WHITE; - String actionTypeName = ""; - String questionSuffix = ""; - - if (singleActionType.equals(CommandEndAction.class)) { - actionTypeName = "command"; - textColor = NamedTextColor.AQUA; - questionSuffix = "execute?"; - } else if (singleActionType.equals(KickPlayerEndAction.class)) { - actionTypeName = "player"; - textColor = NamedTextColor.GOLD; - questionSuffix = "kick?"; - } else if (singleActionType.equals(MutationEndAction.class)) { - actionTypeName = "mutation"; - textColor = NamedTextColor.GREEN; - questionSuffix = "toggle?"; - } else if (singleActionType.equals(MapEndAction.class)) { - actionTypeName = "map"; - textColor = NamedTextColor.YELLOW; - questionSuffix = "play next?"; - } - - return text() - .append(text("Which ")) - .append(text(actionTypeName, textColor)) - .append(text(" should we ")) - .append(text(questionSuffix)) - .color(NamedTextColor.WHITE) - .build(); + Class singleActionType = uniqueActionTypes.iterator().next(); + NamedTextColor textColor = NamedTextColor.WHITE; + String actionTypeName = ""; + String questionSuffix = ""; + + if (singleActionType.equals(CommandEndAction.class)) { + actionTypeName = "command"; + textColor = NamedTextColor.AQUA; + questionSuffix = "execute?"; + } else if (singleActionType.equals(KickPlayerEndAction.class)) { + actionTypeName = "player"; + textColor = NamedTextColor.GOLD; + questionSuffix = "kick?"; + } else if (singleActionType.equals(MutationEndAction.class)) { + actionTypeName = "mutation"; + textColor = NamedTextColor.GREEN; + questionSuffix = "toggle?"; + } else if (singleActionType.equals(MapEndAction.class)) { + actionTypeName = "map"; + textColor = NamedTextColor.YELLOW; + questionSuffix = "play next?"; } - return text("What should we do?", NamedTextColor.WHITE); + return text() + .append(text("Which ")) + .append(text(actionTypeName, textColor)) + .append(text(" should we ")) + .append(text(questionSuffix)) + .color(NamedTextColor.WHITE) + .build(); } } diff --git a/core/src/main/java/dev/pgm/community/polls/PollComponents.java b/core/src/main/java/dev/pgm/community/polls/PollComponents.java index 6d1d1656..57791b27 100644 --- a/core/src/main/java/dev/pgm/community/polls/PollComponents.java +++ b/core/src/main/java/dev/pgm/community/polls/PollComponents.java @@ -13,9 +13,9 @@ import dev.pgm.community.utils.MessageUtils; import dev.pgm.community.utils.Sounds; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; @@ -103,25 +103,21 @@ default Component formatCategoryDetail(String category, Component value) { } default Component formatQuestion(Poll poll) { - Component question = - text() - .append(text("Question", NamedTextColor.GOLD, TextDecoration.BOLD)) - .append(text(": ", NamedTextColor.GRAY)) - .hoverEvent( - HoverEvent.showText( - text() - .append(poll.getRequiredThreshold().toComponent()) - .append(text(" required for success.", NamedTextColor.GRAY)))) - .build(); + Component question = text() + .append(text("Question", NamedTextColor.GOLD, TextDecoration.BOLD)) + .append(text(": ", NamedTextColor.GRAY)) + .hoverEvent(HoverEvent.showText(text() + .append(poll.getRequiredThreshold().toComponent()) + .append(text(" required for success.", NamedTextColor.GRAY)))) + .build(); return text().append(question).append(poll.getQuestion()).build(); } default void sendPollBroadcast(Poll poll) { List lines = Lists.newArrayList(); - lines.add( - TextFormatter.horizontalLineHeading( - null, text("Server Poll", NamedTextColor.AQUA), NamedTextColor.YELLOW)); + lines.add(TextFormatter.horizontalLineHeading( + null, text("Server Poll", NamedTextColor.AQUA), NamedTextColor.YELLOW)); lines.add(text(" ")); Component question = formatQuestion(poll); @@ -140,25 +136,21 @@ default void sendBooleanPollResults(Poll poll, long yay, long nay, boolean succe final NamedTextColor lineColor = success ? NamedTextColor.GREEN : NamedTextColor.RED; - Component header = - TextFormatter.horizontalLineHeading( - null, text("Poll Results", NamedTextColor.AQUA), lineColor); + Component header = TextFormatter.horizontalLineHeading( + null, text("Poll Results", NamedTextColor.AQUA), lineColor); Component footer = TextFormatter.horizontalLine(lineColor, TextFormatter.MAX_CHAT_WIDTH); Component question = formatQuestion(poll); - Component finalResult = - text() - .append(text("Final Result", NamedTextColor.GOLD, TextDecoration.BOLD)) - .append(text(": ", NamedTextColor.GRAY)) - .append(text(success ? "YES" : "NO", lineColor, TextDecoration.UNDERLINED)) - .hoverEvent( - HoverEvent.showText( - text() - .append(poll.getRequiredThreshold().toComponent()) - .appendNewline() - .append(createYesNoInfo(yay, nay)))) - .build(); + Component finalResult = text() + .append(text("Final Result", NamedTextColor.GOLD, TextDecoration.BOLD)) + .append(text(": ", NamedTextColor.GRAY)) + .append(text(success ? "YES" : "NO", lineColor, TextDecoration.UNDERLINED)) + .hoverEvent(HoverEvent.showText(text() + .append(poll.getRequiredThreshold().toComponent()) + .appendNewline() + .append(createYesNoInfo(yay, nay)))) + .build(); Component graphBreakdown = createGraphBreakdown(yay, nay); @@ -225,26 +217,22 @@ default void sendMultiChoicePollResults( Poll poll, Map voteCounts, EndAction winningAction) { List lines = Lists.newArrayList(); - Component header = - TextFormatter.horizontalLineHeading( - null, text("Poll Results", NamedTextColor.AQUA), NamedTextColor.GREEN); + Component header = TextFormatter.horizontalLineHeading( + null, text("Poll Results", NamedTextColor.AQUA), NamedTextColor.GREEN); Component footer = TextFormatter.horizontalLine(NamedTextColor.GREEN, TextFormatter.MAX_CHAT_WIDTH); Component question = formatQuestion(poll); - Component finalResult = - text() - .append(text("Final Result", NamedTextColor.GOLD, TextDecoration.BOLD)) - .append(text(": ", NamedTextColor.GRAY)) - .append(winningAction.getPreviewValue().decorate(TextDecoration.UNDERLINED)) - .hoverEvent( - HoverEvent.showText( - text() - .append(poll.getRequiredThreshold().toComponent()) - .appendNewline() - .append(createMultiChoiceInfo(voteCounts)))) - .build(); + Component finalResult = text() + .append(text("Final Result", NamedTextColor.GOLD, TextDecoration.BOLD)) + .append(text(": ", NamedTextColor.GRAY)) + .append(winningAction.getPreviewValue().decorate(TextDecoration.UNDERLINED)) + .hoverEvent(HoverEvent.showText(text() + .append(poll.getRequiredThreshold().toComponent()) + .appendNewline() + .append(createMultiChoiceInfo(voteCounts)))) + .build(); Component graphBreakdown = createRankedGraphBreakdown(voteCounts, winningAction); @@ -283,11 +271,10 @@ default Component createMultiChoiceInfo(Map voteCounts) { default Component createRankedGraphBreakdown( Map voteCounts, EndAction winningAction) { - List rankedActions = - voteCounts.entrySet().stream() - .sorted(Map.Entry.comparingByValue().reversed()) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); + List rankedActions = voteCounts.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .map(Map.Entry::getKey) + .toList(); final int maxBarLength = 17; // Max length of the bar in characters int totalVotes = rankedActions.stream().mapToInt(voteCounts::get).sum(); @@ -312,9 +299,8 @@ default Component createRankedGraphBreakdown( barColor = NamedTextColor.GRAY; } - builder.append( - createHoverableBar( - action, actionBarLength, maxBarLength, barColor, actionVotes, actionPercentage)); + builder.append(createHoverableBar( + action, actionBarLength, maxBarLength, barColor, actionVotes, actionPercentage)); } builder @@ -339,15 +325,14 @@ default Component createHoverableBar( for (int i = 0; i < maxBarLength; i++) { if (i < barLength) { - Component hoverText = - text() - .append(action.getPreviewValue().color(barColor)) - .append(text(": ", NamedTextColor.GRAY)) - .append(text(actionVotes + " vote" + (actionVotes != 1 ? "s" : ""), barColor)) - .append(text(" (", NamedTextColor.GRAY)) - .append(text(String.format("%.2f", actionPercentage * 100) + "%", barColor)) - .append(text(")", NamedTextColor.GRAY)) - .build(); + Component hoverText = text() + .append(action.getPreviewValue().color(barColor)) + .append(text(": ", NamedTextColor.GRAY)) + .append(text(actionVotes + " vote" + (actionVotes != 1 ? "s" : ""), barColor)) + .append(text(" (", NamedTextColor.GRAY)) + .append(text(String.format("%.2f", actionPercentage * 100) + "%", barColor)) + .append(text(")", NamedTextColor.GRAY)) + .build(); builder.append(SQUARE.hoverEvent(HoverEvent.showText(hoverText))); } } @@ -387,17 +372,16 @@ default Component formatButton( } default Component createVoteReminderBroadcast(Poll poll, Duration timeLeft, boolean hasVoted) { - TextComponent.Builder alert = - text() - .append(text("[", NamedTextColor.GRAY)) - .append(text("Poll", NamedTextColor.AQUA)) - .append(text("]", NamedTextColor.GRAY)) - .appendSpace() - .append(text("Only ")) - .append(TemporalComponent.duration(timeLeft, urgencyColor(timeLeft))) - .append(text(" left to vote! ")) - .color(NamedTextColor.DARK_AQUA) - .hoverEvent(HoverEvent.showText(poll.getQuestion())); + TextComponent.Builder alert = text() + .append(text("[", NamedTextColor.GRAY)) + .append(text("Poll", NamedTextColor.AQUA)) + .append(text("]", NamedTextColor.GRAY)) + .appendSpace() + .append(text("Only ")) + .append(TemporalComponent.duration(timeLeft, urgencyColor(timeLeft))) + .append(text(" left to vote! ")) + .color(NamedTextColor.DARK_AQUA) + .hoverEvent(HoverEvent.showText(poll.getQuestion())); if (!hasVoted) { alert.append(poll.getVoteButtons(true)); @@ -455,21 +439,18 @@ default void sendBuilderDetails(PollBuilder builder, CommandAudience audience) { builder.getQuestion(), builder.getDuration(), builder.getThreshold(), - builder.getEndAction().stream().collect(Collectors.toList()), + new ArrayList<>(builder.getEndAction()), true, !builder.canBuild()); if (builder.canBuild()) { - Component buttons = - text() - .append( - formatButton( - "Start", NamedTextColor.GREEN, "/poll start", "Click to start poll", false)) - .appendSpace() - .append( - formatButton( - "Reset", NamedTextColor.RED, "/poll reset", "Click to reset values", false)) - .build(); + Component buttons = text() + .append(formatButton( + "Start", NamedTextColor.GREEN, "/poll start", "Click to start poll", false)) + .appendSpace() + .append(formatButton( + "Reset", NamedTextColor.RED, "/poll reset", "Click to reset values", false)) + .build(); audience.sendMessage(buttons); audience.sendMessage(getFooter()); @@ -486,9 +467,8 @@ default void sendDetails( boolean builder, boolean footer) { - audience.sendMessage( - TextFormatter.horizontalLineHeading( - audience.getSender(), text(title, NamedTextColor.AQUA), NamedTextColor.GRAY)); + audience.sendMessage(TextFormatter.horizontalLineHeading( + audience.getSender(), text(title, NamedTextColor.AQUA), NamedTextColor.GRAY)); List optionLines = Lists.newArrayList(); int i = 0; @@ -498,59 +478,46 @@ default void sendDetails( } if (builder && optionLines.isEmpty()) { - optionLines.add( - createEndActionLine(new NullEndAction(), 0, false) - .append(text(" - ", NamedTextColor.GRAY)) - .append( - formatButton( - "Command", - NamedTextColor.YELLOW, - "/poll command", - "Click to set a command", - true)) - .append( - formatButton("Map", NamedTextColor.GOLD, "/poll map", "Click to set a map", true)) - .append( - formatButton( - "Kick", NamedTextColor.RED, "/poll kick", "Click to kick a player", true))); + optionLines.add(createEndActionLine(new NullEndAction(), 0, false) + .append(text(" - ", NamedTextColor.GRAY)) + .append(formatButton( + "Command", NamedTextColor.YELLOW, "/poll command", "Click to set a command", true)) + .append(formatButton("Map", NamedTextColor.GOLD, "/poll map", "Click to set a map", true)) + .append(formatButton( + "Kick", NamedTextColor.RED, "/poll kick", "Click to kick a player", true))); } Component durationComponent = TemporalComponent.duration(duration, NamedTextColor.GREEN); if (builder) { - durationComponent = - durationComponent - .append(text(" - ", NamedTextColor.GRAY)) - .append( - formatButton( - "1m", - NamedTextColor.DARK_AQUA, - "/poll duration 1m", - "Click to set a 1 minute time limit", - false)) - .append( - formatButton( - "5m", - NamedTextColor.DARK_AQUA, - "/poll duration 5m", - "Click to set a 5 minute time limit", - false)) - .append( - formatButton( - "Custom", - NamedTextColor.DARK_AQUA, - "/poll duration", - "Click to set a custom time limit", - true)); + durationComponent = durationComponent + .append(text(" - ", NamedTextColor.GRAY)) + .append(formatButton( + "1m", + NamedTextColor.DARK_AQUA, + "/poll duration 1m", + "Click to set a 1 minute time limit", + false)) + .append(formatButton( + "5m", + NamedTextColor.DARK_AQUA, + "/poll duration 5m", + "Click to set a 5 minute time limit", + false)) + .append(formatButton( + "Custom", + NamedTextColor.DARK_AQUA, + "/poll duration", + "Click to set a custom time limit", + true)); } - Component thresholdComponent = - text() - .append(threshold.toComponent()) - .append(text(" for vote to pass.", NamedTextColor.GRAY)) - .hoverEvent(HoverEvent.showText(text("Click to adjust threshold", NamedTextColor.GRAY))) - .clickEvent(ClickEvent.suggestCommand("/poll threshold")) - .build(); + Component thresholdComponent = text() + .append(threshold.toComponent()) + .append(text(" for vote to pass.", NamedTextColor.GRAY)) + .hoverEvent(HoverEvent.showText(text("Click to adjust threshold", NamedTextColor.GRAY))) + .clickEvent(ClickEvent.suggestCommand("/poll threshold")) + .build(); if (question == null) { question = PollBuilder.generateQuestion(options); @@ -574,13 +541,12 @@ default void sendDetails( } default Component createEndActionLine(EndAction action, int index, boolean showRemove) { - Component remove = - formatIconButton( - MessageUtils.DENY, - null, - NamedTextColor.RED, - "/poll remove " + action.getValue(), - "Click to remove"); + Component remove = formatIconButton( + MessageUtils.DENY, + null, + NamedTextColor.RED, + "/poll remove " + action.getValue(), + "Click to remove"); TextComponent.Builder line = text(); diff --git a/core/src/main/java/dev/pgm/community/polls/PollEditAlerter.java b/core/src/main/java/dev/pgm/community/polls/PollEditAlerter.java index 99b8f9a4..bd9f5435 100644 --- a/core/src/main/java/dev/pgm/community/polls/PollEditAlerter.java +++ b/core/src/main/java/dev/pgm/community/polls/PollEditAlerter.java @@ -22,8 +22,8 @@ public interface PollEditAlerter { - static final NamedTextColor CATEGORY_COLOR = NamedTextColor.DARK_AQUA; - static final Component RESET_MSG = text("value has been reset", NamedTextColor.YELLOW); + NamedTextColor CATEGORY_COLOR = NamedTextColor.DARK_AQUA; + Component RESET_MSG = text("value has been reset", NamedTextColor.YELLOW); default void broadcastChange(CommandAudience sender, String announcement) { broadcastChange(sender, announcement, null, true); @@ -40,28 +40,24 @@ default void broadcastChange( if (value != null) { valueComponent = text(value.toString()); - if (value instanceof Duration) { - Duration time = (Duration) value; + if (value instanceof Duration time) { valueComponent = TemporalComponent.duration(time, NamedTextColor.AQUA); } - if (value instanceof MapInfo) { - MapInfo map = (MapInfo) value; + if (value instanceof MapInfo map) { valueComponent = map.getStyledName(MapNameStyle.COLOR); } - if (value instanceof UUID) { - UUID playerId = (UUID) value; + if (value instanceof UUID playerId) { valueComponent = player(playerId, NameStyle.FANCY); } - if (value instanceof PollThreshold) { - PollThreshold threshold = (PollThreshold) value; + if (value instanceof PollThreshold threshold) { valueComponent = threshold.toComponent(); } - if (value instanceof Component) { - valueComponent = (Component) value; + if (value instanceof Component component) { + valueComponent = component; } } @@ -69,11 +65,10 @@ default void broadcastChange( sender = new CommandAudience(Bukkit.getConsoleSender()); } - TextComponent.Builder broadcast = - text() - .append(sender.getStyledName()) - .append(BroadcastUtils.BROADCAST_DIV) - .append(text(category, CATEGORY_COLOR)); + TextComponent.Builder broadcast = text() + .append(sender.getStyledName()) + .append(BroadcastUtils.BROADCAST_DIV) + .append(text(category, CATEGORY_COLOR)); if (!empty) { broadcast.append(BroadcastUtils.BROADCAST_DIV).append(valueComponent); diff --git a/core/src/main/java/dev/pgm/community/polls/ending/types/CommandEndAction.java b/core/src/main/java/dev/pgm/community/polls/ending/types/CommandEndAction.java index fc18a167..e9b6dc05 100644 --- a/core/src/main/java/dev/pgm/community/polls/ending/types/CommandEndAction.java +++ b/core/src/main/java/dev/pgm/community/polls/ending/types/CommandEndAction.java @@ -9,13 +9,7 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; -public class CommandEndAction implements EndAction { - - private final String command; - - public CommandEndAction(String command) { - this.command = command; - } +public record CommandEndAction(String command) implements EndAction { public String getBukkitCommand() { return command.startsWith("/") ? command.substring(1) : command; diff --git a/core/src/main/java/dev/pgm/community/polls/ending/types/KickPlayerEndAction.java b/core/src/main/java/dev/pgm/community/polls/ending/types/KickPlayerEndAction.java index eff9a07c..d6315f29 100644 --- a/core/src/main/java/dev/pgm/community/polls/ending/types/KickPlayerEndAction.java +++ b/core/src/main/java/dev/pgm/community/polls/ending/types/KickPlayerEndAction.java @@ -17,15 +17,9 @@ import tc.oc.pgm.api.integration.Integration; import tc.oc.pgm.util.named.NameStyle; -public class KickPlayerEndAction implements EndAction { +public record KickPlayerEndAction(UUID targetId) implements EndAction { - private static int DELAY_SECONDS = 2; - - private final UUID targetId; - - public KickPlayerEndAction(UUID targetId) { - this.targetId = targetId; - } + private static final int DELAY_SECONDS = 2; public UUID getPlayerId() { return targetId; @@ -53,14 +47,10 @@ public void execute(Player creator) { .getFeatures() .getUsers() .renderUsername(targetId, NameStyle.FANCY) - .thenAcceptAsync( - playerName -> { - BroadcastUtils.sendGlobalMessage( - text() - .append(playerName) - .append(text(" is no longer online!", NamedTextColor.YELLOW)) - .build()); - }); + .thenAcceptAsync(playerName -> BroadcastUtils.sendGlobalMessage(text() + .append(playerName) + .append(text(" is no longer online!", NamedTextColor.YELLOW)) + .build())); return; } @@ -70,11 +60,10 @@ public void execute(Player creator) { Community.get(), () -> { // Send broadcast before kick, so name renders properly - BroadcastUtils.sendGlobalMessage( - text() - .append(player(target, NameStyle.FANCY)) - .append(text(" has been kicked!", NamedTextColor.RED, TextDecoration.BOLD)) - .build()); + BroadcastUtils.sendGlobalMessage(text() + .append(player(target, NameStyle.FANCY)) + .append(text(" has been kicked!", NamedTextColor.RED, TextDecoration.BOLD)) + .build()); target.kickPlayer(colorize("&4&lYou have been voted off the server!")); }, 20L * DELAY_SECONDS); @@ -83,9 +72,8 @@ public void execute(Player creator) { @Override public Component getName() { return text("Kick Player") - .hoverEvent( - HoverEvent.showText( - text("Kicks the target player upon completion", NamedTextColor.GRAY))); + .hoverEvent(HoverEvent.showText( + text("Kicks the target player upon completion", NamedTextColor.GRAY))); } @Override diff --git a/core/src/main/java/dev/pgm/community/polls/ending/types/MapEndAction.java b/core/src/main/java/dev/pgm/community/polls/ending/types/MapEndAction.java index 5379f009..033e824a 100644 --- a/core/src/main/java/dev/pgm/community/polls/ending/types/MapEndAction.java +++ b/core/src/main/java/dev/pgm/community/polls/ending/types/MapEndAction.java @@ -18,17 +18,7 @@ import tc.oc.pgm.util.named.MapNameStyle; import tc.oc.pgm.util.text.TextFormatter; -public class MapEndAction implements EndAction { - - private MapInfo map; - - public MapEndAction(MapInfo map) { - this.map = map; - } - - public MapInfo getMap() { - return map; - } +public record MapEndAction(MapInfo map) implements EndAction { @Override public String getValue() { @@ -72,19 +62,17 @@ private Component getFancyMapName() { } else if (!gamemodes.isEmpty()) { boolean acronyms = gamemodes.size() > 1; hover - .append( - TextFormatter.list( - gamemodes.stream() - .map(gm -> text(acronyms ? gm.getAcronym() : gm.getFullName())) - .collect(Collectors.toList()), - NamedTextColor.AQUA)) + .append(TextFormatter.list( + gamemodes.stream() + .map(gm -> text(acronyms ? gm.getAcronym() : gm.getFullName())) + .collect(Collectors.toList()), + NamedTextColor.AQUA)) .appendNewline(); } - hover.append( - text( - map.getTags().stream().map(MapTag::toString).collect(Collectors.joining(" ")), - NamedTextColor.YELLOW)); + hover.append(text( + map.getTags().stream().map(MapTag::toString).collect(Collectors.joining(" ")), + NamedTextColor.YELLOW)); return text() .append(map.getStyledName(MapNameStyle.PLAIN).color(NamedTextColor.AQUA)) @@ -105,12 +93,12 @@ public Component getDefaultQuestion() { @Override public boolean equals(Object other) { - if (!(other instanceof MapEndAction)) return false; - return ((MapEndAction) other).getMap().equals(getMap()); + if (!(other instanceof MapEndAction action)) return false; + return action.map().equals(map()); } @Override public int hashCode() { - return getMap().hashCode(); + return map().hashCode(); } } diff --git a/core/src/main/java/dev/pgm/community/polls/ending/types/NullEndAction.java b/core/src/main/java/dev/pgm/community/polls/ending/types/NullEndAction.java index edba881d..0a15e3bd 100644 --- a/core/src/main/java/dev/pgm/community/polls/ending/types/NullEndAction.java +++ b/core/src/main/java/dev/pgm/community/polls/ending/types/NullEndAction.java @@ -8,28 +8,16 @@ import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; -public class NullEndAction implements EndAction { - - private final String option; +public record NullEndAction(String option) implements EndAction { public NullEndAction() { this(null); } - public NullEndAction(String option) { - this.option = option; - } - - @Nullable - public String getOption() { - return option; - } - @Override public String getValue() { - return getOption(); + return option(); } @Override @@ -70,16 +58,15 @@ public Component getDefaultQuestion() { @Override public boolean equals(Object other) { - if (!(other instanceof NullEndAction)) return false; - NullEndAction otherAction = ((NullEndAction) other); - if (otherAction.getOption() != null) { - return otherAction.getOption().equalsIgnoreCase(getOption()); + if (!(other instanceof NullEndAction(String otherAction))) return false; + if (otherAction != null) { + return otherAction.equalsIgnoreCase(option()); } return true; } @Override public int hashCode() { - return Objects.hash(getOption()); + return Objects.hash(option()); } } diff --git a/core/src/main/java/dev/pgm/community/polls/events/PollVoteEvent.java b/core/src/main/java/dev/pgm/community/polls/events/PollVoteEvent.java index 87cec8d0..582caade 100644 --- a/core/src/main/java/dev/pgm/community/polls/events/PollVoteEvent.java +++ b/core/src/main/java/dev/pgm/community/polls/events/PollVoteEvent.java @@ -5,7 +5,7 @@ public class PollVoteEvent extends PollEvent { - private Player player; + private final Player player; public PollVoteEvent(Player player, Poll poll) { super(poll); diff --git a/core/src/main/java/dev/pgm/community/polls/response/SingleChoiceResponseConverter.java b/core/src/main/java/dev/pgm/community/polls/response/SingleChoiceResponseConverter.java index b7a6b025..d5c5aaf8 100644 --- a/core/src/main/java/dev/pgm/community/polls/response/SingleChoiceResponseConverter.java +++ b/core/src/main/java/dev/pgm/community/polls/response/SingleChoiceResponseConverter.java @@ -7,25 +7,12 @@ public class SingleChoiceResponseConverter { public static boolean convert(String input) { String cleanInput = input.trim().toLowerCase(); - switch (cleanInput) { - case "true": - case "yes": - case "y": - case "affirmative": - case "ok": - case "okay": - case "yeah": - return true; - case "false": - case "no": - case "n": - case "negative": - case "nope": - case "not okay": - return false; - default: + return switch (cleanInput) { + case "true", "yes", "y", "affirmative", "ok", "okay", "yeah" -> true; + case "false", "no", "n", "negative", "nope", "not okay" -> false; + default -> throw exception( "Invalid input: '" + input + "'! Please provide a valid 'yes' or 'no' response."); - } + }; } } diff --git a/core/src/main/java/dev/pgm/community/requests/MapCooldown.java b/core/src/main/java/dev/pgm/community/requests/MapCooldown.java index 252fbcd3..b3c86764 100644 --- a/core/src/main/java/dev/pgm/community/requests/MapCooldown.java +++ b/core/src/main/java/dev/pgm/community/requests/MapCooldown.java @@ -4,11 +4,9 @@ import java.time.Instant; import tc.oc.pgm.util.TimeUtils; -public class MapCooldown { - private final Instant endsAt; - - public MapCooldown(Duration cooldown) { - this.endsAt = Instant.now().plus(cooldown); +public record MapCooldown(Instant endsAt) { + public MapCooldown(Duration endsAt) { + this(Instant.now().plus(endsAt)); } public boolean hasExpired() { diff --git a/core/src/main/java/dev/pgm/community/requests/SponsorRequest.java b/core/src/main/java/dev/pgm/community/requests/SponsorRequest.java index e77b24da..2d1ef3f5 100644 --- a/core/src/main/java/dev/pgm/community/requests/SponsorRequest.java +++ b/core/src/main/java/dev/pgm/community/requests/SponsorRequest.java @@ -3,27 +3,4 @@ import java.util.UUID; import tc.oc.pgm.api.map.MapInfo; -public class SponsorRequest { - - private UUID playerId; - private MapInfo map; - private boolean canRefund; - - public SponsorRequest(UUID playerId, MapInfo map, boolean canRefund) { - this.playerId = playerId; - this.map = map; - this.canRefund = canRefund; - } - - public UUID getPlayerId() { - return playerId; - } - - public MapInfo getMap() { - return map; - } - - public boolean canRefund() { - return canRefund; - } -} +public record SponsorRequest(UUID playerId, MapInfo map, boolean canRefund) {} diff --git a/core/src/main/java/dev/pgm/community/requests/commands/sponsor/SponsorCommands.java b/core/src/main/java/dev/pgm/community/requests/commands/sponsor/SponsorCommands.java index 499d1471..45760a49 100644 --- a/core/src/main/java/dev/pgm/community/requests/commands/sponsor/SponsorCommands.java +++ b/core/src/main/java/dev/pgm/community/requests/commands/sponsor/SponsorCommands.java @@ -144,7 +144,7 @@ public void info(CommandAudience audience, Player player) { audience.sendMessage(current); audience.sendMessage(text() .append(text(" - ", NamedTextColor.YELLOW)) - .append(sponsor.getMap().getStyledName(MapNameStyle.COLOR_WITH_AUTHORS)) + .append(sponsor.map().getStyledName(MapNameStyle.COLOR_WITH_AUTHORS)) .build()); audience.sendMessage(queue); }); @@ -238,9 +238,9 @@ public void viewMapList( .append(text("Current online player range", NamedTextColor.DARK_AQUA)) .appendSpace() .append(text("(", NamedTextColor.GRAY)) - .append(text(bounds.getLowerBound(), NamedTextColor.GOLD)) + .append(text(bounds.lowerBound(), NamedTextColor.GOLD)) .append(text("-", NamedTextColor.GRAY)) - .append(text(bounds.getUpperBound(), NamedTextColor.GOLD)) + .append(text(bounds.upperBound(), NamedTextColor.GOLD)) .append(text(")", NamedTextColor.GRAY)) .build(); Component title = text() @@ -359,17 +359,17 @@ public void viewQueue(CommandAudience audience, @Argument("page") @Default("1") new PaginatedComponentResults(formattedTitle, resultsPerPage) { @Override public Component format(SponsorRequest sponsor, int index) { - MapInfo map = sponsor.getMap(); + MapInfo map = sponsor.map(); Component mapName = map.getStyledName(MapNameStyle.COLOR) .clickEvent(ClickEvent.runCommand("/map " + map.getName())) .hoverEvent(HoverEvent.showText(translatable( "command.maps.hover", NamedTextColor.GRAY, map.getStyledName(MapNameStyle.COLOR)))); - Component playerName = VisibilityUtils.isDisguised(sponsor.getPlayerId()) + Component playerName = VisibilityUtils.isDisguised(sponsor.playerId()) ? empty() : text() .append(BroadcastUtils.BROADCAST_DIV) - .append(player(sponsor.getPlayerId(), NameStyle.FANCY)) + .append(player(sponsor.playerId(), NameStyle.FANCY)) .build(); return text() @@ -404,19 +404,19 @@ private Component renderExtraInfo(Player player, RequestProfile profile) { .build(); } - if (info.getDuration() != null) { + if (info.timeLeft() != null) { boolean canClaim = profile.getSponsorTokens() < config.getMaxTokens(); if (canClaim) { return text() .append(text(" | ")) .append(text("Next token (")) - .append(text("+" + info.getAmount(), NamedTextColor.GREEN, TextDecoration.BOLD)) + .append(text("+" + info.amount(), NamedTextColor.GREEN, TextDecoration.BOLD)) .append(text("): ")) .append( - info.getDuration().isNegative() + info.timeLeft().isNegative() ? text("Now! Please rejoin") - : duration(info.getDuration(), NamedTextColor.YELLOW)) + : duration(info.timeLeft(), NamedTextColor.YELLOW)) .build(); } else { return text() diff --git a/core/src/main/java/dev/pgm/community/requests/commands/sponsor/TokenCommands.java b/core/src/main/java/dev/pgm/community/requests/commands/sponsor/TokenCommands.java index cf365652..074987b6 100644 --- a/core/src/main/java/dev/pgm/community/requests/commands/sponsor/TokenCommands.java +++ b/core/src/main/java/dev/pgm/community/requests/commands/sponsor/TokenCommands.java @@ -109,23 +109,7 @@ private void sendTokenBalanceMessage(Audience viewer, Component name, int tokens .build()); } - public static class TokenRefreshAmount { - private Duration timeLeft; - private int amount; - - public TokenRefreshAmount(Duration timeLeft, int amount) { - this.timeLeft = timeLeft; - this.amount = amount; - } - - public Duration getDuration() { - return timeLeft; - } - - public int getAmount() { - return amount; - } - } + public record TokenRefreshAmount(Duration timeLeft, int amount) {} public static TokenRefreshAmount getTimeLeft( Player player, Instant lastRefresh, RequestFeature requests) { @@ -152,13 +136,13 @@ private void sendRefreshDuration(Audience viewer, Player player, RequestProfile } TokenRefreshAmount info = getTimeLeft(player, profile.getLastTokenRefreshTime(), requests); - if (info.getDuration() != null) { + if (info.timeLeft() != null) { if (profile.getSponsorTokens() >= ((RequestConfig) requests.getConfig()).getMaxTokens()) { viewer.sendMessage(text("Spend some tokens in order to claim more", NamedTextColor.GRAY)); return; } - if (info.getDuration().isNegative()) { + if (info.timeLeft().isNegative()) { viewer.sendMessage( text("Token refresh ready! Please rejoin the server to claim", NamedTextColor.GRAY)); return; @@ -168,9 +152,9 @@ private void sendRefreshDuration(Audience viewer, Player player, RequestProfile .append(text("- ", NamedTextColor.YELLOW)) .append(text("Next token (")) .append(text("+", NamedTextColor.GREEN, TextDecoration.BOLD)) - .append(text(info.getAmount(), NamedTextColor.GREEN, TextDecoration.BOLD)) + .append(text(info.amount(), NamedTextColor.GREEN, TextDecoration.BOLD)) .append(text(") in ")) - .append(duration(info.getDuration(), NamedTextColor.YELLOW)) + .append(duration(info.timeLeft(), NamedTextColor.YELLOW)) .color(NamedTextColor.GRAY) .build()); } diff --git a/core/src/main/java/dev/pgm/community/requests/feature/RequestFeature.java b/core/src/main/java/dev/pgm/community/requests/feature/RequestFeature.java index 32558e62..30140b2d 100644 --- a/core/src/main/java/dev/pgm/community/requests/feature/RequestFeature.java +++ b/core/src/main/java/dev/pgm/community/requests/feature/RequestFeature.java @@ -19,14 +19,14 @@ import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerJoinEvent; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.api.map.MapInfo; public interface RequestFeature extends Feature { - static final String TOKEN_SYMBOL = "✪"; - static final Component TOKEN = text(TOKEN_SYMBOL, NamedTextColor.GOLD); - static final Component SPONSOR = text("+", NamedTextColor.GREEN, TextDecoration.BOLD); + String TOKEN_SYMBOL = "✪"; + Component TOKEN = text(TOKEN_SYMBOL, NamedTextColor.GOLD); + Component SPONSOR = text("+", NamedTextColor.GREEN, TextDecoration.BOLD); /** * Submit a map request diff --git a/core/src/main/java/dev/pgm/community/requests/feature/SponsorVotingBookCreator.java b/core/src/main/java/dev/pgm/community/requests/feature/SponsorVotingBookCreator.java index b8c2e55c..3b447bdf 100644 --- a/core/src/main/java/dev/pgm/community/requests/feature/SponsorVotingBookCreator.java +++ b/core/src/main/java/dev/pgm/community/requests/feature/SponsorVotingBookCreator.java @@ -37,13 +37,13 @@ public ComponentLike getHover(MatchPlayer viewer, MapInfo map, boolean voted) { // Add sponsor hover if available SponsorRequest sponsor = manager.getCurrentSponsor(); - if (sponsor != null && sponsor.getMap().equals(map)) { + if (sponsor != null && sponsor.map().equals(map)) { return text() .append(originalHover) .append(newline()) .append(text("+ ", NamedTextColor.YELLOW, TextDecoration.BOLD)) .append(text("Sponsored by ", NamedTextColor.GRAY)) - .append(player(sponsor.getPlayerId(), NameStyle.FANCY)) + .append(player(sponsor.playerId(), NameStyle.FANCY)) .build(); } @@ -136,7 +136,7 @@ private Component getVoteMultiplierComponent(int multiplier) { for (Rank rank : Community.get().getServerConfig().getRanksConfig().getRanks()) { Component rankComponent = text() - .append(text(rank.getPrefix() + " " + rank.getName(), rank.getTextColor())) + .append(text(rank.prefix() + " " + rank.name(), rank.getTextColor())) .append(text(" has a ", NamedTextColor.GRAY)) .append(text(rank.getVoteMultiplier() + "x", rank.getTextColor(), TextDecoration.BOLD)) .append(text(" multiplier", NamedTextColor.GRAY)) diff --git a/core/src/main/java/dev/pgm/community/requests/feature/types/RequestFeatureCore.java b/core/src/main/java/dev/pgm/community/requests/feature/types/RequestFeatureCore.java index 57bf21b9..a13d52fb 100644 --- a/core/src/main/java/dev/pgm/community/requests/feature/types/RequestFeatureCore.java +++ b/core/src/main/java/dev/pgm/community/requests/feature/types/RequestFeatureCore.java @@ -35,8 +35,16 @@ import dev.pgm.community.utils.VisibilityUtils; import java.time.Duration; import java.time.Instant; -import java.util.*; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Queue; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; @@ -383,21 +391,21 @@ public void onMatchEnd(MatchFinishEvent event) { if (nextRequest == null) return; // Notify PGM of the sponsored map and minimum cooldown - options.addMap(nextRequest.getMap(), nextRequest.getPlayerId()); - sponsor.startNewMapCooldown(nextRequest.getMap(), Duration.ZERO); + options.addMap(nextRequest.map(), nextRequest.playerId()); + sponsor.startNewMapCooldown(nextRequest.map(), Duration.ZERO); // Track the current sponsor sponsor.setCurrentSponsor(nextRequest); // Update profile - getRequestProfile(nextRequest.getPlayerId()).thenAcceptAsync(profile -> { + getRequestProfile(nextRequest.playerId()).thenAcceptAsync(profile -> { // Update RequestProfile with sponsor map info - profile.sponsor(nextRequest.getMap()); + profile.sponsor(nextRequest.map()); update(profile); }); // Alert online player if their sponsor request has been processed - sponsor.alertRequesterToConfirmation(nextRequest.getPlayerId()); + sponsor.alertRequesterToConfirmation(nextRequest.playerId()); }, 1, TimeUnit.SECONDS); @@ -411,11 +419,11 @@ public void onVoteEnd(MatchVoteFinishEvent event) { if (currentSponsor != null) { - Player player = Bukkit.getPlayer(currentSponsor.getPlayerId()); + Player player = Bukkit.getPlayer(currentSponsor.playerId()); // Same map = winner, refund the token even if offline - if (currentSponsor.getMap().equals(event.getPickedMap()) && currentSponsor.canRefund()) { - getRequestProfile(currentSponsor.getPlayerId()).thenAcceptAsync(profile -> { + if (currentSponsor.map().equals(event.getPickedMap()) && currentSponsor.canRefund()) { + getRequestProfile(currentSponsor.playerId()).thenAcceptAsync(profile -> { profile.giveSponsorToken(1); update(profile); @@ -439,16 +447,16 @@ public void onMatchJoinMessage(PlayerJoinMatchEvent event) { MapInfo map = event.getMatch().getMap(); if (getCurrentSponsor() == null) return; - if (VisibilityUtils.isDisguised(getCurrentSponsor().getPlayerId())) return; - if (!getCurrentSponsor().getMap().equals(map)) return; + if (VisibilityUtils.isDisguised(getCurrentSponsor().playerId())) return; + if (!getCurrentSponsor().map().equals(map)) return; event.getExtraLines().add(empty()); event .getExtraLines() - .add(SponsorComponents.getSponsoredJoinMessage(getCurrentSponsor().getPlayerId())); + .add(SponsorComponents.getSponsoredJoinMessage(getCurrentSponsor().playerId())); } - private Cache voteConfirm = + private final Cache voteConfirm = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build(); private static final List BLOCKED_COMMANDS = @@ -500,7 +508,7 @@ public SponsorRequest getCurrentSponsor() { @Override public boolean cancelSponsorRequest(UUID playerId) { - return this.sponsor.getSponsorQueue().removeIf(s -> s.getPlayerId().equals(playerId)); + return this.sponsor.getSponsorQueue().removeIf(s -> s.playerId().equals(playerId)); } @Override @@ -533,7 +541,7 @@ public Queue getSponsorQueue() { @Override public Optional getPendingSponsor(UUID playerId) { return this.sponsor.getSponsorQueue().stream() - .filter(sr -> sr.getPlayerId().equals(playerId)) + .filter(sr -> sr.playerId().equals(playerId)) .findAny(); } @@ -546,13 +554,13 @@ private void removeOfflineSponsors() { Iterator iterator = sponsor.getSponsorQueue().iterator(); while (iterator.hasNext()) { SponsorRequest request = iterator.next(); - Player player = Bukkit.getPlayer(request.getPlayerId()); + Player player = Bukkit.getPlayer(request.playerId()); if (player == null || !player.isOnline()) { iterator.remove(); - logger.info("Removed offline sponsor request:" + request.getPlayerId() + " for map " - + request.getMap().getName()); + logger.info("Removed offline sponsor request:" + request.playerId() + " for map " + + request.map().getName()); } } } diff --git a/core/src/main/java/dev/pgm/community/requests/services/RequestQuery.java b/core/src/main/java/dev/pgm/community/requests/services/RequestQuery.java index a0579dcf..d7bf265c 100644 --- a/core/src/main/java/dev/pgm/community/requests/services/RequestQuery.java +++ b/core/src/main/java/dev/pgm/community/requests/services/RequestQuery.java @@ -2,17 +2,15 @@ public interface RequestQuery { - static final String TABLE_FIELDS = + String TABLE_FIELDS = "(id VARCHAR(36) PRIMARY KEY, last_request_time LONG, last_request_map VARCHAR(255), last_sponsor_time LONG, last_sponsor_map VARCHAR(255), tokens INT, last_token_refresh LONG, super_votes INT, last_super_vote LONG)"; - static final String TABLE_NAME = "requests"; + String TABLE_NAME = "requests"; - static final String INSERT_REQUESTS_QUERY = - "INSERT INTO " + TABLE_NAME + " VALUES (?,?,?,?,?,?,?,?,?)"; + String INSERT_REQUESTS_QUERY = "INSERT INTO " + TABLE_NAME + " VALUES (?,?,?,?,?,?,?,?,?)"; - static final String UPDATE_REQUEST_QUERY = "UPDATE " + String UPDATE_REQUEST_QUERY = "UPDATE " + TABLE_NAME + " SET last_request_time = ?, last_request_map = ?, last_sponsor_time = ?, last_sponsor_map = ?, tokens = ?, last_token_refresh = ?, super_votes = ?, last_super_vote = ? WHERE id = ? "; - static final String SELECT_REQUEST_QUERY = - "SELECT * from " + TABLE_NAME + " WHERE id = ? LIMIT 1"; + String SELECT_REQUEST_QUERY = "SELECT * from " + TABLE_NAME + " WHERE id = ? LIMIT 1"; } diff --git a/core/src/main/java/dev/pgm/community/requests/services/SQLRequestService.java b/core/src/main/java/dev/pgm/community/requests/services/SQLRequestService.java index bdf35198..c56d743a 100644 --- a/core/src/main/java/dev/pgm/community/requests/services/SQLRequestService.java +++ b/core/src/main/java/dev/pgm/community/requests/services/SQLRequestService.java @@ -11,22 +11,17 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; public class SQLRequestService extends SQLFeatureBase implements RequestQuery { - private LoadingCache profileCache; + private final LoadingCache profileCache; public SQLRequestService() { super(TABLE_NAME, TABLE_FIELDS); - this.profileCache = CacheBuilder.newBuilder().build(new CacheLoader() { - @Override - public UserRequestData load(UUID key) throws Exception { - return new UserRequestData(key); - } - }); + this.profileCache = CacheBuilder.newBuilder().build(CacheLoader.from(UserRequestData::new)); } public CompletableFuture login(UUID playerId) { @@ -143,9 +138,9 @@ private long convertTime(Instant time) { return time.toEpochMilli(); } - private class UserRequestData { + private static class UserRequestData { - private UUID playerId; + private final UUID playerId; private RequestProfile profile; private boolean loaded; diff --git a/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorComponents.java b/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorComponents.java index 69d6b8c5..e06b8d05 100644 --- a/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorComponents.java +++ b/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorComponents.java @@ -28,9 +28,9 @@ public class SponsorComponents { public static ComponentLike getMapSizeBoundsComponent(MapSizeBounds bounds) { return text("(", NamedTextColor.YELLOW) - .append(text(bounds.getLowerBound(), NamedTextColor.GOLD)) + .append(text(bounds.lowerBound(), NamedTextColor.GOLD)) .append(text("-")) - .append(text(bounds.getUpperBound(), NamedTextColor.GOLD)) + .append(text(bounds.upperBound(), NamedTextColor.GOLD)) .append(text(")")); } diff --git a/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorManager.java b/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorManager.java index 79aedfde..34114320 100644 --- a/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorManager.java +++ b/core/src/main/java/dev/pgm/community/requests/sponsor/SponsorManager.java @@ -66,11 +66,11 @@ public LinkedList getSponsorQueue() { } public boolean isQueued(UUID playerId) { - return getSponsorQueue().stream().anyMatch(sr -> sr.getPlayerId().equals(playerId)); + return getSponsorQueue().stream().anyMatch(sr -> sr.playerId().equals(playerId)); } public boolean isMapQueued(MapInfo map) { - return getSponsorQueue().stream().anyMatch(sr -> sr.getMap().equals(map)); + return getSponsorQueue().stream().anyMatch(sr -> sr.map().equals(map)); } public boolean isQueueOpen() { @@ -104,7 +104,7 @@ public MapSizeBounds getCurrentMapSizeBounds() { public SponsorRequest getNextSponsor() { for (Iterator it = sponsors.iterator(); it.hasNext(); ) { SponsorRequest request = it.next(); - if (!isMapSizeAllowed(request.getMap())) { + if (!isMapSizeAllowed(request.map())) { sendWrongSizeMapError(request); continue; } @@ -188,12 +188,12 @@ public boolean isMapSizeAllowed(MapInfo map) { } private void sendWrongSizeMapError(SponsorRequest request) { - Player player = Bukkit.getPlayer(request.getPlayerId()); + Player player = Bukkit.getPlayer(request.playerId()); if (player == null || !player.isOnline()) return; Audience viewer = Audience.get(player); viewer.sendWarning(SponsorComponents.getWrongSizeMapError( - request.getMap().getStyledName(MapNameStyle.COLOR), getCurrentMapSizeBounds())); + request.map().getStyledName(MapNameStyle.COLOR), getCurrentMapSizeBounds())); } private void sendDelayedTokenRefreshMessage(Player player, int amount, boolean daily, int total) { diff --git a/core/src/main/java/dev/pgm/community/requests/supervotes/SuperVoteManager.java b/core/src/main/java/dev/pgm/community/requests/supervotes/SuperVoteManager.java index bdf57a79..7873a1bc 100644 --- a/core/src/main/java/dev/pgm/community/requests/supervotes/SuperVoteManager.java +++ b/core/src/main/java/dev/pgm/community/requests/supervotes/SuperVoteManager.java @@ -121,13 +121,9 @@ public boolean isActive(Player player) { return this.activeSuperVoters.contains(player.getUniqueId()); } - private class StoredPermission { - private PermissionAttachment attachment; - private String permission; - - public StoredPermission(Player player, String permission) { - this.attachment = player.addAttachment(Community.get()); - this.permission = permission; + private record StoredPermission(PermissionAttachment attachment, String permission) { + private StoredPermission(Player player, String permission) { + this(player.addAttachment(Community.get()), permission); } public void enable() { @@ -138,10 +134,6 @@ public void disable(Player player) { attachment.setPermission(permission, false); player.removeAttachment(attachment); } - - public String getPermission() { - return permission; - } } public void sendSuperVoterActivationFeedback(Player player) { diff --git a/core/src/main/java/dev/pgm/community/sessions/SessionQuery.java b/core/src/main/java/dev/pgm/community/sessions/SessionQuery.java index b0ccb578..528ad671 100644 --- a/core/src/main/java/dev/pgm/community/sessions/SessionQuery.java +++ b/core/src/main/java/dev/pgm/community/sessions/SessionQuery.java @@ -2,30 +2,17 @@ import java.util.UUID; -public class SessionQuery { - - private final UUID playerId; // the UUID of the player - private final boolean ignoreDisguised; // do we want to find a disguised session? - - public SessionQuery(UUID playerId, boolean ignoreDisguised) { - this.playerId = playerId; - this.ignoreDisguised = ignoreDisguised; - } - - public UUID getPlayerId() { - return playerId; - } - - public boolean ignoreDisguised() { - return ignoreDisguised; - } +/** + * @param playerId the UUID of the player + * @param ignoreDisguised do we want to find a disguised session? + */ +public record SessionQuery(UUID playerId, boolean ignoreDisguised) { @Override public boolean equals(Object obj) { - if (!(obj instanceof SessionQuery)) return false; - SessionQuery other = (SessionQuery) obj; + if (!(obj instanceof SessionQuery(UUID id, boolean disguised))) return false; - return other.playerId.equals(playerId) && other.ignoreDisguised == ignoreDisguised; + return id.equals(playerId) && disguised == ignoreDisguised; } @Override diff --git a/core/src/main/java/dev/pgm/community/sessions/VanishedSessionListener.java b/core/src/main/java/dev/pgm/community/sessions/VanishedSessionListener.java index 83ad1f96..79957430 100644 --- a/core/src/main/java/dev/pgm/community/sessions/VanishedSessionListener.java +++ b/core/src/main/java/dev/pgm/community/sessions/VanishedSessionListener.java @@ -6,25 +6,16 @@ import org.bukkit.event.Listener; import tc.oc.pgm.api.player.event.PlayerVanishEvent; -public class VanishedSessionListener implements Listener { - - private final SessionFeature sessions; - - public VanishedSessionListener(SessionFeature sessions) { - this.sessions = sessions; - } +public record VanishedSessionListener(SessionFeature sessions) implements Listener { @EventHandler public void onVanish(PlayerVanishEvent event) { Player player = event.getPlayer().getBukkit(); if (sessions.isPlayerJoining(player)) return; - sessions - .getLatestSession(player.getUniqueId(), false) - .thenAcceptAsync( - session -> { - sessions.endSession(session); - sessions.startSession(player); - }); + sessions.getLatestSession(player.getUniqueId(), false).thenAcceptAsync(session -> { + sessions.endSession(session); + sessions.startSession(player); + }); } } diff --git a/core/src/main/java/dev/pgm/community/sessions/services/SQLSessionService.java b/core/src/main/java/dev/pgm/community/sessions/services/SQLSessionService.java index c6161519..fb1bc5aa 100644 --- a/core/src/main/java/dev/pgm/community/sessions/services/SQLSessionService.java +++ b/core/src/main/java/dev/pgm/community/sessions/services/SQLSessionService.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import org.jetbrains.annotations.NotNull; public class SQLSessionService extends SQLFeatureBase implements SessionDataQuery { @@ -24,12 +23,7 @@ public class SQLSessionService extends SQLFeatureBase public SQLSessionService() { super(TABLE_NAME, TABLE_FIELDS); this.sessionCache = CacheBuilder.newBuilder() - .build(new CacheLoader() { - @Override - public SessionData load(@NotNull SessionQuery key) { - return new SessionData(key.getPlayerId(), key.ignoreDisguised()); - } - }); + .build(CacheLoader.from(key -> new SessionData(key.playerId(), key.ignoreDisguised()))); this.upsertLatestSessionQuery = DatabaseExecutor.getDialect().upsertLatestSessionQuery(); } @@ -146,7 +140,7 @@ public CompletableFuture query(SessionQuery target) { return new Session( UUID.fromString(id), UUID.fromString(player), disguised, server, start, end); }, - target.getPlayerId().toString(), + target.playerId().toString(), target.ignoreDisguised()) .thenApplyAsync(result -> { if (result != null) { @@ -157,7 +151,7 @@ public CompletableFuture query(SessionQuery target) { } } - private class SessionData { + private static class SessionData { private final UUID playerId; private final boolean ignoreDisguised; diff --git a/core/src/main/java/dev/pgm/community/sessions/services/SessionDataQuery.java b/core/src/main/java/dev/pgm/community/sessions/services/SessionDataQuery.java index 9aa695a1..8038ac4b 100644 --- a/core/src/main/java/dev/pgm/community/sessions/services/SessionDataQuery.java +++ b/core/src/main/java/dev/pgm/community/sessions/services/SessionDataQuery.java @@ -2,29 +2,28 @@ public interface SessionDataQuery { - static final String TABLE_NAME = "sessions"; - static final String TABLE_FIELDS = + String TABLE_NAME = "sessions"; + String TABLE_FIELDS = "(id VARCHAR(36) PRIMARY KEY, player VARCHAR(36), disguised BOOL, server VARCHAR(32), start_time BIGINT, end_time BIGINT)"; - static final String INSERT_SESSION_QUERY = "INSERT INTO " + TABLE_NAME + String INSERT_SESSION_QUERY = "INSERT INTO " + TABLE_NAME + "(id, player, disguised, server, start_time, end_time) VALUES (?, ?, ?, ?, ?, ?)"; - static final String UPDATE_SESSION_ENDTIME_QUERY = - "UPDATE " + TABLE_NAME + " SET end_time = ? WHERE id = ?"; + String UPDATE_SESSION_ENDTIME_QUERY = "UPDATE " + TABLE_NAME + " SET end_time = ? WHERE id = ?"; - static final String UPDATE_ONGOING_SESSION_ENDING_QUERY = + String UPDATE_ONGOING_SESSION_ENDING_QUERY = "UPDATE " + TABLE_NAME + " SET end_time = ? WHERE server = ? AND end_time IS NULL"; - static final String LATEST_TABLE_NAME = "latest_sessions"; - static final String LATEST_TABLE_FIELDS = + String LATEST_TABLE_NAME = "latest_sessions"; + String LATEST_TABLE_FIELDS = "(player VARCHAR(36), ignore_disguised BOOL, session_id VARCHAR(36), disguised BOOL, server VARCHAR(32), start_time BIGINT, end_time BIGINT, PRIMARY KEY (player, ignore_disguised))"; - static final String SELECT_LATEST_SESSION_QUERY = + String SELECT_LATEST_SESSION_QUERY = "SELECT * FROM " + LATEST_TABLE_NAME + " WHERE player = ? AND ignore_disguised = ? LIMIT 1"; - static final String UPDATE_LATEST_ENDTIME_QUERY = + String UPDATE_LATEST_ENDTIME_QUERY = "UPDATE " + LATEST_TABLE_NAME + " SET end_time = ? WHERE session_id = ?"; - static final String UPDATE_LATEST_ONGOING_SESSION_ENDING_QUERY = + String UPDATE_LATEST_ONGOING_SESSION_ENDING_QUERY = "UPDATE " + LATEST_TABLE_NAME + " SET end_time = ? WHERE server = ? AND end_time IS NULL"; } diff --git a/core/src/main/java/dev/pgm/community/teleports/TeleportCommand.java b/core/src/main/java/dev/pgm/community/teleports/TeleportCommand.java index e8f05f80..b3e1a5bc 100644 --- a/core/src/main/java/dev/pgm/community/teleports/TeleportCommand.java +++ b/core/src/main/java/dev/pgm/community/teleports/TeleportCommand.java @@ -40,12 +40,12 @@ public void teleportCommand( public void teleportAll(CommandAudience viewer, @Argument("target") Player target) { PlayerSelection selection = getPlayers(viewer, "*"); - if (selection.getPlayers().isEmpty()) { + if (selection.players().isEmpty()) { selection.sendNoPlayerComponent(viewer); return; } - teleport.teleport(viewer, selection.getPlayers(), target, selection.getText()); + teleport.teleport(viewer, selection.players(), target, selection.getText()); } @Command("tpteam ") @@ -57,8 +57,10 @@ public void teleportTeam( team.getPlayers().stream().map(MatchPlayer::getBukkit).collect(Collectors.toSet()); if (players.isEmpty()) { - viewer.sendWarning( - text().append(team.getName()).append(text(" has no players to teleport")).build()); + viewer.sendWarning(text() + .append(team.getName()) + .append(text(" has no players to teleport")) + .build()); return; } @@ -85,7 +87,7 @@ public void teleportLocation( return; } - if (!viewer.isPlayer()) TextException.playerOnly(); + if (!viewer.isPlayer()) throw TextException.playerOnly(); teleport.teleport(viewer, viewer.getPlayer(), location); } diff --git a/core/src/main/java/dev/pgm/community/teleports/TeleportFeatureBase.java b/core/src/main/java/dev/pgm/community/teleports/TeleportFeatureBase.java index 45701c15..1112e705 100644 --- a/core/src/main/java/dev/pgm/community/teleports/TeleportFeatureBase.java +++ b/core/src/main/java/dev/pgm/community/teleports/TeleportFeatureBase.java @@ -6,6 +6,7 @@ import dev.pgm.community.feature.FeatureBase; import dev.pgm.community.utils.CommandAudience; import dev.pgm.community.utils.Sounds; +import java.util.Objects; import java.util.logging.Logger; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -32,7 +33,8 @@ public TeleportConfig getTeleportConfig() { public void teleport( CommandAudience sender, Player teleporter, Location target, Component message) { boolean involved = sender.isPlayer() - && (sender.getPlayer().equals(teleporter) || sender.getPlayer().equals(teleporter)); + && (Objects.equals(sender.getPlayer(), teleporter) + || Objects.equals(sender.getPlayer(), teleporter)); teleporter.teleport(target); if (message != null) { @@ -57,7 +59,8 @@ public void teleport( Component targetMsg, boolean senderFeedback) { boolean involved = sender.isPlayer() - && (sender.getPlayer().equals(teleporter) || sender.getPlayer().equals(target)); + && (Objects.equals(sender.getPlayer(), teleporter) + || Objects.equals(sender.getPlayer(), target)); teleporter.teleport(target); diff --git a/core/src/main/java/dev/pgm/community/text/UTF8Control.java b/core/src/main/java/dev/pgm/community/text/UTF8Control.java index fb087a88..a5b76b0e 100644 --- a/core/src/main/java/dev/pgm/community/text/UTF8Control.java +++ b/core/src/main/java/dev/pgm/community/text/UTF8Control.java @@ -6,7 +6,6 @@ import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.PropertyResourceBundle; @@ -54,6 +53,6 @@ public ResourceBundle newBundle( @Override public List getCandidateLocales(String name, Locale locale) { - return Arrays.asList(Locale.ROOT); + return List.of(Locale.ROOT); } } diff --git a/core/src/main/java/dev/pgm/community/users/UserProfileImpl.java b/core/src/main/java/dev/pgm/community/users/UserProfileImpl.java index 51eba932..77b27f04 100644 --- a/core/src/main/java/dev/pgm/community/users/UserProfileImpl.java +++ b/core/src/main/java/dev/pgm/community/users/UserProfileImpl.java @@ -9,7 +9,7 @@ public class UserProfileImpl implements UserProfile { - private UUID playerId; + private final UUID playerId; private String username; private Instant firstLogin; private int joinCount; diff --git a/core/src/main/java/dev/pgm/community/users/UserProfileWithSessionCallback.java b/core/src/main/java/dev/pgm/community/users/UserProfileWithSessionCallback.java index 7c7a133b..d5f74038 100644 --- a/core/src/main/java/dev/pgm/community/users/UserProfileWithSessionCallback.java +++ b/core/src/main/java/dev/pgm/community/users/UserProfileWithSessionCallback.java @@ -4,5 +4,5 @@ public interface UserProfileWithSessionCallback { - public void run(UserProfile profile, Session session); + void run(UserProfile profile, Session session); } diff --git a/core/src/main/java/dev/pgm/community/users/commands/UserInfoCommands.java b/core/src/main/java/dev/pgm/community/users/commands/UserInfoCommands.java index 0c783cf1..176cf67e 100644 --- a/core/src/main/java/dev/pgm/community/users/commands/UserInfoCommands.java +++ b/core/src/main/java/dev/pgm/community/users/commands/UserInfoCommands.java @@ -4,6 +4,7 @@ import static net.kyori.adventure.text.Component.newline; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.translatable; +import static net.kyori.adventure.text.JoinConfiguration.separator; import static tc.oc.pgm.util.player.PlayerComponent.player; import static tc.oc.pgm.util.text.TemporalComponent.duration; import static tc.oc.pgm.util.text.TemporalComponent.relativePastApproximate; @@ -36,7 +37,6 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; @@ -71,52 +71,41 @@ public void seenPlayer(CommandAudience audience, @Argument("target") TargetPlaye boolean staff = audience.hasPermission(CommunityPermissions.STAFF); boolean findAnyone = audience.hasPermission(CommunityPermissions.FIND_ANYONE); - users.findUserWithSession( - target.getIdentifier(), - !staff, - (profile, session) -> { - if (profile == null || session == null) { - audience.sendWarning( - findAnyone - ? MessageUtils.formatUnseen(target.getIdentifier()) - : MessageUtils.formatNotFriend(target.getIdentifier())); - return; - } - - if (audience.isPlayer() - && !friends.isFriend(audience.getPlayer().getUniqueId(), profile.getId()) - && !findAnyone) { - audience.sendWarning( - text("You are not friends with ") - .append(text(profile.getUsername(), NamedTextColor.DARK_AQUA))); - return; - } + users.findUserWithSession(target.getIdentifier(), !staff, (profile, session) -> { + if (profile == null || session == null) { + audience.sendWarning( + findAnyone + ? MessageUtils.formatUnseen(target.getIdentifier()) + : MessageUtils.formatNotFriend(target.getIdentifier())); + return; + } - boolean online = !session.hasEnded(); - boolean disguised = session.isDisguised(); - boolean visible = online && (!disguised || staff); + if (audience.isPlayer() + && !friends.isFriend(audience.getPlayer().getUniqueId(), profile.getId()) + && !findAnyone) { + audience.sendWarning(text("You are not friends with ") + .append(text(profile.getUsername(), NamedTextColor.DARK_AQUA))); + return; + } - Component lastSeenMsg = - text() - .append(player(profile.getId(), NameStyle.FANCY)) - .append( - text( - visible ? " has been online for " : " was last seen ")) // TODO: translate - .append( - (visible - ? duration( - Duration.between(session.getLatestUpdateDate(), Instant.now())) - : TemporalComponent.relativePastApproximate( - session.getLatestUpdateDate())) - .color(online ? NamedTextColor.GREEN : NamedTextColor.DARK_GREEN)) - .append(text(session.isOnThisServer() ? "" : " on ")) - .append( - text(session.isOnThisServer() ? "" : session.getServerName()) - .color(online ? NamedTextColor.GREEN : NamedTextColor.DARK_GREEN)) - .color(NamedTextColor.GRAY) - .build(); - audience.sendMessage(lastSeenMsg); - }); + boolean online = !session.hasEnded(); + boolean disguised = session.isDisguised(); + boolean visible = online && (!disguised || staff); + + Component lastSeenMsg = text() + .append(player(profile.getId(), NameStyle.FANCY)) + .append(text(visible ? " has been online for " : " was last seen ")) // TODO: translate + .append((visible + ? duration(Duration.between(session.getLatestUpdateDate(), Instant.now())) + : TemporalComponent.relativePastApproximate(session.getLatestUpdateDate())) + .color(online ? NamedTextColor.GREEN : NamedTextColor.DARK_GREEN)) + .append(text(session.isOnThisServer() ? "" : " on ")) + .append(text(session.isOnThisServer() ? "" : session.getServerName()) + .color(online ? NamedTextColor.GREEN : NamedTextColor.DARK_GREEN)) + .color(NamedTextColor.GRAY) + .build(); + audience.sendMessage(lastSeenMsg); + }); } @Command("alts|alternateaccounts [target]") @@ -129,94 +118,78 @@ public void viewAlts(CommandAudience audience, @Argument("target") TargetPlayer return; } - users - .getStoredProfile(target.getIdentifier()) - .thenAcceptAsync( - profile -> { - if (profile == null) { - audience.sendWarning(MessageUtils.formatUnseen(target.getIdentifier())); - return; - } - - Set alts = users.getAlternateAccounts(profile.getId()).join(); - - Component targetPlayer = - users.renderUsername(profile.getId(), NameStyle.COLOR).join(); - if (alts.isEmpty()) { - audience.sendWarning( - translatable("moderation.alts.noAlts", NamedTextColor.GRAY, targetPlayer)); - return; - } - - Set altNames = - alts.stream() - .map( - altId -> { - Component name = users.renderUsername(altId, NameStyle.COLOR).join(); - - return text() - .append(name) - .clickEvent(ClickEvent.runCommand("/l " + altId.toString())) - .hoverEvent( - HoverEvent.showText( - text( - "Click to view punishment history of ", - NamedTextColor.GRAY) - .append(name))) - .build(); - }) - .collect(Collectors.toSet()); - - Component numberOfAlts = - text(alts.size(), NamedTextColor.YELLOW, TextDecoration.BOLD); - - Component altNameList = - text() - .append(targetPlayer) - .append(text(" has ")) - .append(numberOfAlts) - .append(text(" known alternate account")) - .append(text(alts.size() != 1 ? "s" : "")) - .append(text(": ")) - .append(TextFormatter.list(altNames, NamedTextColor.GRAY)) - .color(NamedTextColor.GRAY) - .build(); - - List altsWithBans = - alts.stream() - .filter(altId -> moderation.isBanned(altId.toString()).join()) - .map( - altId -> { - Component name = users.renderUsername(altId, NameStyle.FANCY).join(); - - return text() - .append(name) - .clickEvent(ClickEvent.runCommand("/l " + altId)) - .hoverEvent( - HoverEvent.showText( - text( - "Click to view punishment history of ", - NamedTextColor.GRAY) - .append(name))) - .build(); - }) - .collect(Collectors.toList()); - - Component numberOfBannedAlts = - text(altsWithBans.size(), NamedTextColor.YELLOW, TextDecoration.BOLD); - - Component altBans = - text() - .append(numberOfBannedAlts) - .append(text(" of these accounts are currently banned: ")) - .append(TextFormatter.list(altsWithBans, NamedTextColor.GRAY)) - .color(NamedTextColor.GRAY) - .build(); - audience.sendMessage(altNameList); - if (altsWithBans.size() > 0) { - audience.sendMessage(altBans); - } - }); + users.getStoredProfile(target.getIdentifier()).thenAcceptAsync(profile -> { + if (profile == null) { + audience.sendWarning(MessageUtils.formatUnseen(target.getIdentifier())); + return; + } + + Set alts = users.getAlternateAccounts(profile.getId()).join(); + + Component targetPlayer = + users.renderUsername(profile.getId(), NameStyle.COLOR).join(); + if (alts.isEmpty()) { + audience.sendWarning( + translatable("moderation.alts.noAlts", NamedTextColor.GRAY, targetPlayer)); + return; + } + + Set altNames = alts.stream() + .map(altId -> { + Component name = users.renderUsername(altId, NameStyle.COLOR).join(); + + return text() + .append(name) + .clickEvent(ClickEvent.runCommand("/l " + altId.toString())) + .hoverEvent(HoverEvent.showText( + text("Click to view punishment history of ", NamedTextColor.GRAY) + .append(name))) + .build(); + }) + .collect(Collectors.toSet()); + + Component numberOfAlts = text(alts.size(), NamedTextColor.YELLOW, TextDecoration.BOLD); + + Component altNameList = text() + .append(targetPlayer) + .append(text(" has ")) + .append(numberOfAlts) + .append(text(" known alternate account")) + .append(text(alts.size() != 1 ? "s" : "")) + .append(text(": ")) + .append(TextFormatter.list(altNames, NamedTextColor.GRAY)) + .color(NamedTextColor.GRAY) + .build(); + + List altsWithBans = alts.stream() + .filter(altId -> moderation.isBanned(altId.toString()).join()) + .map(altId -> { + Component name = users.renderUsername(altId, NameStyle.FANCY).join(); + + return text() + .append(name) + .clickEvent(ClickEvent.runCommand("/l " + altId)) + .hoverEvent(HoverEvent.showText( + text("Click to view punishment history of ", NamedTextColor.GRAY) + .append(name))) + .build(); + }) + .collect(Collectors.toList()); + + Component numberOfBannedAlts = + text(altsWithBans.size(), NamedTextColor.YELLOW, TextDecoration.BOLD); + + Component altBans = text() + .append(numberOfBannedAlts) + .append(text(" of these accounts are currently banned: ")) + .append(TextFormatter.list(altsWithBans, NamedTextColor.GRAY)) + .color(NamedTextColor.GRAY) + .build(); + audience.sendMessage(altNameList); + if (!altsWithBans.isEmpty()) { + audience.sendMessage(altBans); + } + }); } @Command("profile|user [all]") @@ -226,122 +199,95 @@ public void viewUserProfile( CommandAudience audience, @Argument("target") TargetPlayer target, @Argument("all") @Default("false") boolean viewAll) { - users.findUserWithSession( - target.getIdentifier(), - false, - (profile, session) -> { - if (profile == null || session == null) { - audience.sendWarning(MessageUtils.formatUnseen(target.getIdentifier())); - return; + users.findUserWithSession(target.getIdentifier(), false, (profile, session) -> { + if (profile == null || session == null) { + audience.sendWarning(MessageUtils.formatUnseen(target.getIdentifier())); + return; + } + + Component header = text("Account Info", NamedTextColor.RED) + .append(text(" - ", NamedTextColor.GRAY)) + .append(player(profile.getId(), NameStyle.FANCY)); + + Component uuid = + formatInfoField("UUID", text(profile.getId().toString(), NamedTextColor.YELLOW)); + Component firstLogin = + formatInfoField("First Login", formatDateWithHover(profile.getFirstLogin())); + Component lastLogin = + formatInfoField("Last Login", formatDateWithHover(session.getLatestUpdateDate())); + Component joinCount = + formatInfoField("Join Count", text(profile.getJoinCount(), NamedTextColor.LIGHT_PURPLE)); + + Component lastServer = + formatInfoField("Last Server", text(session.getServerName(), NamedTextColor.AQUA)); + + Component knownIPs = formatInfoField("Known IPs", empty()); + + audience.sendMessage(TextFormatter.horizontalLineHeading( + audience.getSender(), header, NamedTextColor.DARK_GRAY)); + + audience.sendMessage(uuid); + audience.sendMessage(firstLogin); + audience.sendMessage(lastLogin); + audience.sendMessage(joinCount); + audience.sendMessage(lastServer); + + if (audience.getSender().hasPermission(CommunityPermissions.RESTRICTED)) { + users.getLatestAddress(profile.getId()).thenAcceptAsync(latest -> { + final String lastIpFieldName = "Latest IP"; + + if (latest == null) { + audience.sendMessage(formatInfoField( + lastIpFieldName, + text("Unavailable", NamedTextColor.RED) + .hoverEvent(HoverEvent.showText(text( + "No IP info found (user has not logged in recently)", + NamedTextColor.RED))))); + } else { + audience.sendMessage(formatInfoField( + lastIpFieldName, + text() + .append(text(latest.getAddress(), NamedTextColor.AQUA)) + .append(text(" (")) + .append(relativePastApproximate(latest.getDate())) + .append(text(")")) + .color(NamedTextColor.GRAY) + .build())); } + }); - Component header = - text("Account Info", NamedTextColor.RED) - .append(text(" - ", NamedTextColor.GRAY)) - .append(player(profile.getId(), NameStyle.FANCY)); - - Component uuid = - formatInfoField("UUID", text(profile.getId().toString(), NamedTextColor.YELLOW)); - Component firstLogin = - formatInfoField("First Login", formatDateWithHover(profile.getFirstLogin())); - Component lastLogin = - formatInfoField("Last Login", formatDateWithHover(session.getLatestUpdateDate())); - Component joinCount = - formatInfoField( - "Join Count", text(profile.getJoinCount(), NamedTextColor.LIGHT_PURPLE)); - - Component lastServer = - formatInfoField("Last Server", text(session.getServerName(), NamedTextColor.AQUA)); - - Component knownIPs = formatInfoField("Known IPs", empty()); - - audience.sendMessage( - TextFormatter.horizontalLineHeading( - audience.getSender(), header, NamedTextColor.DARK_GRAY)); - - audience.sendMessage(uuid); - audience.sendMessage(firstLogin); - audience.sendMessage(lastLogin); - audience.sendMessage(joinCount); - audience.sendMessage(lastServer); - - if (audience.getSender().hasPermission(CommunityPermissions.RESTRICTED)) { - users - .getLatestAddress(profile.getId()) - .thenAcceptAsync( - latest -> { - final String lastIpFieldName = "Latest IP"; - - if (latest == null) { - audience.sendMessage( - formatInfoField( - lastIpFieldName, - text("Unavailable", NamedTextColor.RED) - .hoverEvent( - HoverEvent.showText( - text( - "No IP info found (user has not logged in recently)", - NamedTextColor.RED))))); - } else { - audience.sendMessage( - formatInfoField( - lastIpFieldName, - text() - .append(text(latest.getAddress(), NamedTextColor.AQUA)) - .append(text(" (")) - .append(relativePastApproximate(latest.getDate())) - .append(text(")")) - .color(NamedTextColor.GRAY) - .build())); - } - }); - - users - .getKnownIPs(profile.getId()) - .thenAcceptAsync( - ips -> { - if (ips.size() > 1) { - final int MAX_VIEWABLE = 6; - List viewableIps = Lists.newArrayList(ips); - if (!viewAll) { - viewableIps = viewableIps.subList(0, Math.min(ips.size(), MAX_VIEWABLE)); - } - audience.sendMessage( - knownIPs.append(text("(" + ips.size() + ")", NamedTextColor.GRAY))); - audience.sendMessage( - formatListItems( - viewableIps.stream() - .map( - ip -> - text() - .append(text(" - ", NamedTextColor.YELLOW)) - .append(text(ip, NamedTextColor.DARK_AQUA)) - .build()) - .collect(Collectors.toList()))); - if (ips.size() > MAX_VIEWABLE && !viewAll) { - audience.sendMessage( - text() - .append( - text( - ips.size() - MAX_VIEWABLE, - NamedTextColor.YELLOW, - TextDecoration.BOLD)) - .append(text(" Additional IPs found! ", NamedTextColor.DARK_AQUA)) - .append(text("[", NamedTextColor.GRAY)) - .append(text("View All", NamedTextColor.BLUE)) - .append(text("]", NamedTextColor.GRAY)) - .clickEvent( - ClickEvent.runCommand( - "/profile " + target.getIdentifier() + " true")) - .hoverEvent( - HoverEvent.showText( - text("Click to view all ips", NamedTextColor.GRAY))) - .build()); - } - } - }); + users.getKnownIPs(profile.getId()).thenAcceptAsync(ips -> { + if (ips.size() > 1) { + final int MAX_VIEWABLE = 6; + List viewableIps = Lists.newArrayList(ips); + if (!viewAll) { + viewableIps = viewableIps.subList(0, Math.min(ips.size(), MAX_VIEWABLE)); + } + audience.sendMessage( + knownIPs.append(text("(" + ips.size() + ")", NamedTextColor.GRAY))); + audience.sendMessage(formatListItems(viewableIps.stream() + .map(ip -> text() + .append(text(" - ", NamedTextColor.YELLOW)) + .append(text(ip, NamedTextColor.DARK_AQUA)) + .build()) + .collect(Collectors.toList()))); + if (ips.size() > MAX_VIEWABLE && !viewAll) { + audience.sendMessage(text() + .append( + text(ips.size() - MAX_VIEWABLE, NamedTextColor.YELLOW, TextDecoration.BOLD)) + .append(text(" Additional IPs found! ", NamedTextColor.DARK_AQUA)) + .append(text("[", NamedTextColor.GRAY)) + .append(text("View All", NamedTextColor.BLUE)) + .append(text("]", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.runCommand("/profile " + target.getIdentifier() + " true")) + .hoverEvent( + HoverEvent.showText(text("Click to view all ips", NamedTextColor.GRAY))) + .build()); + } } }); + } + }); } private Component formatDateWithHover(Instant pastDate) { @@ -354,7 +300,7 @@ private Component formatDateWithHover(Instant pastDate) { } private Component formatListItems(Collection components) { - return Component.join(newline(), components); + return Component.join(separator(newline()), components); } private Component formatInfoField(String field, Component value) { @@ -373,9 +319,7 @@ private void showOnlineAlts(CommandAudience audience, int page) { for (Player player : Bukkit.getOnlinePlayers()) { Set alts = getOnlineAltAccounts(player); - if (alts.isEmpty() || accountedFor.contains(player.getUniqueId())) { - continue; - } else { + if (!(alts.isEmpty() || accountedFor.contains(player.getUniqueId()))) { altAccounts.add(formatAltAccountList(player, alts)); accountedFor.add(player.getUniqueId()); accountedFor.addAll(alts); @@ -386,28 +330,28 @@ private void showOnlineAlts(CommandAudience audience, int page) { } private void showBannedAlts(CommandAudience audience, int page) { - CompletableFuture.runAsync( - () -> { - Set altAccounts = Sets.newHashSet(); - Set accountedFor = Sets.newHashSet(); - - for (Player player : Bukkit.getOnlinePlayers()) { - Set alts = users.getAlternateAccounts(player.getUniqueId()).join(); - Map punishmentMap = new HashMap<>(); - for (UUID alt : alts) { - Optional punishment = moderation.getActiveBan(alt.toString()).join(); - punishment.ifPresent(value -> punishmentMap.put(alt, value)); - } - - if (!punishmentMap.isEmpty() && !accountedFor.contains(player.getUniqueId())) { - altAccounts.add(formatAltAccountList(player, punishmentMap)); - accountedFor.add(player.getUniqueId()); - accountedFor.addAll(punishmentMap.keySet()); - } - } + CompletableFuture.runAsync(() -> { + Set altAccounts = Sets.newHashSet(); + Set accountedFor = Sets.newHashSet(); + + for (Player player : Bukkit.getOnlinePlayers()) { + Set alts = users.getAlternateAccounts(player.getUniqueId()).join(); + Map punishmentMap = new HashMap<>(); + for (UUID alt : alts) { + Optional punishment = + moderation.getActiveBan(alt.toString()).join(); + punishment.ifPresent(value -> punishmentMap.put(alt, value)); + } + + if (!punishmentMap.isEmpty() && !accountedFor.contains(player.getUniqueId())) { + altAccounts.add(formatAltAccountList(player, punishmentMap)); + accountedFor.add(player.getUniqueId()); + accountedFor.addAll(punishmentMap.keySet()); + } + } - sendAltList(audience, page, altAccounts, true); - }); + sendAltList(audience, page, altAccounts, true); + }); } private void sendAltList( @@ -415,26 +359,23 @@ private void sendAltList( int perPage = Math.max(15, altAccounts.size()); int pages = (altAccounts.size() + perPage - 1) / perPage; - Component pageHeader = - translatable( - "command.pageHeader", - NamedTextColor.GRAY, - text(Integer.toString(page), NamedTextColor.DARK_AQUA), - text(Integer.toString(pages), NamedTextColor.DARK_AQUA)); - - Component headerText = - translatable( - banned ? "Banned Alt-Accounts" : "moderation.alts.header", NamedTextColor.DARK_AQUA); - - Component header = - text() - .append(headerText) - .append(text(" (", NamedTextColor.GRAY)) - .append(text(Integer.toString(altAccounts.size()), NamedTextColor.DARK_AQUA)) - .append(text(")", NamedTextColor.GRAY)) - .append(text(" » ", NamedTextColor.GOLD)) - .append(pageHeader) - .build(); + Component pageHeader = translatable( + "command.pageHeader", + NamedTextColor.GRAY, + text(Integer.toString(page), NamedTextColor.DARK_AQUA), + text(Integer.toString(pages), NamedTextColor.DARK_AQUA)); + + Component headerText = translatable( + banned ? "Banned Alt-Accounts" : "moderation.alts.header", NamedTextColor.DARK_AQUA); + + Component header = text() + .append(headerText) + .append(text(" (", NamedTextColor.GRAY)) + .append(text(Integer.toString(altAccounts.size()), NamedTextColor.DARK_AQUA)) + .append(text(")", NamedTextColor.GRAY)) + .append(text(" » ", NamedTextColor.GOLD)) + .append(pageHeader) + .build(); Component formattedHeader = TextFormatter.horizontalLineHeading(audience.getSender(), header, NamedTextColor.BLUE); @@ -455,12 +396,11 @@ public Component formatEmpty() { } private Component formatAltAccountList(Player target, Set alts) { - Component names = - Component.join( - text(", ", NamedTextColor.GRAY), - alts.stream() - .map(pl -> users.renderUsername(pl, NameStyle.FANCY).join()) - .collect(Collectors.toSet())); + Component names = Component.join( + separator(text(", ", NamedTextColor.GRAY)), + alts.stream() + .map(pl -> users.renderUsername(pl, NameStyle.FANCY).join()) + .collect(Collectors.toSet())); Component size = text(Integer.toString(alts.size()), NamedTextColor.YELLOW); return text("[", NamedTextColor.GOLD) @@ -473,30 +413,24 @@ private Component formatAltAccountList(Player target, Set alts) { } private Component formatAltAccountList(Player target, Map alts) { - Component names = - Component.join( - text(", ", NamedTextColor.GRAY), - alts.entrySet().stream() - .map( - pl -> { - Punishment punishment = pl.getValue(); - List components = new ArrayList<>(); - components.add( - TemporalComponent.relativePastApproximate(punishment.getTimeIssued()) - .color(NamedTextColor.YELLOW)); - components.add(punishment.formatTimeComponent()); - components.add(text(punishment.getReason()).color(NamedTextColor.RED)); - - return users - .renderUsername(pl.getKey(), NameStyle.FANCY) - .join() - .hoverEvent( - HoverEvent.showText( - Component.join( - JoinConfiguration.separator(BroadcastUtils.BROADCAST_DIV), - components))); - }) - .collect(Collectors.toSet())); + Component names = Component.join( + separator(text(", ", NamedTextColor.GRAY)), + alts.entrySet().stream() + .map(pl -> { + Punishment punishment = pl.getValue(); + List components = new ArrayList<>(); + components.add(TemporalComponent.relativePastApproximate(punishment.getTimeIssued()) + .color(NamedTextColor.YELLOW)); + components.add(punishment.formatTimeComponent()); + components.add(text(punishment.getReason()).color(NamedTextColor.RED)); + + return users + .renderUsername(pl.getKey(), NameStyle.FANCY) + .join() + .hoverEvent(HoverEvent.showText( + Component.join(separator(BroadcastUtils.BROADCAST_DIV), components))); + }) + .collect(Collectors.toSet())); Component size = text(Integer.toString(alts.size()), NamedTextColor.YELLOW); return text("[", NamedTextColor.GOLD) diff --git a/core/src/main/java/dev/pgm/community/users/feature/UsersFeature.java b/core/src/main/java/dev/pgm/community/users/feature/UsersFeature.java index a0935bc8..47f38de0 100644 --- a/core/src/main/java/dev/pgm/community/users/feature/UsersFeature.java +++ b/core/src/main/java/dev/pgm/community/users/feature/UsersFeature.java @@ -10,11 +10,10 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.event.player.PlayerJoinEvent; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.named.NameStyle; import tc.oc.pgm.util.player.PlayerComponent; @@ -36,9 +35,10 @@ default CompletableFuture renderUsername(UUID userId, NameStyle style * @return The rendered name component of provided UUID */ default CompletableFuture renderUsername(Optional userId, NameStyle style) { - if (!userId.isPresent()) return CompletableFuture.completedFuture(PlayerComponent.CONSOLE); - return getStoredUsername(userId.get()) - .thenApplyAsync(name -> player(Bukkit.getPlayer(userId.get()), name, style)); + return userId + .map(uuid -> getStoredUsername(uuid) + .thenApplyAsync(name -> player(Bukkit.getPlayer(uuid), name, style))) + .orElseGet(() -> CompletableFuture.completedFuture(PlayerComponent.CONSOLE)); } /** @@ -147,7 +147,6 @@ default CompletableFuture renderUsername(Optional userId, NameS * @param target Player username * @param ignoreDisguised Whether the target's latest session should include disguised sessions * @param callback The callback to be ran with - * @throws ExecutionException */ default void findUserWithSession( String target, boolean ignoreDisguised, UserProfileWithSessionCallback callback) { @@ -158,7 +157,7 @@ default void findUserWithSession( return profile.getLatestSession(ignoreDisguised).join(); }), - (profile, session) -> callback.run(profile, session)); + callback::run); } /** @@ -167,7 +166,6 @@ default void findUserWithSession( * @param id Player UUID * @param ignoreDisguised Whether the target's latest session should include disguised sessions * @param callback The callback to be ran with - * @throws ExecutionException */ default void findUserWithSession( UUID id, boolean ignoreDisguised, UserProfileWithSessionCallback callback) { @@ -178,6 +176,6 @@ default void findUserWithSession( return profile.getLatestSession(ignoreDisguised).join(); }), - (profile, session) -> callback.run(profile, session)); + callback::run); } } diff --git a/core/src/main/java/dev/pgm/community/users/listeners/UserProfileLoginListener.java b/core/src/main/java/dev/pgm/community/users/listeners/UserProfileLoginListener.java index c1495138..4f7593f5 100644 --- a/core/src/main/java/dev/pgm/community/users/listeners/UserProfileLoginListener.java +++ b/core/src/main/java/dev/pgm/community/users/listeners/UserProfileLoginListener.java @@ -14,13 +14,7 @@ import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.text.TextParser; -public class UserProfileLoginListener implements Listener { - - private UsersFeature users; - - public UserProfileLoginListener(UsersFeature users) { - this.users = users; - } +public record UserProfileLoginListener(UsersFeature users) implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onLoginEvent(final PlayerJoinEvent event) { @@ -41,7 +35,7 @@ public void onPostLoginEvent(UserProfileLoadEvent event) { .replace("%name%", player.getName()); boolean message = command.startsWith("!send"); if (message) { - String msg = command.substring(5, command.length()); + String msg = command.substring(5); Audience.get(player).sendMessage(TextParser.parseComponent(MessageUtils.format(msg))); } else { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command); diff --git a/core/src/main/java/dev/pgm/community/users/services/AddressHistoryService.java b/core/src/main/java/dev/pgm/community/users/services/AddressHistoryService.java index f6d62c45..373e749d 100644 --- a/core/src/main/java/dev/pgm/community/users/services/AddressHistoryService.java +++ b/core/src/main/java/dev/pgm/community/users/services/AddressHistoryService.java @@ -15,39 +15,19 @@ public class AddressHistoryService implements AddressQuery { - private LoadingCache historyCache; + private final LoadingCache historyCache; - private LoadingCache latestCache; + private final LoadingCache latestCache; - private LoadingCache resolvedIPCache; + private final LoadingCache resolvedIPCache; - private LoadingCache altsCache; + private final LoadingCache altsCache; public AddressHistoryService() { - this.historyCache = CacheBuilder.newBuilder().build(new CacheLoader() { - @Override - public AddressHistory load(UUID key) throws Exception { - return new AddressHistory(key); - } - }); - this.latestCache = CacheBuilder.newBuilder().build(new CacheLoader() { - @Override - public LatestAddressInfo load(UUID key) throws Exception { - return new LatestAddressInfo(key); - } - }); - this.resolvedIPCache = CacheBuilder.newBuilder().build(new CacheLoader() { - @Override - public ResolvedIP load(String key) throws Exception { - return new ResolvedIP(key); - } - }); - this.altsCache = CacheBuilder.newBuilder().build(new CacheLoader() { - @Override - public IpAlts load(String key) throws Exception { - return new IpAlts(key); - } - }); + this.historyCache = CacheBuilder.newBuilder().build(CacheLoader.from(AddressHistory::new)); + this.latestCache = CacheBuilder.newBuilder().build(CacheLoader.from(LatestAddressInfo::new)); + this.resolvedIPCache = CacheBuilder.newBuilder().build(CacheLoader.from(ResolvedIP::new)); + this.altsCache = CacheBuilder.newBuilder().build(CacheLoader.from(IpAlts::new)); DatabaseExecutor.executeUpdateAsync(Query.createTable(IP_TABLE_NAME, IP_TABLE_FIELDS)); DatabaseExecutor.executeUpdateAsync( @@ -83,7 +63,7 @@ public void trackIp(UUID id, String address) { Set known = getKnownIps(id).join(); if (known == null || known.isEmpty() - || !known.stream().anyMatch(ip -> ip.equalsIgnoreCase(address))) { + || known.stream().noneMatch(ip -> ip.equalsIgnoreCase(address))) { // Add user to known ip-id list DatabaseExecutor.executeUpdateAsync(INSERT_IP_USER_QUERY, id.toString(), ipId); } @@ -184,9 +164,9 @@ public CompletableFuture> getAlternateAccounts(UUID playerId) { }); } - private class IpAlts { - private String ipId; - private Set playerIds; + private static class IpAlts { + private final String ipId; + private final Set playerIds; private boolean loaded; public IpAlts(String ipId) { @@ -214,7 +194,7 @@ public void setLoaded(boolean loaded) { public static class ResolvedIP { - private String ipId; + private final String ipId; private String address; private boolean loaded; @@ -244,8 +224,8 @@ public boolean isLoaded() { /** Holds Player ID and list of IP ids that match */ public static class AddressHistory { - private UUID playerId; - private Set addressesIds; + private final UUID playerId; + private final Set addressesIds; private boolean loaded; public AddressHistory(UUID playerId) { diff --git a/core/src/main/java/dev/pgm/community/users/services/AddressQuery.java b/core/src/main/java/dev/pgm/community/users/services/AddressQuery.java index 6fe6713f..555db126 100644 --- a/core/src/main/java/dev/pgm/community/users/services/AddressQuery.java +++ b/core/src/main/java/dev/pgm/community/users/services/AddressQuery.java @@ -2,67 +2,62 @@ public interface AddressQuery { - static final String IP_ADDRESS_FIELD = "address"; - static final String IP_ID_FIELD = "ip_id"; - static final String USER_ID_FIELD = "user_id"; - static final String DATE_FIELD = "last_time"; + String IP_ADDRESS_FIELD = "address"; + String IP_ID_FIELD = "ip_id"; + String USER_ID_FIELD = "user_id"; + String DATE_FIELD = "last_time"; - static final String IP_TABLE_FIELDS = + String IP_TABLE_FIELDS = String.format("(%s VARCHAR(15), %s VARCHAR(36))", IP_ADDRESS_FIELD, IP_ID_FIELD); - static final String IP_TABLE_NAME = "addresses"; + String IP_TABLE_NAME = "addresses"; - static final String IP_USER_TABLE_FIELDS = + String IP_USER_TABLE_FIELDS = String.format("(%s VARCHAR(36), %s VARCHAR(36))", USER_ID_FIELD, IP_ID_FIELD); - static final String IP_USER_TABLE_NAME = "ip_history"; - - static final String LATEST_IP_TABLE_FIELDS = - String.format( - "(%s VARCHAR(36) PRIMARY KEY, %s VARCHAR(15), %s LONG)", - USER_ID_FIELD, IP_ADDRESS_FIELD, DATE_FIELD); - static final String LATEST_IP_TABLE_NAME = "latest_ip"; - - static final String INSERT_LATEST_IP_QUERY = - "REPLACE INTO " - + LATEST_IP_TABLE_NAME - + "(" - + USER_ID_FIELD - + "," - + IP_ADDRESS_FIELD - + "," - + DATE_FIELD - + ")" - + " VALUES(?,?,?)"; - - static final String SELECT_IP_QUERY = + String IP_USER_TABLE_NAME = "ip_history"; + + String LATEST_IP_TABLE_FIELDS = String.format( + "(%s VARCHAR(36) PRIMARY KEY, %s VARCHAR(15), %s LONG)", + USER_ID_FIELD, IP_ADDRESS_FIELD, DATE_FIELD); + String LATEST_IP_TABLE_NAME = "latest_ip"; + + String INSERT_LATEST_IP_QUERY = "REPLACE INTO " + + LATEST_IP_TABLE_NAME + + "(" + + USER_ID_FIELD + + "," + + IP_ADDRESS_FIELD + + "," + + DATE_FIELD + + ")" + + " VALUES(?,?,?)"; + + String SELECT_IP_QUERY = "SELECT " + IP_ID_FIELD + " FROM " + IP_TABLE_NAME + " WHERE " + IP_ADDRESS_FIELD + " = ?"; - static final String INSERT_IP_QUERY = - "INSERT INTO " - + IP_TABLE_NAME - + " (" - + IP_ADDRESS_FIELD - + "," - + IP_ID_FIELD - + ") VALUES (?,?)"; - - static final String INSERT_IP_USER_QUERY = - "INSERT INTO " - + IP_USER_TABLE_NAME - + " (" - + USER_ID_FIELD - + "," - + IP_ID_FIELD - + ") VALUES (?,?)"; - - static final String SELECT_LATEST_IP_QUERY = + String INSERT_IP_QUERY = "INSERT INTO " + + IP_TABLE_NAME + + " (" + + IP_ADDRESS_FIELD + + "," + + IP_ID_FIELD + + ") VALUES (?,?)"; + + String INSERT_IP_USER_QUERY = "INSERT INTO " + + IP_USER_TABLE_NAME + + " (" + + USER_ID_FIELD + + "," + + IP_ID_FIELD + + ") VALUES (?,?)"; + + String SELECT_LATEST_IP_QUERY = "SELECT * FROM " + LATEST_IP_TABLE_NAME + " WHERE " + USER_ID_FIELD + " = ?"; - static final String SELECT_IP_HISTORY_QUERY = - "SELECT ip_id FROM " + IP_USER_TABLE_NAME + " WHERE user_id = ?"; + String SELECT_IP_HISTORY_QUERY = "SELECT ip_id FROM " + IP_USER_TABLE_NAME + " WHERE user_id = ?"; - static final String SELECT_IP_ID_QUERY = + String SELECT_IP_ID_QUERY = "SELECT " + IP_ADDRESS_FIELD + " FROM " + IP_TABLE_NAME + " WHERE " + IP_ID_FIELD + " = ?"; - static final String SELECT_ALTS_QUERY = + String SELECT_ALTS_QUERY = "SELECT " + USER_ID_FIELD + " FROM " + IP_USER_TABLE_NAME + " WHERE " + IP_ID_FIELD + " = ?"; } diff --git a/core/src/main/java/dev/pgm/community/users/services/SQLUserService.java b/core/src/main/java/dev/pgm/community/users/services/SQLUserService.java index e3eb9e2b..9c95d77c 100644 --- a/core/src/main/java/dev/pgm/community/users/services/SQLUserService.java +++ b/core/src/main/java/dev/pgm/community/users/services/SQLUserService.java @@ -16,17 +16,12 @@ public class SQLUserService extends SQLFeatureBase implements UserQuery { - private LoadingCache profileCache; + private final LoadingCache profileCache; public SQLUserService() { super(TABLE_NAME, TABLE_FIELDS); - this.profileCache = CacheBuilder.newBuilder().build(new CacheLoader() { - @Override - public UserData load(UUID key) throws Exception { - return new UserData(key); - } - }); + this.profileCache = CacheBuilder.newBuilder().build(CacheLoader.from(UserData::new)); } @Override @@ -109,9 +104,9 @@ public CompletableFuture login(UUID id, String username, String add }); } - private class UserData { + private static class UserData { - private UUID playerId; + private final UUID playerId; private UserProfile profile; private boolean loaded; diff --git a/core/src/main/java/dev/pgm/community/users/services/UserQuery.java b/core/src/main/java/dev/pgm/community/users/services/UserQuery.java index 2d79e789..293c5b35 100644 --- a/core/src/main/java/dev/pgm/community/users/services/UserQuery.java +++ b/core/src/main/java/dev/pgm/community/users/services/UserQuery.java @@ -2,17 +2,15 @@ public interface UserQuery { - static final String TABLE_FIELDS = + String TABLE_FIELDS = "(id VARCHAR(36) PRIMARY KEY, name VARCHAR(16), first_join LONG, join_count INT)"; - static final String TABLE_NAME = "users"; + String TABLE_NAME = "users"; - static final String INSERT_USER_QUERY = + String INSERT_USER_QUERY = "INSERT INTO " + TABLE_NAME + "(id, name, first_join, join_count) VALUES (?,?,?,?)"; - static final String USERNAME_QUERY = - "SELECT * from " + TABLE_NAME + " WHERE LOWER(name) = LOWER(?) LIMIT 1"; - static final String PLAYERID_QUERY = "SELECT * from " + TABLE_NAME + " WHERE id = ? LIMIT 1"; + String USERNAME_QUERY = "SELECT * from " + TABLE_NAME + " WHERE LOWER(name) = LOWER(?) LIMIT 1"; + String PLAYERID_QUERY = "SELECT * from " + TABLE_NAME + " WHERE id = ? LIMIT 1"; - static final String UPDATE_USER_QUERY = - "UPDATE " + TABLE_NAME + " SET name = ?, join_count = ? WHERE id = ? "; + String UPDATE_USER_QUERY = "UPDATE " + TABLE_NAME + " SET name = ?, join_count = ? WHERE id = ? "; } diff --git a/core/src/main/java/dev/pgm/community/utils/BroadcastUtils.java b/core/src/main/java/dev/pgm/community/utils/BroadcastUtils.java index 22761269..a7cee688 100644 --- a/core/src/main/java/dev/pgm/community/utils/BroadcastUtils.java +++ b/core/src/main/java/dev/pgm/community/utils/BroadcastUtils.java @@ -3,6 +3,7 @@ import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.space; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.title.Title.Times.times; import static net.kyori.adventure.title.Title.title; import dev.pgm.community.Community; @@ -13,12 +14,11 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.title.Title.Times; import net.kyori.adventure.util.Ticks; import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.bukkit.ViaUtils; @@ -124,7 +124,7 @@ public static void sendGlobalTitle( public static void sendGlobalTitle( @Nullable Component title, @Nullable Component subTitle, int stay, @Nullable Sound sound) { - Bukkit.getOnlinePlayers().stream().forEach(p -> { + Bukkit.getOnlinePlayers().forEach(p -> { Audience viewer = Audience.get(p); // Support legacy players if (ViaUtils.getProtocolVersion(p) <= ViaUtils.VERSION_1_7) { @@ -133,7 +133,7 @@ public static void sendGlobalTitle( viewer.showTitle(title( title == null ? empty() : title, subTitle == null ? empty() : subTitle, - Times.of(Ticks.duration(5), Ticks.duration(20 * stay), Ticks.duration(15)))); + times(Ticks.duration(5), Ticks.duration(20L * stay), Ticks.duration(15)))); if (sound != null) { viewer.playSound(sound); diff --git a/core/src/main/java/dev/pgm/community/utils/CommandAudience.java b/core/src/main/java/dev/pgm/community/utils/CommandAudience.java index 83a3efde..da6bdf74 100644 --- a/core/src/main/java/dev/pgm/community/utils/CommandAudience.java +++ b/core/src/main/java/dev/pgm/community/utils/CommandAudience.java @@ -6,15 +6,15 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.named.NameStyle; import tc.oc.pgm.util.player.PlayerComponent; public class CommandAudience { - private Audience audience; - private CommandSender sender; + private final Audience audience; + private final CommandSender sender; public static CommandAudience CONSOLE = new CommandAudience(Bukkit.getConsoleSender()); @@ -60,6 +60,6 @@ public void sendWarning(Component message) { } public boolean hasPermission(String permission) { - return isPlayer() ? getPlayer().hasPermission(permission) : true; + return !isPlayer() || getPlayer().hasPermission(permission); } } diff --git a/core/src/main/java/dev/pgm/community/utils/ImportUtils.java b/core/src/main/java/dev/pgm/community/utils/ImportUtils.java index 03bb6871..88b9f1f8 100644 --- a/core/src/main/java/dev/pgm/community/utils/ImportUtils.java +++ b/core/src/main/java/dev/pgm/community/utils/ImportUtils.java @@ -20,7 +20,7 @@ import java.util.Date; import java.util.List; import java.util.UUID; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; import tc.oc.pgm.util.text.TextException; public class ImportUtils { @@ -46,12 +46,22 @@ public static class BukkitBanEntry { private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); - private UUID uuid; - private String name; - private String source; - private String created; - private String expires; - private String reason; + private final UUID uuid; + private final String name; + private final String source; + private final String created; + private final String expires; + private final String reason; + + public BukkitBanEntry( + UUID uuid, String name, String source, String created, String expires, String reason) { + this.uuid = uuid; + this.name = name; + this.source = source; + this.created = created; + this.expires = expires; + this.reason = reason; + } public UUID getUUID() { return uuid; diff --git a/core/src/main/java/dev/pgm/community/utils/MessageUtils.java b/core/src/main/java/dev/pgm/community/utils/MessageUtils.java index 877ac125..5ca235ed 100644 --- a/core/src/main/java/dev/pgm/community/utils/MessageUtils.java +++ b/core/src/main/java/dev/pgm/community/utils/MessageUtils.java @@ -2,6 +2,7 @@ import static net.kyori.adventure.text.Component.space; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.separator; import static tc.oc.pgm.util.text.TemporalComponent.duration; import com.google.common.collect.Lists; @@ -35,7 +36,7 @@ public class MessageUtils { public static final Component TOKEN = text(TOKEN_SYMBOL, NamedTextColor.GOLD); public static final Component VOTE = text(VOTE_SYMBOL, NamedTextColor.LIGHT_PURPLE); - public static final Component getStoreLink() { + public static Component getStoreLink() { return text() .append(text( Community.get().getServerConfig().getStoreLink(), @@ -54,10 +55,11 @@ public static String formatKickScreenMessage(String headerTitle, List LegacyFormatUtils.horizontalLine(ChatColor.DARK_GRAY, LegacyFormatUtils.MAX_CHAT_WIDTH)); message.add(header); // Header Line - FIRST - lines.forEach(message::add); // Add messages + message.addAll(lines); // Add messages message.add(footer); // Footer Line - LAST - return TextTranslations.translateLegacy(Component.join(text("\n" + ChatColor.RESET), message)); + return TextTranslations.translateLegacy( + Component.join(separator(text("\n" + ChatColor.RESET)), message)); } public static Component formatUnseen(String target) { @@ -125,8 +127,8 @@ public static Component parseComponentWithURL(String line) { } } - private static final Pattern URL_PATTERN = Pattern.compile( - "(https?://[\\w\\-\\.]+(:\\d+)?(/[\\w\\-\\./?%&=]*)?)", Pattern.CASE_INSENSITIVE); + private static final Pattern URL_PATTERN = + Pattern.compile("(https?://[\\w\\-.]+(:\\d+)?(/[\\w\\-./?%&=]*)?)", Pattern.CASE_INSENSITIVE); private static Component addUrlEventsToComponent(Component component) { return component.replaceText( diff --git a/core/src/main/java/dev/pgm/community/utils/NameUtils.java b/core/src/main/java/dev/pgm/community/utils/NameUtils.java index 1e4b9766..482ef36a 100644 --- a/core/src/main/java/dev/pgm/community/utils/NameUtils.java +++ b/core/src/main/java/dev/pgm/community/utils/NameUtils.java @@ -13,7 +13,7 @@ public static boolean isMinecraftName(String name) { public static boolean isPlayerId(String uuid) { try { - UUID playerId = UUID.fromString(uuid); + UUID.fromString(uuid); return true; } catch (IllegalArgumentException e) { return false; diff --git a/core/src/main/java/dev/pgm/community/utils/PGMUtils.java b/core/src/main/java/dev/pgm/community/utils/PGMUtils.java index ed3db150..369b1ecf 100644 --- a/core/src/main/java/dev/pgm/community/utils/PGMUtils.java +++ b/core/src/main/java/dev/pgm/community/utils/PGMUtils.java @@ -68,23 +68,7 @@ public static MapInfo getCurrentMap() { return isPGMEnabled() && getMatch() != null ? getMatch().getMap() : null; } - public static class MapSizeBounds { - private int lowerBound; - private int upperBound; - - public MapSizeBounds(int lowerBound, int upperBound) { - this.lowerBound = lowerBound; - this.upperBound = upperBound; - } - - public int getLowerBound() { - return lowerBound; - } - - public int getUpperBound() { - return upperBound; - } - } + public record MapSizeBounds(int lowerBound, int upperBound) {} public static boolean isMapSizeAllowed( MapInfo map, int lowerBoundOffset, int upperBoundOffset, double scaleFactor) { @@ -93,7 +77,7 @@ public static boolean isMapSizeAllowed( int max = getMapMaxSize(map); - return max >= bounds.getLowerBound() && max <= bounds.getUpperBound(); + return max >= bounds.lowerBound() && max <= bounds.upperBound(); } return true; @@ -149,8 +133,7 @@ public static boolean isBlitz() { public static void setMapPool(CommandSender sender, MapPool pool) { if (isPGMEnabled()) { - if (PGM.get().getMapOrder() instanceof MapPoolManager) { - MapPoolManager manager = (MapPoolManager) PGM.get().getMapOrder(); + if (PGM.get().getMapOrder() instanceof MapPoolManager manager) { manager.updateActiveMapPool(pool, getMatch(), true, sender, null, 0); } } @@ -173,8 +156,7 @@ public static MapPool getActiveMapPool() { public static Optional getMapPool(String name) { if (isPGMEnabled()) { - if (PGM.get().getMapOrder() instanceof MapPoolManager) { - MapPoolManager manager = (MapPoolManager) PGM.get().getMapOrder(); + if (PGM.get().getMapOrder() instanceof MapPoolManager manager) { return Optional.ofNullable(manager.getMapPoolByName(name)); } } diff --git a/core/src/main/java/dev/pgm/community/utils/PaginatedComponentResults.java b/core/src/main/java/dev/pgm/community/utils/PaginatedComponentResults.java index 3315ec15..8bebed8b 100644 --- a/core/src/main/java/dev/pgm/community/utils/PaginatedComponentResults.java +++ b/core/src/main/java/dev/pgm/community/utils/PaginatedComponentResults.java @@ -12,8 +12,8 @@ public abstract class PaginatedComponentResults { - private Component header; - private int resultsPerPage; + private final Component header; + private final int resultsPerPage; /** * Constructor @@ -88,7 +88,7 @@ public void display(Audience audience, Collection data, int page) * @throws TextException no match exceptions */ public void display(Audience audience, List data, int page) throws TextException { - if (data.size() == 0) { + if (data.isEmpty()) { audience.sendWarning(formatEmpty()); return; } diff --git a/core/src/main/java/dev/pgm/community/utils/ranks/RankUtils.java b/core/src/main/java/dev/pgm/community/utils/ranks/RankUtils.java index 784e6273..0b1d7ffc 100644 --- a/core/src/main/java/dev/pgm/community/utils/ranks/RankUtils.java +++ b/core/src/main/java/dev/pgm/community/utils/ranks/RankUtils.java @@ -3,19 +3,18 @@ import dev.pgm.community.Community; import java.util.List; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.Nullable; public class RankUtils { - @Nullable - public static RanksConfig.Rank getHighestLevelRank(Player player) { + public static RanksConfig.@Nullable Rank getHighestLevelRank(Player player) { List allRanks = Community.get().getServerConfig().getRanksConfig().getRanks(); RanksConfig.Rank highestRank = null; for (RanksConfig.Rank rank : allRanks) { - if (player.hasPermission(rank.getPermission())) { - if (highestRank == null || rank.getWeight() > highestRank.getWeight()) { + if (player.hasPermission(rank.permission())) { + if (highestRank == null || rank.weight() > highestRank.weight()) { highestRank = rank; } } diff --git a/core/src/main/java/dev/pgm/community/utils/ranks/RanksConfig.java b/core/src/main/java/dev/pgm/community/utils/ranks/RanksConfig.java index a1b1fe38..e6729441 100644 --- a/core/src/main/java/dev/pgm/community/utils/ranks/RanksConfig.java +++ b/core/src/main/java/dev/pgm/community/utils/ranks/RanksConfig.java @@ -1,7 +1,6 @@ package dev.pgm.community.utils.ranks; import com.google.common.collect.Lists; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Set; @@ -41,57 +40,18 @@ public void reload(Configuration config) { ranks.add(rank); } - Collections.sort(ranks, Comparator.comparingInt(Rank::getWeight)); + ranks.sort(Comparator.comparingInt(Rank::weight)); } - public static class Rank { - private String name; - private String prefix; - private String permission; - private ChatColor color; - private int multiplier; - private int weight; - - public Rank( - String name, - String prefix, - String permission, - ChatColor color, - int multiplier, - int weight) { - this.name = name; - this.prefix = prefix; - this.color = color; - this.multiplier = multiplier; - this.weight = weight; - } - - public String getName() { - return name; - } - - public String getPrefix() { - return prefix; - } - - public String getPermission() { - return permission; - } - - public ChatColor getColor() { - return color; - } + public record Rank( + String name, String prefix, String permission, ChatColor color, int multiplier, int weight) { public NamedTextColor getTextColor() { - return TextFormatter.convert(getColor()); + return TextFormatter.convert(color()); } public int getVoteMultiplier() { return multiplier; } - - public int getWeight() { - return weight; - } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee3125fe0768e9a76ee977ac089eb657005e..61285a659d17295f1de7c53e24fdf13ad755c379 100644 GIT binary patch delta 37058 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 NNswbwE82Y!{{uvZmpcFe delta 36446 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 JWd7DQ`9Hc?h(rJY diff --git a/platform/platform-modern/src/main/java/dev/pgm/community/platform/modern/ModernInventoryUtils.java b/platform/platform-modern/src/main/java/dev/pgm/community/platform/modern/ModernInventoryUtils.java index 2b6bda4b..d38a6bb4 100644 --- a/platform/platform-modern/src/main/java/dev/pgm/community/platform/modern/ModernInventoryUtils.java +++ b/platform/platform-modern/src/main/java/dev/pgm/community/platform/modern/ModernInventoryUtils.java @@ -6,7 +6,6 @@ import dev.pgm.community.util.Supports; import java.util.List; import java.util.Random; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.bukkit.Material; import org.bukkit.attribute.Attribute; @@ -33,7 +32,7 @@ public ItemStack getRandomPotion(boolean splash, Random random) { case WATER, MUNDANE, THICK, AWKWARD, WEAVING, OOZING, INFESTED -> false; default -> true; }) - .collect(Collectors.toList()); + .toList(); PotionType randomType = safeTypes.get(random.nextInt(safeTypes.size())); ItemStack item = new ItemStack(splash ? Material.SPLASH_POTION : Material.POTION); if (item.getItemMeta() instanceof PotionMeta meta) { diff --git a/platform/platform-sportpaper/src/main/java/dev/pgm/community/platform/sportpaper/SpInventoryUtils.java b/platform/platform-sportpaper/src/main/java/dev/pgm/community/platform/sportpaper/SpInventoryUtils.java index c2c865aa..dfe161ca 100644 --- a/platform/platform-sportpaper/src/main/java/dev/pgm/community/platform/sportpaper/SpInventoryUtils.java +++ b/platform/platform-sportpaper/src/main/java/dev/pgm/community/platform/sportpaper/SpInventoryUtils.java @@ -6,7 +6,6 @@ import dev.pgm.community.util.Supports; import java.util.List; import java.util.Random; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.bukkit.Material; import org.bukkit.attribute.Attribute; @@ -30,7 +29,7 @@ public void addAttributeModifier(ItemMeta meta, Attribute attribute, AttributeMo public ItemStack getRandomPotion(boolean splash, Random random) { List safeTypes = Stream.of(PotionType.values()) .filter(p -> p != PotionType.WATER) // No water lol - .collect(Collectors.toList()); + .toList(); PotionType randomType = safeTypes.get(random.nextInt(safeTypes.size())); Potion potion = new Potion(randomType, 1, splash); ItemStack item = new ItemStack(Material.POTION); diff --git a/util/src/main/java/dev/pgm/community/util/Attributes.java b/util/src/main/java/dev/pgm/community/util/Attributes.java index df01cbeb..f60d6e46 100644 --- a/util/src/main/java/dev/pgm/community/util/Attributes.java +++ b/util/src/main/java/dev/pgm/community/util/Attributes.java @@ -10,7 +10,6 @@ public class Attributes { parse("GENERIC_KNOCKBACK_RESISTANCE", "KNOCKBACK_RESISTANCE"); private static Attribute parse(String... names) { - Attribute type = BukkitUtils.parse(Attribute::valueOf, names); - return type; + return BukkitUtils.parse(Attribute::valueOf, names); } }