diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d2d21ce..810607b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -52,7 +52,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: 17 + java-version: 25 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/src/main/java/pro/cloudnode/smp/smpcore/CitizenRequest.java b/src/main/java/pro/cloudnode/smp/smpcore/CitizenRequest.java index 6dda82d..cc4e1b5 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/CitizenRequest.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/CitizenRequest.java @@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable; import pro.cloudnode.smp.smpcore.command.Command; -import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -118,13 +117,6 @@ public void accept() { delete(); } - /** - * Rejects the request - */ - public void reject() { - delete(); - } - public CitizenRequest(final @NotNull ResultSet rs) throws SQLException { this( UUID.fromString(rs.getString("member")), @@ -137,10 +129,10 @@ public CitizenRequest(final @NotNull ResultSet rs) throws SQLException { public void save() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement( - "INSERT INTO `citizen_requests` (`member`, `nation`, `mode`, `created`, `expires`) VALUES (?," - + " ?, ?, ?, ?)") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement( + "INSERT INTO `citizen_requests` (`member`, `nation`, `mode`, `created`, `expires`) VALUES (?," + + " ?, ?, ?, ?)" + ) ) { stmt.setString(1, uuid.toString()); stmt.setString(2, nationID); @@ -162,8 +154,7 @@ public void save() { public void delete() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement( + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement( "DELETE FROM `citizen_requests` WHERE `member` = ? AND `nation` = ?") ) { stmt.setString(1, uuid.toString()); @@ -192,8 +183,7 @@ public void delete() { final @NotNull Nation nation ) { try ( - final @NotNull Connection conn = SMPCore.getInstance().db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement( + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement( "SELECT * FROM `citizen_requests` WHERE `member` = ? AND `nation` = ? LIMIT 1") ) { stmt.setString(1, member.uuid.toString()); @@ -221,8 +211,7 @@ public void delete() { */ public static @NotNull List<@NotNull CitizenRequest> get(final @NotNull Nation nation, final boolean mode) { try ( - final @NotNull Connection conn = SMPCore.getInstance().db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement( + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement( "SELECT * FROM `citizen_requests` WHERE `nation` = ? AND `mode` = ? ORDER BY `created`") ) { stmt.setString(1, nation.id); @@ -249,8 +238,7 @@ public void delete() { */ public static @NotNull List<@NotNull CitizenRequest> get(final @NotNull Member member, final boolean mode) { try ( - final @NotNull Connection conn = SMPCore.getInstance().db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement( + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement( "SELECT * FROM `citizen_requests` WHERE `member` = ? AND `mode` = ? ORDER BY `created`") ) { stmt.setString(1, member.uuid.toString()); @@ -280,11 +268,10 @@ public void delete() { */ public static void delete(final @NotNull List<@NotNull CitizenRequest> requests) { try ( - final @NotNull Connection conn = SMPCore.getInstance().db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement( + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement( "DELETE FROM `citizen_requests` WHERE `member` = ? AND `nation` = ?") ) { - conn.setAutoCommit(false); + SMPCore.getInstance().conn.setAutoCommit(false); for (final @NotNull CitizenRequest request : requests) { stmt.setString(1, request.uuid.toString()); stmt.setString(2, request.nationID); @@ -292,7 +279,8 @@ public static void delete(final @NotNull List<@NotNull CitizenRequest> requests) } stmt.executeBatch(); - conn.commit(); + SMPCore.getInstance().conn.commit(); + SMPCore.getInstance().conn.setAutoCommit(true); } catch (final @NotNull SQLException e) { SMPCore.getInstance().getLogger().log( diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java b/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java index 9c6f0d3..624e4bb 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Configuration.java @@ -70,9 +70,7 @@ public boolean deathBanEnabled() { case DAYS -> "days"; case MONTHS -> "months"; case YEARS -> "years"; - default -> { - throw new IllegalStateException("No relative time format for ChronoUnit " + unit); - } + default -> throw new IllegalStateException("No relative time format for ChronoUnit " + unit); })); return MiniMessage.miniMessage().deserialize(formatString, Formatter.number("t", t), diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Member.java b/src/main/java/pro/cloudnode/smp/smpcore/Member.java index 3bd242d..01e6f3e 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Member.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Member.java @@ -2,12 +2,9 @@ import io.papermc.paper.ban.BanListType; import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.metadata.MetadataValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -23,6 +20,7 @@ public final class Member { public final @NotNull UUID uuid; public @Nullable String nationID; + @SuppressWarnings("CanBeFinal") public boolean staff; public final @Nullable UUID altOwnerUUID; public final @NotNull Date added; @@ -39,7 +37,7 @@ public Member(final @NotNull OfflinePlayer player, final @Nullable Member altOwn this(player.getUniqueId(), null, false, altOwner == null ? null : altOwner.uuid, new Date()); } - private Member(final @NotNull ResultSet rs) throws @NotNull SQLException { + private Member(final @NotNull ResultSet rs) throws SQLException { this(UUID.fromString(rs.getString("uuid")), rs.getString("nation"), rs.getBoolean("staff"), rs.getString("alt_owner") == null ? null : UUID.fromString(rs.getString("alt_owner")), rs.getTimestamp("added")); } @@ -47,17 +45,6 @@ private Member(final @NotNull ResultSet rs) throws @NotNull SQLException { return SMPCore.getInstance().getServer().getOfflinePlayer(uuid); } - /** - * Check if player is online and not vanished - */ - public boolean onlineNotVanished() { - final @NotNull Optional<@NotNull Player> player = Optional.ofNullable(player().getPlayer()); - if (player.isEmpty()) return false; - for (final @NotNull MetadataValue meta : player.get().getMetadata("vanished")) - if (meta.asBoolean()) return false; - return player.get().isOnline(); - } - public boolean isActive() { return new Date().getTime() - player().getLastSeen() < (long) SMPCore.config().membersInactiveDays() * 24 * 60 * 60 * 1000; } @@ -74,19 +61,14 @@ public boolean isAlt() { return nationID == null ? Optional.empty() : Nation.get(nationID); } - public @NotNull Token createToken() throws @NotNull SQLException { - return Token.create(this); - } - - public @NotNull HashSet<@NotNull Token> tokens() { + public @NotNull Set<@NotNull Token> tokens() { return Token.get(this); } - public @NotNull HashSet<@NotNull Member> getAlts() { - final @NotNull HashSet<@NotNull Member> alts = new HashSet<>(); + public @NotNull Set<@NotNull Member> getAlts() { + final @NotNull Set<@NotNull Member> alts = new HashSet<>(); try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `members` WHERE `alt_owner` = ?") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `members` WHERE `alt_owner` = ?") ) { stmt.setString(1, uuid.toString()); final @NotNull ResultSet rs = stmt.executeQuery(); @@ -105,8 +87,7 @@ public void unban() { public void save() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("INSERT OR REPLACE INTO `members` (`uuid`, `nation`, `staff`, `alt_owner`, `added`) VALUES (?, ?, ?, ?, ?)") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("INSERT OR REPLACE INTO `members` (`uuid`, `nation`, `staff`, `alt_owner`, `added`) VALUES (?, ?, ?, ?, ?)") ) { stmt.setString(1, uuid.toString()); stmt.setString(2, nationID == null ? null : nationID); @@ -125,8 +106,7 @@ public void save() { */ private void remove() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("DELETE FROM `members` WHERE `uuid` = ?") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("DELETE FROM `members` WHERE `uuid` = ?") ) { stmt.setString(1, uuid.toString()); stmt.executeUpdate(); @@ -148,6 +128,7 @@ private void remove() { * * @return whether the member was deleted */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean delete() { if (!getAlts().isEmpty()) return false; final @NotNull OfflinePlayer player = player(); @@ -166,21 +147,13 @@ public boolean delete() { return true; } - public static @NotNull Member create(final @NotNull OfflinePlayer player, final @Nullable Member altOwner) { - final @NotNull Member member = new Member(player.getUniqueId(), null, false, altOwner == null ? null : altOwner.uuid, new Date()); - member.save(); - member.player().setWhitelisted(true); - return member; - } - public static @NotNull Optional<@NotNull Member> get(final @NotNull OfflinePlayer player) { return get(player.getUniqueId()); } public static @NotNull Optional<@NotNull Member> get(final @NotNull UUID uuid) { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `members` WHERE `uuid` = ? LIMIT 1") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `members` WHERE `uuid` = ? LIMIT 1") ) { stmt.setString(1, uuid.toString()); final @NotNull ResultSet rs = stmt.executeQuery(); @@ -193,11 +166,10 @@ public boolean delete() { } } - public static @NotNull HashSet<@NotNull Member> get() { - final @NotNull HashSet<@NotNull Member> members = new HashSet<>(); + public static @NotNull Set<@NotNull Member> get() { + final @NotNull Set<@NotNull Member> members = new HashSet<>(); try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `members`") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `members`") ) { final @NotNull ResultSet rs = stmt.executeQuery(); while (rs.next()) members.add(new Member(rs)); @@ -208,12 +180,11 @@ public boolean delete() { return members; } - public static @NotNull HashSet<@NotNull Member> get(int limit, int page) { + public static @NotNull Set<@NotNull Member> get(int limit, int page) { final int offset = (page - 1) * limit; - final @NotNull HashSet<@NotNull Member> members = new HashSet<>(); + final @NotNull Set<@NotNull Member> members = new HashSet<>(); try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `members` LIMIT ? OFFSET ?") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `members` LIMIT ? OFFSET ?") ) { stmt.setInt(1, limit); stmt.setInt(2, offset); @@ -226,11 +197,10 @@ public boolean delete() { return members; } - public static @NotNull HashSet<@NotNull Member> get(final @NotNull Nation nation) { - final @NotNull HashSet<@NotNull Member> members = new HashSet<>(); + public static @NotNull Set<@NotNull Member> get(final @NotNull Nation nation) { + final @NotNull Set<@NotNull Member> members = new HashSet<>(); try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `members` WHERE `nation` = ?") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `members` WHERE `nation` = ?") ) { stmt.setString(1, nation.id); final @NotNull ResultSet rs = stmt.executeQuery(); @@ -244,8 +214,7 @@ public boolean delete() { public static int count() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT COUNT(*) as `n` FROM `members`") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT COUNT(*) as `n` FROM `members`") ) { final @NotNull ResultSet rs = stmt.executeQuery(); rs.next(); @@ -257,10 +226,12 @@ public static int count() { } } + @SuppressWarnings("NullableProblems") public static @NotNull Set<@NotNull String> getNames() { return get().stream().map(m -> m.player().getName()).filter(Objects::nonNull).collect(Collectors.toSet()); } + @SuppressWarnings("NullableProblems") public static @NotNull Set<@NotNull String> getAltNames() { return get().stream().filter(Member::isAlt).map(m -> m.player().getName()).filter(Objects::nonNull).collect(Collectors.toSet()); } diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Messages.java b/src/main/java/pro/cloudnode/smp/smpcore/Messages.java index 1b29b95..0480c75 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Messages.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Messages.java @@ -22,10 +22,10 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.TimeZone; import java.util.stream.Collectors; @@ -241,7 +241,7 @@ public Messages() { } public @NotNull Component nationCitizensList(final @NotNull Nation nation, final @NotNull Permissible sender, final boolean other) { - final @NotNull HashSet<@NotNull Member> members = nation.citizens(); + final @NotNull Set<@NotNull Member> members = nation.citizens(); final @NotNull Component header = MiniMessage.miniMessage() .deserialize(Objects.requireNonNull(config.getString("nation.citizens.list.header")) .replaceAll("", "<#" + nation.color + ">") @@ -513,7 +513,7 @@ public Messages() { .ofNullable(player.player().getName()).orElse(player.player().getUniqueId().toString()))); } - public @NotNull Component errorDisallowedCharacters(final @NotNull HashSet<@NotNull Character> chars) { + public @NotNull Component errorDisallowedCharacters(final @NotNull Set<@NotNull Character> chars) { return MiniMessage.miniMessage() .deserialize(Objects.requireNonNull(config.getString("error.disallowed-characters")), Placeholder.unparsed("chars", chars.stream().map(String::valueOf).collect(Collectors.joining()))); } @@ -584,10 +584,6 @@ public Messages() { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("error.other-citizen")), Placeholder.unparsed("player", Optional.ofNullable(member.player().getName()).orElse(member.player().getUniqueId().toString()))); } - public @NotNull Component errorNotPlayer() { - return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("error.not-player"))); - } - public @NotNull Component errorKickLeadership() { return MiniMessage.miniMessage().deserialize(Objects.requireNonNull(config.getString("error.kick-leadership"))); } diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Nation.java b/src/main/java/pro/cloudnode/smp/smpcore/Nation.java index b53dff2..c7e125e 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Nation.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Nation.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; import java.util.stream.Stream; @@ -33,6 +34,7 @@ public final class Nation { *

* Max length: 128 */ + @SuppressWarnings("CanBeFinal") public @NotNull String name; /** @@ -40,6 +42,7 @@ public final class Nation { *

* Max length: 16 */ + @SuppressWarnings("CanBeFinal") public @NotNull String shortName; /** @@ -47,11 +50,13 @@ public final class Nation { *

* Max length: 6 */ + @SuppressWarnings("CanBeFinal") public @NotNull String color; /** * Nation leader's UUID */ + @SuppressWarnings("CanBeFinal") public @NotNull UUID leaderUUID; /** @@ -97,7 +102,7 @@ public Nation(final @NotNull String id, final @NotNull String name, final @NotNu this.bank = bank; } - public @NotNull HashSet<@NotNull Member> citizens() { + public @NotNull Set<@NotNull Member> citizens() { return Member.get(this); } @@ -166,7 +171,7 @@ public void remove(final @NotNull Member member) { getTeam().removePlayer(member.player()); } - public Nation(final @NotNull ResultSet rs) throws @NotNull SQLException { + public Nation(final @NotNull ResultSet rs) throws SQLException { this( rs.getString("id"), rs.getString("name"), @@ -182,8 +187,7 @@ public Nation(final @NotNull ResultSet rs) throws @NotNull SQLException { public void save() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("INSERT OR REPLACE INTO `nations` (`id`, `name`, `short_name`, `color`, `leader`, `vice`, `founded`, `founded_ticks`, `bank`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("INSERT OR REPLACE INTO `nations` (`id`, `name`, `short_name`, `color`, `leader`, `vice`, `founded`, `founded_ticks`, `bank`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)") ) { stmt.setString(1, id); stmt.setString(2, name); @@ -207,8 +211,7 @@ public void save() { public static @NotNull Optional<@NotNull Nation> get(final @NotNull String id) { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `nations` WHERE `id` = ? LIMIT 1") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `nations` WHERE `id` = ? LIMIT 1") ) { stmt.setString(1, id); final @NotNull ResultSet rs = stmt.executeQuery(); @@ -221,13 +224,12 @@ public void save() { } } - public static @NotNull HashSet<@NotNull Nation> get() { + public static @NotNull Set<@NotNull Nation> get() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `nations`") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `nations`") ) { final @NotNull ResultSet rs = stmt.executeQuery(); - final @NotNull HashSet<@NotNull Nation> nations = new HashSet<>(); + final @NotNull Set<@NotNull Nation> nations = new HashSet<>(); while (rs.next()) nations.add(new Nation(rs)); return nations; } diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Permission.java b/src/main/java/pro/cloudnode/smp/smpcore/Permission.java index 36c57ab..e1e624c 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Permission.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Permission.java @@ -3,159 +3,159 @@ import org.jetbrains.annotations.NotNull; public final class Permission { - public static @NotNull String RELOAD = "smpcore.reload"; - public static @NotNull String BAN = "smpcore.ban"; + public static final @NotNull String RELOAD = "smpcore.reload"; + public static final @NotNull String BAN = "smpcore.ban"; /** * See your own alts */ - public static @NotNull String ALT = "smpcore.alt"; + public static final @NotNull String ALT = "smpcore.alt"; /** * See someone else's alts */ - public static @NotNull String ALT_OTHER = "smpcore.alt.other"; + public static final @NotNull String ALT_OTHER = "smpcore.alt.other"; /** * Add an alt */ - public static @NotNull String ALT_ADD = "smpcore.alt.add"; + public static final @NotNull String ALT_ADD = "smpcore.alt.add"; /** * Add an alt for someone else */ - public static @NotNull String ALT_ADD_OTHER = "smpcore.alt.add.other"; + public static final @NotNull String ALT_ADD_OTHER = "smpcore.alt.add.other"; /** * Bypass the maximum alts limit */ - public static @NotNull String ALT_MAX_BYPASS = "smpcore.alt.bypass.max"; + public static final @NotNull String ALT_MAX_BYPASS = "smpcore.alt.bypass.max"; /** * Remove an alt */ - public static @NotNull String ALT_REMOVE = "smpcore.alt.remove"; + public static final @NotNull String ALT_REMOVE = "smpcore.alt.remove"; /** * Remove someone else's alt */ - public static @NotNull String ALT_REMOVE_OTHER = "smpcore.alt.remove.other"; + public static final @NotNull String ALT_REMOVE_OTHER = "smpcore.alt.remove.other"; /** * Remove an alt that has joined the server */ - public static @NotNull String ALT_REMOVE_JOINED = "smpcore.alt.remove.joined"; + public static final @NotNull String ALT_REMOVE_JOINED = "smpcore.alt.remove.joined"; - public static @NotNull String SEEN = "smpcore.seen"; + public static final @NotNull String SEEN = "smpcore.seen"; /** * Allow using `/seen` on staff */ - public static @NotNull String SEEN_STAFF = "smpcore.seen.staff"; + public static final @NotNull String SEEN_STAFF = "smpcore.seen.staff"; /** * Allow seeing the game time and date */ - public static @NotNull String TIME = "smpcore.time"; + public static final @NotNull String TIME = "smpcore.time"; /** * Access to the {@code /nation} command */ - public static @NotNull String NATION = "smpcore.nation"; + public static final @NotNull String NATION = "smpcore.nation"; /** * List the citizens of your nation */ - public static @NotNull String NATION_CITIZENS_LIST = "smpcore.nation.citizens.list"; + public static final @NotNull String NATION_CITIZENS_LIST = "smpcore.nation.citizens.list"; /** * List the member of any nation */ - public static @NotNull String NATION_CITIZENS_LIST_OTHER = "smpcore.nation.citizens.list.other"; + public static final @NotNull String NATION_CITIZENS_LIST_OTHER = "smpcore.nation.citizens.list.other"; /** * Kick citizens of your nation */ - public static @NotNull String NATION_CITIZENS_KICK = "smpcore.nation.citizens.kick"; + public static final @NotNull String NATION_CITIZENS_KICK = "smpcore.nation.citizens.kick"; /** * Kick citizens of any nation */ - public static @NotNull String NATION_CITIZENS_KICK_OTHER = "smpcore.nation.citizens.kick.other"; + public static final @NotNull String NATION_CITIZENS_KICK_OTHER = "smpcore.nation.citizens.kick.other"; /** * Request to join a nation */ - public static @NotNull String NATION_JOIN_REQUEST = "smpcore.nation.join.request"; + public static final @NotNull String NATION_JOIN_REQUEST = "smpcore.nation.join.request"; /** * Request to join a nation while already in a nation */ - public static @NotNull String NATION_JOIN_REQUEST_SWITCH = "smpcore.nation.join.request.switch"; + public static final @NotNull String NATION_JOIN_REQUEST_SWITCH = "smpcore.nation.join.request.switch"; /** * Join a nation without requesting */ - public static @NotNull String NATION_JOIN_FORCE = "smpcore.nation.join.force"; + public static final @NotNull String NATION_JOIN_FORCE = "smpcore.nation.join.force"; /** * Accept invitation to join nation */ - public static @NotNull String NATION_INVITE_ACCEPT = "smpcore.nation.invite.accept"; + public static final @NotNull String NATION_INVITE_ACCEPT = "smpcore.nation.invite.accept"; /** * Accept invitation to join nation while already in a nation */ - public static @NotNull String NATION_INVITE_ACCEPT_SWITCH = "smpcore.nation.invite.accept.switch"; + public static final @NotNull String NATION_INVITE_ACCEPT_SWITCH = "smpcore.nation.invite.accept.switch"; /** * Send invitation to join your nation */ - public static @NotNull String NATION_INVITE = "smpcore.nation.invite"; + public static final @NotNull String NATION_INVITE = "smpcore.nation.invite"; /** * Send invitation to join any nation */ - public static @NotNull String NATION_INVITE_OTHER = "smpcore.nation.invite.other"; + public static final @NotNull String NATION_INVITE_OTHER = "smpcore.nation.invite.other"; /** * Leave your nation */ - public static @NotNull String NATION_LEAVE = "smpcore.nation.leave"; + public static final @NotNull String NATION_LEAVE = "smpcore.nation.leave"; /** * Add member to your nation */ - public static @NotNull String NATION_CITIZEN_ADD = "smpcore.nation.citizens.add"; + public static final @NotNull String NATION_CITIZEN_ADD = "smpcore.nation.citizens.add"; /** * Add member to any nation */ - public static @NotNull String NATION_CITIZEN_ADD_OTHER = "smpcore.nation.citizens.add.other"; + public static final @NotNull String NATION_CITIZEN_ADD_OTHER = "smpcore.nation.citizens.add.other"; /** * Add member to nation even if they are already in another */ - public static @NotNull String NATION_CITIZEN_ADD_SWITCH = "smpcore.nation.citizens.add.switch"; + public static final @NotNull String NATION_CITIZEN_ADD_SWITCH = "smpcore.nation.citizens.add.switch"; /** * Appoint nation citizen as vice-leader of your nation */ - public static @NotNull String NATION_PROMOTE = "smpcore.nation.citizens.promote"; + public static final @NotNull String NATION_PROMOTE = "smpcore.nation.citizens.promote"; /** * Appoint nation citizen as vice-leader of any nation */ - public static @NotNull String NATION_PROMOTE_OTHER = "smpcore.nation.citizens.promote.other"; + public static final @NotNull String NATION_PROMOTE_OTHER = "smpcore.nation.citizens.promote.other"; /** * Relieve vice-leader of your nation of their duties */ - public static @NotNull String NATION_DEMOTE = "smpcore.nation.citizens.demote"; + public static final @NotNull String NATION_DEMOTE = "smpcore.nation.citizens.demote"; /** * Relieve vice-leader of any nation of their duties */ - public static @NotNull String NATION_DEMOTE_OTHER = "smpcore.nation.citizens.demote.other"; + public static final @NotNull String NATION_DEMOTE_OTHER = "smpcore.nation.citizens.demote.other"; /** * Bypass death ban. diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Rest.java b/src/main/java/pro/cloudnode/smp/smpcore/REST.java similarity index 87% rename from src/main/java/pro/cloudnode/smp/smpcore/Rest.java rename to src/main/java/pro/cloudnode/smp/smpcore/REST.java index d176e2f..890c44c 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Rest.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/REST.java @@ -11,14 +11,12 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Type; -import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.UUID; -public class Rest { - final @NotNull Javalin javalin = Javalin.create(config -> { - config.jsonMapper(new Mapper()); - }); +public class REST { + final @NotNull Javalin javalin = Javalin.create(config -> config.jsonMapper(new Mapper())); private void e404 (final @NotNull io.javalin.http.Context ctx) { ctx.status(404); @@ -34,7 +32,7 @@ private void e404 (final @NotNull io.javalin.http.Context ctx) { obj.addProperty("name", player.getName()); obj.addProperty("nation", member.nationID); obj.addProperty("staff", member.staff); - obj.addProperty("online", member.onlineNotVanished()); + obj.addProperty("online", !member.staff && player.isOnline()); obj.addProperty("whitelisted", player.isWhitelisted()); obj.addProperty("banned", player.isBanned()); obj.addProperty("altOwner", member.altOwnerUUID == null ? null : member.altOwnerUUID.toString()); @@ -61,7 +59,7 @@ private void e404 (final @NotNull io.javalin.http.Context ctx) { return obj; } - public Rest(final int port) { + public REST(final int port) { javalin.before(ctx -> { final @Nullable String origin = ctx.header("Origin"); ctx.header("Access-Control-Allow-Origin", origin == null ? "*" : origin); @@ -108,14 +106,21 @@ public Rest(final int port) { page = t; } - final @NotNull HashSet<@NotNull Member> members = limit == null ? Member.get() : Member.get(limit, page); + final @NotNull Set<@NotNull Member> members = limit == null ? Member.get() : Member.get(limit, page); final @NotNull JsonArray arr = new JsonArray(); for (final @NotNull Member member : members) { - if (filter != null) { - if (filter.equals("online") && !member.onlineNotVanished()) continue; - if (filter.equals("offline") && member.onlineNotVanished()) continue; - if (filter.equals("banned") && !member.player().isBanned()) continue; - } + if (filter != null) + switch (filter) { + case "online": + if (member.staff || !member.player().isOnline()) + continue; + case "offline": + if (!member.staff && member.player().isOnline()) + continue; + case "banned": + if (!member.player().isBanned()) + continue; + } final @NotNull JsonObject m = getMemberObject(member); if (include != null) { switch (include) { @@ -147,7 +152,7 @@ public Rest(final int port) { e404(ctx); return; } - final @NotNull HashSet<@NotNull Member> alts = member.get().getAlts(); + final @NotNull Set<@NotNull Member> alts = member.get().getAlts(); final @NotNull JsonObject obj = getMemberObject(member.get()); final @NotNull JsonArray altsArray = new JsonArray(); for (final @NotNull Member alt : alts) { @@ -165,7 +170,7 @@ public Rest(final int port) { }); javalin.get("/nations", ctx -> { - final @NotNull HashSet<@NotNull Nation> nations = Nation.get(); + final @NotNull Set<@NotNull Nation> nations = Nation.get(); final @NotNull JsonArray arr = new JsonArray(); for (final @NotNull Nation nation : nations) arr.add(getNationObject(nation)); @@ -186,7 +191,7 @@ public Rest(final int port) { switch (include) { case "members" -> { final @NotNull JsonArray arr = new JsonArray(); - final @NotNull HashSet<@NotNull Member> members = nation.get().citizens(); + final @NotNull Set<@NotNull Member> members = nation.get().citizens(); for (final @NotNull Member member : members) arr.add(getMemberObject(member)); obj.add("members", arr); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java index ee5b0a6..99c0e42 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/SMPCore.java @@ -16,11 +16,12 @@ import pro.cloudnode.smp.smpcore.command.SeenCommand; import pro.cloudnode.smp.smpcore.command.TimeCommand; import pro.cloudnode.smp.smpcore.command.UnbanCommand; -import pro.cloudnode.smp.smpcore.listener.NationTeamUpdaterListener; +import pro.cloudnode.smp.smpcore.listener.PlayerJoinListener; import pro.cloudnode.smp.smpcore.listener.PlayerDeathListener; import pro.cloudnode.smp.smpcore.listener.PlayerPostRespawnListener; -import pro.cloudnode.smp.smpcore.listener.PlayerSlotsListener; import pro.cloudnode.smp.smpcore.listener.PlayerPreLoginListener; +import pro.cloudnode.smp.smpcore.listener.PlayerServerFullCheckListener; +import pro.cloudnode.smp.smpcore.listener.ServerListPingListener; import java.io.IOException; import java.io.InputStream; @@ -33,6 +34,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Consumer; import java.util.logging.Level; import java.util.regex.Matcher; @@ -44,11 +46,8 @@ public final class SMPCore extends JavaPlugin { } public final @NotNull HikariConfig hikariConfig = new HikariConfig(); - private HikariDataSource dbSource; - - public @NotNull HikariDataSource db() { - return dbSource; - } + private HikariDataSource db; + Connection conn; private @Nullable Configuration config; private @Nullable Messages messages; @@ -61,7 +60,7 @@ public final class SMPCore extends JavaPlugin { return Objects.requireNonNull(getInstance().messages); } - private @Nullable Rest rest; + private @Nullable REST rest; @Override public void onEnable() { @@ -74,13 +73,14 @@ public void onEnable() { reload(); initDatabase(); - getServer().getPluginManager().registerEvents(new NationTeamUpdaterListener(), this); - getServer().getPluginManager().registerEvents(new PlayerSlotsListener(), this); + getServer().getPluginManager().registerEvents(new PlayerJoinListener(), this); + getServer().getPluginManager().registerEvents(new ServerListPingListener(), this); + getServer().getPluginManager().registerEvents(new PlayerServerFullCheckListener(), this); getServer().getPluginManager().registerEvents(new PlayerDeathListener(), this); getServer().getPluginManager().registerEvents(new PlayerPreLoginListener(), this); getServer().getPluginManager().registerEvents(new PlayerPostRespawnListener(), this); - final @NotNull HashMap<@NotNull String, @NotNull Command> commands = new HashMap<>() {{ + final Map commands = new HashMap<>() {{ put("smpcore", new MainCommand()); put("ban", new BanCommand()); put("unban", new UnbanCommand()); @@ -90,22 +90,29 @@ public void onEnable() { put("citizens", new CitizensCommand()); }}; commands.put("alts", new AltsCommand(commands.get("smpcore"))); - for (final @NotNull Map.Entry<@NotNull String, @NotNull Command> entry : commands.entrySet()) + for (final Map.Entry entry : commands.entrySet()) Objects.requireNonNull(getServer().getPluginCommand(entry.getKey())).setExecutor(entry.getValue()); } @Override public void onDisable() { - db().close(); + try { + conn.close(); + } + catch (SQLException e) { + getLogger().log(Level.SEVERE, "failed to close db connection", e); + } + db.close(); if (rest != null) rest.javalin.stop(); } public void reload() { - if (config != null) config.reload(); + Objects.requireNonNull(config); + config.reload(); if (messages != null) messages.reload(); setupDatabase(); if (rest != null) rest.javalin.stop(); - rest = new Rest(config.apiPort()); + rest = new REST(config.apiPort()); } private void disable() { @@ -126,30 +133,37 @@ private void setupDatabase() { hikariConfig.addDataSourceProperty("elideSetAutoCommits", "true"); hikariConfig.addDataSourceProperty("maintainTimeStats", "true"); - dbSource = new HikariDataSource(hikariConfig); + db = new HikariDataSource(hikariConfig); + try { + conn = db.getConnection(); + } + catch (final SQLException e) { + getLogger().log(Level.SEVERE, "could not get db connection", e); + disable(); + } } private void initDatabase() { - final @NotNull String setup; - try (final @Nullable InputStream in = getClassLoader().getResourceAsStream("init.sql")) { + final String setup; + try (final InputStream in = getClassLoader().getResourceAsStream("init.sql")) { setup = new String(Objects.requireNonNull(in).readAllBytes()); } - catch (final @NotNull IOException e) { + catch (final IOException e) { getLogger().log(Level.SEVERE, "db init: could not read db setup file", e); disable(); return; } - final @NotNull String @NotNull [] queries = setup.split(";"); - for (@NotNull String q : queries) { - final @NotNull String query = q.stripTrailing().stripIndent().replaceAll("^\\s+(?:--.+)*", ""); + final String[] queries = setup.split(";"); + for (String q : queries) { + final String query = q.stripTrailing().stripIndent().replaceAll("^\\s+(?:--.+)*", ""); if (query.isBlank()) continue; try ( - final @NotNull Connection conn = db().getConnection(); - final @NotNull PreparedStatement stmt = conn.prepareStatement(query) + final Connection conn = db.getConnection(); + final PreparedStatement stmt = conn.prepareStatement(query) ) { stmt.executeUpdate(); } - catch (final @NotNull SQLException e) { + catch (final SQLException e) { getLogger().log(Level.SEVERE, "db init: could not execute query: " + query, e); disable(); return; @@ -165,17 +179,17 @@ public static void runMain(final @NotNull Runnable runnable) { getInstance().getServer().getScheduler().runTask(getInstance(), runnable); } - public static @NotNull HashSet<@NotNull Character> getDisallowedCharacters(final @NotNull String source, final @NotNull Pattern pattern) { - final @NotNull Matcher matcher = pattern.matcher(source); - final @NotNull HashSet<@NotNull Character> chars = new HashSet<>(); + public static @NotNull Set<@NotNull Character> getDisallowedCharacters(final @NotNull String source, final @NotNull Pattern pattern) { + final Matcher matcher = pattern.matcher(source); + final Set chars = new HashSet<>(); while (matcher.find()) for (char c : matcher.group().toCharArray()) chars.add(c); return chars; } - public static boolean ifDisallowedCharacters(final @NotNull String source, final @NotNull Pattern pattern, final @NotNull Consumer<@NotNull HashSet<@NotNull Character>> consumer) { - final @NotNull HashSet<@NotNull Character> chars = getDisallowedCharacters(source, pattern); + public static boolean ifDisallowedCharacters(final @NotNull String source, final @NotNull Pattern pattern, final @NotNull Consumer<@NotNull Set<@NotNull Character>> consumer) { + final Set chars = getDisallowedCharacters(source, pattern); if (!chars.isEmpty()) { consumer.accept(chars); return true; @@ -193,7 +207,7 @@ public static boolean ifDisallowedCharacters(final @NotNull String source, final final double months = Math.floor(days / 30.0); final double years = Math.floor(months / 12.0); - final @NotNull Component t; + final Component t; if (years > 0) t = SMPCore.config().relativeTime(years, ChronoUnit.YEARS); else if (months > 0) t = SMPCore.config().relativeTime((int) months, ChronoUnit.MONTHS); else if (days > 0) t = SMPCore.config().relativeTime((int) days, ChronoUnit.DAYS); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/Token.java b/src/main/java/pro/cloudnode/smp/smpcore/Token.java index 67cce84..48d9e5e 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/Token.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/Token.java @@ -1,7 +1,6 @@ package pro.cloudnode.smp.smpcore; import org.jetbrains.annotations.NotNull; -import pro.cloudnode.smp.smpcore.exception.MemberNotFoundException; import java.sql.Connection; import java.sql.PreparedStatement; @@ -10,9 +9,11 @@ import java.util.Date; import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; +@SuppressWarnings("unused") public final class Token { public final @NotNull UUID token; public final @NotNull UUID memberUUID; @@ -26,7 +27,7 @@ public Token(final @NotNull UUID token, final @NotNull UUID memberUUID, final @N this.lastUsed = lastUsed; } - public Token(final @NotNull ResultSet rs) throws @NotNull SQLException { + public Token(final @NotNull ResultSet rs) throws SQLException { this( UUID.fromString(rs.getString("token")), UUID.fromString(rs.getString("member")), @@ -37,8 +38,7 @@ public Token(final @NotNull ResultSet rs) throws @NotNull SQLException { public void save() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("INSERT OR REPLACE INTO `tokens` (`token`, `member`, `created`, `last_used`) VALUES (?, ?, ?, ?)") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("INSERT OR REPLACE INTO `tokens` (`token`, `member`, `created`, `last_used`) VALUES (?, ?, ?, ?)") ) { stmt.setString(1, token.toString()); stmt.setString(2, memberUUID.toString()); @@ -53,8 +53,7 @@ public void save() { public void delete() { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("DELETE FROM `tokens` WHERE `token` = ?") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("DELETE FROM `tokens` WHERE `token` = ?") ) { stmt.setString(1, token.toString()); stmt.executeUpdate(); @@ -64,10 +63,9 @@ public void delete() { } } - public static @NotNull Optional<@NotNull Token> get(final @NotNull UUID token) throws @NotNull SQLException, @NotNull MemberNotFoundException { + public static @NotNull Optional<@NotNull Token> get(final @NotNull UUID token) throws SQLException { try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `tokens` WHERE `token` = ? LIMIT 1") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `tokens` WHERE `token` = ? LIMIT 1") ) { stmt.setString(1, token.toString()); final @NotNull ResultSet rs = stmt.executeQuery(); @@ -76,11 +74,10 @@ public void delete() { } } - public static @NotNull HashSet<@NotNull Token> get(final @NotNull Member member) { - final @NotNull HashSet<@NotNull Token> tokens = new HashSet<>(); + public static @NotNull Set<@NotNull Token> get(final @NotNull Member member) { + final @NotNull Set<@NotNull Token> tokens = new HashSet<>(); try ( - final @NotNull Connection conn = SMPCore.getInstance().db() - .getConnection(); final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT * FROM `tokens` WHERE `member` = ?") + final @NotNull PreparedStatement stmt = SMPCore.getInstance().conn.prepareStatement("SELECT * FROM `tokens` WHERE `member` = ?") ) { stmt.setString(1, member.uuid.toString()); final @NotNull ResultSet rs = stmt.executeQuery(); @@ -91,10 +88,4 @@ public void delete() { } return tokens; } - - public static @NotNull Token create(final @NotNull Member member) throws @NotNull SQLException { - final @NotNull Token token = new Token(UUID.randomUUID(), member.uuid, new Date(), new Date()); - token.save(); - return token; - } } diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java index d352ee7..b05e3fd 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/BanCommand.java @@ -114,13 +114,14 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul if (banned.isEmpty()) return sendMessage(sender, SMPCore.messages().bannedPlayer(target, duration)); if (banned.size() == 1) - return sendMessage(sender, SMPCore.messages().bannedMember(banned.get(0), duration)); + return sendMessage(sender, SMPCore.messages().bannedMember(banned.getFirst(), duration)); return sendMessage(sender, SMPCore.messages().bannedMemberChain( - banned.get(0), + banned.getFirst(), banned.subList(1, banned.size()), duration) ); } + @SuppressWarnings("NullableProblems") @Override public @NotNull List<@NotNull String> tab(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { if (args.length <= 1) return Arrays.stream(SMPCore.getInstance().getServer().getOfflinePlayers()).filter(p -> !p.isBanned()).map(OfflinePlayer::getName).filter(Objects::nonNull).toList(); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/Command.java b/src/main/java/pro/cloudnode/smp/smpcore/command/Command.java index 780a815..f91a273 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/Command.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/Command.java @@ -14,6 +14,7 @@ import java.util.List; public abstract class Command implements TabCompleter, CommandExecutor { + @SuppressWarnings("SameReturnValue") public static boolean sendMessage(final @NotNull Audience recipient, final @NotNull Component message) { recipient.sendMessage(message); return true; @@ -38,7 +39,7 @@ public final boolean onCommand(final @NotNull CommandSender sender, final @NotNu } /** - * Check for the presence of any of the permissions (using OR). + * Check for the presence of the permissions (using OR). * * @param permissible Permissible to check * @param permissions Permissions to check diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/MainCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/MainCommand.java index 079f078..5e2bb28 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/MainCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/MainCommand.java @@ -16,11 +16,11 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.regex.Pattern; public final class MainCommand extends Command { @@ -37,6 +37,7 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul }; } + @SuppressWarnings("NullableProblems") @Override public @Nullable List<@NotNull String> tab(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { final @NotNull ArrayList<@NotNull String> suggestions = new ArrayList<>(); @@ -135,7 +136,7 @@ else switch (originalArgs[0]) { } final @NotNull Member member = targetMember.get().altOwner().orElse(targetMember.get()); - final @NotNull HashSet<@NotNull Member> alts = member.getAlts(); + final @NotNull Set<@NotNull Member> alts = member.getAlts(); sendMessage(sender, SMPCore.messages().altsListHeader(member)); if (alts.isEmpty()) return sendMessage(sender, SMPCore.messages().altsListNone()); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/NationCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/NationCommand.java index db9de56..c19c817 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/NationCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/NationCommand.java @@ -74,9 +74,10 @@ public boolean run( return tabComplete(sender, label, args); } + @SuppressWarnings("NullableProblems") public static @Nullable List<@NotNull String> tabComplete( final @NotNull CommandSender sender, - final @NotNull String label, + final @NotNull String ignored, @NotNull String @NotNull [] args ) { final var list = new ArrayList<@NotNull String>(); @@ -157,7 +158,7 @@ else switch (args[0]) { break; if (!sender.hasPermission(Permission.NATION_CITIZENS_KICK)) break; - list.addAll((List<@NotNull String>) nation.get().citizens().stream() + list.addAll(nation.get().citizens().stream() .filter(c -> !c.uuid.equals(nation.get().leaderUUID)) .map(c -> c.player().getName()) .filter(Objects::nonNull).toList()); @@ -167,7 +168,7 @@ else switch (args[0]) { break; if (!sender.hasPermission(Permission.NATION_PROMOTE)) break; - list.addAll((List<@NotNull String>) nation.get().citizens().stream() + list.addAll(nation.get().citizens().stream() .filter(c -> !(c.uuid.equals(nation.get().leaderUUID) || c.uuid.equals(nation.get().viceLeaderUUID))) .map(c -> c.player().getName()) .filter(Objects::nonNull).toList()); @@ -189,7 +190,7 @@ else switch (args[0]) { break; if (!sender.hasPermission(Permission.NATION_INVITE)) break; - list.addAll((List<@NotNull String>) Member.get().stream() + list.addAll(Member.get().stream() .filter(m -> !nation.get().id.equals(m.nationID)) .map(c -> c.player().getName()) .filter(Objects::nonNull).toList()); @@ -199,7 +200,7 @@ else switch (args[0]) { break; if (!sender.hasPermission(Permission.NATION_INVITE)) break; - list.addAll((List<@NotNull String>) Stream.concat( + list.addAll(Stream.concat( CitizenRequest.get(nation.get(), true).stream(), CitizenRequest.get(nation.get(), false).stream() ).map(req -> req.member().player().getName()).filter(Objects::nonNull).sorted().toList()); @@ -209,7 +210,7 @@ else switch (args[0]) { break; if (!sender.hasPermission(Permission.NATION_CITIZEN_ADD)) break; - list.addAll((List<@NotNull String>) Member.get().stream() + list.addAll(Member.get().stream() .filter(m -> !nation.get().id.equals(m.nationID)) .map(c -> c.player().getName()) .filter(Objects::nonNull).toList()); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/SeenCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/SeenCommand.java index 5103f88..b7b0957 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/SeenCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/SeenCommand.java @@ -31,6 +31,7 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul .orElseGet(() -> sendMessage(sender, SMPCore.messages().seen(player))); } + @SuppressWarnings("NullableProblems") @Override public @NotNull List<@NotNull String> tab(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { if (sender.hasPermission(Permission.SEEN_STAFF)) return Member.getNames().stream().toList(); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/command/UnbanCommand.java b/src/main/java/pro/cloudnode/smp/smpcore/command/UnbanCommand.java index 49d11a5..9bbc375 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/command/UnbanCommand.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/command/UnbanCommand.java @@ -10,7 +10,6 @@ import pro.cloudnode.smp.smpcore.Permission; import pro.cloudnode.smp.smpcore.SMPCore; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -32,12 +31,13 @@ public boolean run(@NotNull CommandSender sender, @NotNull String label, @NotNul return sendMessage(sender, SMPCore.messages().unbannedPlayer(target)); } final @NotNull Member main = targetMember.get().altOwner().orElse(targetMember.get()); - final @NotNull HashSet<@NotNull Member> alts = main.getAlts(); + final @NotNull Set<@NotNull Member> alts = main.getAlts(); main.unban(); alts.forEach(Member::unban); return sendMessage(sender, SMPCore.messages().unbannedMember(main, alts.stream().toList())); } + @SuppressWarnings("NullableProblems") @Override public @NotNull List<@NotNull String> tab(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { if (args.length <= 1) { diff --git a/src/main/java/pro/cloudnode/smp/smpcore/exception/MemberNotFoundException.java b/src/main/java/pro/cloudnode/smp/smpcore/exception/MemberNotFoundException.java deleted file mode 100644 index c46d603..0000000 --- a/src/main/java/pro/cloudnode/smp/smpcore/exception/MemberNotFoundException.java +++ /dev/null @@ -1,12 +0,0 @@ -package pro.cloudnode.smp.smpcore.exception; - -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.NotNull; - -public final class MemberNotFoundException extends Exception { - public final @NotNull OfflinePlayer offlinePlayer; - public MemberNotFoundException(final @NotNull OfflinePlayer offlinePlayer) { - super("Member not found: " + offlinePlayer); - this.offlinePlayer = offlinePlayer; - } -} diff --git a/src/main/java/pro/cloudnode/smp/smpcore/exception/NationNotFoundException.java b/src/main/java/pro/cloudnode/smp/smpcore/exception/NationNotFoundException.java deleted file mode 100644 index 3488b76..0000000 --- a/src/main/java/pro/cloudnode/smp/smpcore/exception/NationNotFoundException.java +++ /dev/null @@ -1,18 +0,0 @@ -package pro.cloudnode.smp.smpcore.exception; - -import org.jetbrains.annotations.NotNull; - -public final class NationNotFoundException extends Exception { - /** - * @see pro.cloudnode.smp.smpcore.Nation#id - */ - public final @NotNull String nation; - - /** - * @param id See {@link pro.cloudnode.smp.smpcore.Nation#id} - */ - public NationNotFoundException(final @NotNull String id) { - super("Nation not found: " + id); - this.nation = id; - } -} diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/NationTeamUpdaterListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerJoinListener.java similarity index 87% rename from src/main/java/pro/cloudnode/smp/smpcore/listener/NationTeamUpdaterListener.java rename to src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerJoinListener.java index 889bc7e..bbadd86 100644 --- a/src/main/java/pro/cloudnode/smp/smpcore/listener/NationTeamUpdaterListener.java +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerJoinListener.java @@ -2,6 +2,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.scoreboard.Team; @@ -12,12 +13,9 @@ import java.util.Optional; -/** - * When a player connects to the server, ensures that they are in the right Nation's team - */ -public final class NationTeamUpdaterListener implements Listener { - @EventHandler - public void onPlayerJoin(final @NotNull PlayerJoinEvent event) { +public final class PlayerJoinListener implements Listener { + @EventHandler(priority = EventPriority.NORMAL) + public void putPlayerInNationTeam(final @NotNull PlayerJoinEvent event) { SMPCore.runAsync(() -> { final @NotNull Player player = event.getPlayer(); final @NotNull Optional<@NotNull Member> member = Member.get(player); diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerServerFullCheckListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerServerFullCheckListener.java new file mode 100644 index 0000000..06dba37 --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerServerFullCheckListener.java @@ -0,0 +1,23 @@ +package pro.cloudnode.smp.smpcore.listener; + +import com.destroystokyo.paper.profile.PlayerProfile; +import io.papermc.paper.event.player.PlayerServerFullCheckEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; +import pro.cloudnode.smp.smpcore.Member; + +import java.util.Objects; +import java.util.Optional; + +public final class PlayerServerFullCheckListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST) + public void allowMemberJoinWhenServerFull(final @NotNull PlayerServerFullCheckEvent event) { + if (event.isAllowed()) return; + final PlayerProfile profile = event.getPlayerProfile(); + final @NotNull Optional<@NotNull Member> member = Member.get(Objects.requireNonNull(profile.getId())); + if (member.isEmpty()) return; + event.allow(true); + } +} diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerSlotsListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerSlotsListener.java deleted file mode 100644 index 01ca71a..0000000 --- a/src/main/java/pro/cloudnode/smp/smpcore/listener/PlayerSlotsListener.java +++ /dev/null @@ -1,31 +0,0 @@ -package pro.cloudnode.smp.smpcore.listener; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.server.ServerListPingEvent; -import org.jetbrains.annotations.NotNull; -import pro.cloudnode.smp.smpcore.Member; - -import java.util.Optional; - -public final class PlayerSlotsListener implements Listener { - /** - * Change the max players number in server list ping - */ - @EventHandler - public void onServerListPing(final @NotNull ServerListPingEvent event) { - event.setMaxPlayers(Member.count()); - } - - /** - * If the player is a member, but the server thinks it's full, allow them to join - */ - @EventHandler - public void onPlayerLogin(final @NotNull PlayerLoginEvent event) { - if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL) { - final @NotNull Optional<@NotNull Member> member = Member.get(event.getPlayer()); - if (member.isPresent()) event.allow(); - } - } -} diff --git a/src/main/java/pro/cloudnode/smp/smpcore/listener/ServerListPingListener.java b/src/main/java/pro/cloudnode/smp/smpcore/listener/ServerListPingListener.java new file mode 100644 index 0000000..abe20cb --- /dev/null +++ b/src/main/java/pro/cloudnode/smp/smpcore/listener/ServerListPingListener.java @@ -0,0 +1,15 @@ +package pro.cloudnode.smp.smpcore.listener; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.server.ServerListPingEvent; +import org.jetbrains.annotations.NotNull; +import pro.cloudnode.smp.smpcore.Member; + +public final class ServerListPingListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST) + public void changeMaxPlayers(final @NotNull ServerListPingEvent event) { + event.setMaxPlayers(Member.count()); + } +} diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index ab67ef8..3d4a72c 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -112,7 +112,6 @@ error: command-on-staff: (!) You cannot use / on staff. not-citizen-you: (!) You are not a citizen of any nation. not-citizen: (!) Member is not a citizen of the nation. - not-player: (!) You must be a player to use this command. kick-leadership: (!) You cannot kick a member of the nation's leadership. leader-leave: (!) You cannot leave your nation because you are the leader! nation-not-found: (!) Nation not found.