diff --git a/README.md b/README.md index d42cd83..cea86fc 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ implementation("com.cjburkey.claimchunk:claimchunk:0.0.25-FIX3") Building -------- [![Automatic Build](https://img.shields.io/github/actions/workflow/status/cjburkey01/ClaimChunk/gradle.yml?branch=main&style=for-the-badge)](https://claimchunk.cjburkey.com/server/Downloads.html#snapshot-downloads) -[![Version Info](https://img.shields.io/static/v1?label=Repository%20Version&message=0.0.25-FIX4&color=ff5555&style=for-the-badge)](https://github.com/cjburkey01/ClaimChunk/archive/main.zip) +[![Version Info](https://img.shields.io/static/v1?label=Repository%20Version&message=0.0.26&color=ff5555&style=for-the-badge)](https://github.com/cjburkey01/ClaimChunk/archive/main.zip) If you want to obtain a version of the plugin that isn't available yet (like a snapshot), you can do so by asking on the Discord or building it yourself. Here's how to build it yourself: diff --git a/build.gradle.kts b/build.gradle.kts index 65c55aa..b401282 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ object DepData { const val JAVA_VERSION = 21 const val LIVE_VERSION = "0.0.25-FIX3" - const val THIS_VERSION = "0.0.25-FIX4" + const val THIS_VERSION = "0.0.26" const val PLUGIN_NAME = "ClaimChunk" const val ARCHIVES_BASE_NAME = "claimchunk" const val MAIN_CLASS = "com.cjburkey.claimchunk.ClaimChunk" diff --git a/changelogs/0.0.25-FIX2.md b/changelogs/0.0.25-FIX2.md index 08c9a56..2737b94 100644 --- a/changelogs/0.0.25-FIX2.md +++ b/changelogs/0.0.25-FIX2.md @@ -1,4 +1,4 @@ -# ClaimChunk 0.0.25-FIX1 +# ClaimChunk 0.0.25-FIX2 Fixes: * Re-add the `claimchunk_am_trusted` placeholder diff --git a/changelogs/0.0.25-FIX3.md b/changelogs/0.0.25-FIX3.md index c4010f2..3fcce3a 100644 --- a/changelogs/0.0.25-FIX3.md +++ b/changelogs/0.0.25-FIX3.md @@ -1,4 +1,4 @@ -# ClaimChunk 0.0.25-FIX1 +# ClaimChunk 0.0.25-FIX3 Fixes: * My stupid update checker diff --git a/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java b/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java index 796940c..24becc4 100644 --- a/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java +++ b/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java @@ -9,7 +9,7 @@ public final class CCFlags { // Generics...gotta love 'em, but feel free to hate them too. // Methods named such that they may align with record getters :} - public interface IFlagData> { + public interface IFlagData> { @NotNull TypeEnum flagType(); diff --git a/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java b/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java index 2cc133d..1e2a53f 100644 --- a/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java +++ b/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java @@ -69,6 +69,14 @@ public void loadFromConfig(@NotNull YamlConfiguration config) { // Read each flag name for (String flagName : flagSection.getKeys(false)) { + if (!flagName.matches("[a-zA-Z0-9_-]+")) { + Utils.err( + "Flag name \"%s\" isn't alphanumeric! Must be a string of A-Z, a-z, 0-9," + + " '_', or '-'", + flagName); + continue; + } + // Get the list of maps (see src/resources/defaultFlags.yml for format) List> flagEntries = flagSection.getMapList(flagName); if (flagEntries.isEmpty()) { @@ -233,7 +241,4 @@ public void loadFromConfig(@NotNull YamlConfiguration config) { } return null; } - - // -- CLASSES -- // - } diff --git a/src/main/java/com/cjburkey/claimchunk/data/newdata/IClaimChunkDataHandler.java b/src/main/java/com/cjburkey/claimchunk/data/newdata/IClaimChunkDataHandler.java index 015a0b0..ee6f25d 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/newdata/IClaimChunkDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/newdata/IClaimChunkDataHandler.java @@ -338,6 +338,89 @@ default void addPlayer(UUID player, String lastIgn, boolean alerts, int defaultM // -- ACCESS -- // + /** + * Enable the given permission flag(s) by default in the provided player's chunks. + * + * @param owner Owner of the chunks granting access. + * @param flagNames The name(s) of the flag(s) to grant. + * @since 0.0.26 + */ + void grantPermissionFlagsGlobalDefault(UUID owner, String... flagNames); + + /** + * Disable the given permission flag(s) by default in the provided player's chunks. + * + * @param owner Owner of the chunks revoking access. + * @param flagNames The name(s) of the flag(s) to revoke. + * @since 0.0.26 + */ + void revokePermissionFlagsGlobalDefault(UUID owner, String... flagNames); + + /** + * Enable the given permission flag(s) by default in the provided chunk. + * + * @param owner Owner of the chunks granting access. + * @param chunk Position of the chunk to grant access in. + * @param flagNames The name(s) of the flag(s) to grant. + * @since 0.0.26 + */ + void grantPermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames); + + /** + * Disable the given permission flag(s) by default in the provided chunk. + * + * @param owner Owner of the chunks revoking access. + * @param chunk Position of the chunk to revoke access from. + * @param flagNames The name(s) of the flag(s) to revoke. + * @since 0.0.26 + */ + void revokePermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames); + + /** + * Enable the given permission flag(s) by default for the provided player in the owner's chunks. + * + * @param owner Owner of the chunks granting access. + * @param accessor Other player having access granted to them. + * @param flagNames The name(s) of the flag(s) to grant. + * @since 0.0.26 + */ + void grantPermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames); + + /** + * Disable the given permission flag(s) by default for the provided player in the owner's + * chunks. + * + * @param owner Owner of the chunks granting access. + * @param accessor Other player having access revoked from them. + * @param flagNames The name(s) of the flag(s) to revoke. + * @since 0.0.26 + */ + void revokePermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames); + + /** + * Enable the given permission flag(s) for the provided player in a specific chunk. + * + * @param owner Owner of the chunks granting access. + * @param accessor Other player having access granted to them. + * @param chunk The chunk to grant access to. + * @param flagNames The name(s) of the flag(s) to grant. + * @since 0.0.26 + */ + void grantPermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames); + + /** + * Disable the given permission flag(s) for the provided player in a specific chunk. + * + * @param owner Owner of the chunks revoking access. + * @param accessor Other player having access revoked from them. + * @param chunk The chunk to take access for. + * @param flagNames The name(s) of the flag(s) to revoke. + * @since 0.0.26 + */ + void revokePermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames); + /** * Gives the provided accessor access (with specific permissions) to the given chunk * @@ -346,6 +429,7 @@ default void addPlayer(UUID player, String lastIgn, boolean alerts, int defaultM * @param permissions The permissions to be granted to the accessor * @since 0.0.24 */ + @Deprecated void givePlayerAccess(ChunkPos chunk, UUID accessor, ChunkPlayerPermissions permissions); /** @@ -355,6 +439,7 @@ default void addPlayer(UUID player, String lastIgn, boolean alerts, int defaultM * @param accessor The UUIDs of the player whose access to the chunk should be revoked * @since 0.0.24 */ + @Deprecated void takePlayerAccess(ChunkPos chunk, UUID accessor); /** @@ -365,5 +450,6 @@ default void addPlayer(UUID player, String lastIgn, boolean alerts, int defaultM * @return A map of UUIDs and permissions of all players who can edit this chunk * @since 0.0.24 */ + @Deprecated Map getPlayersWithAccess(ChunkPos chunk); } diff --git a/src/main/java/com/cjburkey/claimchunk/data/newdata/JsonDataHandler.java b/src/main/java/com/cjburkey/claimchunk/data/newdata/JsonDataHandler.java index f6d723f..c59895b 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/newdata/JsonDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/newdata/JsonDataHandler.java @@ -163,15 +163,13 @@ public void addPlayers(FullPlayerData[] players) { } @Override - @Nullable - public String getPlayerUsername(UUID player) { + public @Nullable String getPlayerUsername(UUID player) { FullPlayerData ply = joinedPlayers.get(player); return ply == null ? null : ply.lastIgn; } @Override - @Nullable - public UUID getPlayerUUID(String username) { + public @Nullable UUID getPlayerUUID(String username) { for (FullPlayerData player : joinedPlayers.values()) { if (player.lastIgn.equals(username)) return player.player; } @@ -191,8 +189,7 @@ public void setPlayerChunkName(UUID player, String name) { } @Override - @Nullable - public String getPlayerChunkName(UUID player) { + public @Nullable String getPlayerChunkName(UUID player) { FullPlayerData ply = joinedPlayers.get(player); if (ply != null) return ply.chunkName; return null; @@ -277,6 +274,42 @@ public FullPlayerData[] getFullPlayerData() { return joinedPlayers.values().toArray(new FullPlayerData[0]); } + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsGlobalDefault(UUID owner, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsGlobalDefault(UUID owner, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsChunkDefault( + UUID owner, ChunkPos chunk, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsPlayerDefault( + UUID owner, UUID accessor, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) {} + private Gson getGson() { GsonBuilder builder = new GsonBuilder(); return builder.serializeNulls().create(); diff --git a/src/main/java/com/cjburkey/claimchunk/data/newdata/MySQLDataHandler.java b/src/main/java/com/cjburkey/claimchunk/data/newdata/MySQLDataHandler.java index 797e125..133461f 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/newdata/MySQLDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/newdata/MySQLDataHandler.java @@ -704,6 +704,42 @@ public FullPlayerData[] getFullPlayerData() { return players.toArray(new FullPlayerData[0]); } + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsGlobalDefault(UUID owner, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsGlobalDefault(UUID owner, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsChunkDefault( + UUID owner, ChunkPos chunk, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsPlayerDefault( + UUID owner, UUID accessor, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void grantPermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) {} + + // Only newer data handlers use this! + @Override + public void revokePermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) {} + @Override public void givePlayerAccess( ChunkPos chunk, UUID accessor, ChunkPlayerPermissions permissions) { diff --git a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteDataHandler.java b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteDataHandler.java index 1459adf..35b6f87 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteDataHandler.java @@ -74,7 +74,7 @@ public void load() throws Exception { for (FullPlayerData player : sqLiteWrapper.getAllPlayers()) { joinedPlayers.putIfAbsent(player.player, player); } - for (DataChunk chunk : sqLiteWrapper.getAllChunks()) { + for (DataChunk chunk : SqLiteWrapper.getAllChunksLegacy()) { claimedChunks.putIfAbsent(chunk.chunk, chunk); } } @@ -229,6 +229,49 @@ public FullPlayerData[] getFullPlayerData() { } @Override + public void grantPermissionFlagsGlobalDefault(UUID owner, String... flagNames) { + sqLiteWrapper.grantPermissionFlagsGlobalDefault(owner, flagNames); + } + + @Override + public void revokePermissionFlagsGlobalDefault(UUID owner, String... flagNames) { + sqLiteWrapper.revokePermissionFlagsGlobalDefault(owner, flagNames); + } + + @Override + public void grantPermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames) { + sqLiteWrapper.grantPermissionFlagsChunkDefault(owner, chunk, flagNames); + } + + @Override + public void revokePermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames) { + sqLiteWrapper.revokePermissionFlagsChunkDefault(owner, chunk, flagNames); + } + + @Override + public void grantPermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames) { + sqLiteWrapper.grantPermissionFlagsPlayerDefault(owner, accessor, flagNames); + } + + @Override + public void revokePermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames) { + sqLiteWrapper.revokePermissionFlagsPlayerDefault(owner, accessor, flagNames); + } + + @Override + public void grantPermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) { + sqLiteWrapper.grantPermissionFlagsPlayerChunk(owner, accessor, chunk, flagNames); + } + + @Override + public void revokePermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) { + sqLiteWrapper.revokePermissionFlagsPlayerChunk(owner, accessor, chunk, flagNames); + } + + @Override + @Deprecated public void givePlayerAccess( ChunkPos chunk, UUID accessor, ChunkPlayerPermissions permissions) { DataChunk chunkData = claimedChunks.get(chunk); @@ -239,6 +282,7 @@ public void givePlayerAccess( } @Override + @Deprecated public void takePlayerAccess(ChunkPos chunk, UUID accessor) { DataChunk chunkData = claimedChunks.get(chunk); if (chunkData != null) chunkData.playerPermissions.remove(accessor); diff --git a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteTableMigrationManager.java b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteTableMigrationManager.java index 50b7e89..6b17568 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteTableMigrationManager.java +++ b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteTableMigrationManager.java @@ -12,8 +12,6 @@ public class SqLiteTableMigrationManager { public static void go() { // Make tables if they don't exist tryCreateTables(); - - // Call migration check methods here. } private static void tryCreateTables() { @@ -44,6 +42,7 @@ FOREIGN KEY(owner_uuid) REFERENCES player_data(player_uuid) ) STRICT """); + // TODO: MIGRATE? // Granular chunk player permission table Q2Sql.executeUpdate( """ @@ -57,10 +56,90 @@ FOREIGN KEY(chunk_id) REFERENCES chunk_data(chunk_id), FOREIGN KEY(other_player_uuid) REFERENCES player_data(player_uuid) ) STRICT """); + + // Create table for flags that players have enabled by default in their claims. + Q2Sql.executeUpdate( + """ + CREATE TABLE IF NOT EXISTS flags_player_default_enabled ( + player_uuid TEXT NOT NULL, + flag_name TEXT NOT NULL, + + PRIMARY KEY(player_uuid, flag_name) + + FOREIGN KEY(player_uuid) REFERENCES player_data(player_uuid) + ) STRICT + """); + + // Create table for flags that players have enabled for specific players across their + // chunks by default. + Q2Sql.executeUpdate( + """ + CREATE TABLE IF NOT EXISTS flags_player_other_player_enabled ( + player_uuid TEXT NOT NULL, + other_player_uuid TEXT NOT NULL, + flag_name TEXT NOT NULL, + + PRIMARY KEY(player_uuid, other_player_uuid, flag_name) + + FOREIGN KEY(player_uuid) REFERENCES player_data(player_uuid), + FOREIGN KEY(other_player_uuid) REFERENCES player_data(player_uuid) + ) STRICT + """); + + // Create table for flags that owners have enabled for specific chunks + Q2Sql.executeUpdate( + """ + CREATE TABLE IF NOT EXISTS flags_player_chunk_enabled ( + player_uuid TEXT NOT NULL, + chunk_id INTEGER NOT NULL, + flag_name TEXT NOT NULL, + + PRIMARY KEY(player_uuid, chunk_id, flag_name) + + FOREIGN KEY(player_uuid) REFERENCES player_data(player_uuid), + FOREIGN KEY(chunk_id) REFERENCES chunk_data(chunk_id) + ) STRICT + """); + + // Create table for flags that players have enabled for specific players in specific + // chunks + Q2Sql.executeUpdate( + """ + CREATE TABLE IF NOT EXISTS flags_player_chunk_player_enabled ( + player_uuid TEXT NOT NULL, + other_player_uuid TEXT NOT NULL, + chunk_id INTEGER NOT NULL, + flag_name TEXT NOT NULL, + + PRIMARY KEY(player_uuid, other_player_uuid, chunk_id, flag_name) + + FOREIGN KEY(player_uuid) REFERENCES player_data(player_uuid), + FOREIGN KEY(other_player_uuid) REFERENCES player_data(player_uuid), + FOREIGN KEY(chunk_id) REFERENCES chunk_data(chunk_id) + ) STRICT + """); } - // Use this method to determine if a column exists in a table to perform migrations @SuppressWarnings("unused") + public static boolean tableExists(String tableName) { + return SqlClosure.sqlExecute( + connection -> { + try (PreparedStatement statement = + connection.prepareStatement( + """ + SELECT COUNT(*) FROM sqlite_master + WHERE type='table' + AND name=? + """)) { + statement.setString(1, tableName); + ResultSet resultSet = statement.executeQuery(); + int count = resultSet.next() ? resultSet.getInt(1) : 0; + return count > 0; + } + }); + } + + // Use this method to determine if a column exists in a table to perform migrations public static boolean columnExists(String tableName, String columnName) { return SqlClosure.sqlExecute( connection -> { diff --git a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteWrapper.java b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteWrapper.java index 4b0283d..9d44da0 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteWrapper.java +++ b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteWrapper.java @@ -273,6 +273,7 @@ public void setPlayerExtraMaxClaims(UUID player, int extraMaxClaims) { }); } + @Deprecated public void setPlayerAccess(ChunkPos chunk, UUID accessor, int permissionFlags) { SqlClosure.sqlExecute( connection -> { @@ -299,6 +300,7 @@ ON CONFLICT(chunk_id, other_player_uuid) DO }); } + @Deprecated public void removePlayerAccess(ChunkPos chunk, UUID accessor) { SqlClosure.sqlExecute( connection -> { @@ -318,6 +320,255 @@ public void removePlayerAccess(ChunkPos chunk, UUID accessor) { }); } + public void grantPermissionFlagsGlobalDefault(UUID owner, String... flagNames) { + SqlClosure.sqlExecute( + connection -> { + String values = + Arrays.stream(flagNames) + .map(ignored -> "(?, ?)") + .collect(Collectors.joining(", ")); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE INTO flags_player_default_enabled ( + player_uuid, + flag_name + ) VALUES + """ + + values)) { + int param = 1; + for (String flagName : flagNames) { + statement.setString(param++, owner.toString()); + statement.setString(param++, flagName); + } + statement.execute(); + return null; + } + }); + } + + public void revokePermissionFlagsGlobalDefault(UUID owner, String... flagNames) { + String clauses = + Arrays.stream(flagNames) + .map(ignored -> "flag_name=?") + .collect(Collectors.joining(" OR ")); + + SqlClosure.sqlExecute( + connection -> { + try (PreparedStatement statement = + connection.prepareStatement( + """ + DELETE FROM flags_player_default_enabled + WHERE player_uuid=? AND ( + """ + + clauses + + ")")) { + int param = 1; + statement.setString(param++, owner.toString()); + for (String flagName : flagNames) { + statement.setString(param++, flagName); + } + statement.execute(); + return null; + } + }); + } + + public void grantPermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames) { + SqlClosure.sqlExecute( + connection -> { + String values = + Arrays.stream(flagNames) + .map(ignored -> chunkIdQuery("(?, %%SELECT_CHUNK_ID_SQL%%, ?)")) + .collect(Collectors.joining(", ")); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE INTO flags_player_chunk_enabled ( + player_uuid, + chunk_id, + flag_name + ) VALUES + """ + + values)) { + int param = 1; + for (String flagName : flagNames) { + statement.setString(param++, owner.toString()); + param = setChunkPosParams(statement, param, chunk); + statement.setString(param++, flagName); + } + + statement.execute(); + return null; + } + }); + } + + public void revokePermissionFlagsChunkDefault(UUID owner, ChunkPos chunk, String... flagNames) { + String clauses = + Arrays.stream(flagNames) + .map(ignored -> "flag_name=?") + .collect(Collectors.joining(" OR ")); + + SqlClosure.sqlExecute( + connection -> { + try (PreparedStatement statement = + connection.prepareStatement( + chunkIdQuery( + """ + DELETE FROM flags_player_chunk_enabled + WHERE player_uuid=? + AND chunk_id=%%SELECT_CHUNK_ID_SQL%% + AND ( + """ + + clauses + + ")"))) { + int param = 1; + statement.setString(param++, owner.toString()); + param = setChunkPosParams(statement, param, chunk); + for (String flagName : flagNames) { + statement.setString(param++, flagName); + } + statement.execute(); + return null; + } + }); + } + + public void grantPermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames) { + SqlClosure.sqlExecute( + connection -> { + String values = + Arrays.stream(flagNames) + .map(ignored -> "(?, ?, ?)") + .collect(Collectors.joining(", ")); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE INTO flags_player_other_player_enabled ( + player_uuid, + other_player_uuid, + flag_name + ) VALUES + """ + + values)) { + int param = 1; + for (String flagName : flagNames) { + statement.setString(param++, owner.toString()); + statement.setString(param++, accessor.toString()); + statement.setString(param++, flagName); + } + statement.execute(); + return null; + } + }); + } + + public void revokePermissionFlagsPlayerDefault(UUID owner, UUID accessor, String... flagNames) { + String clauses = + Arrays.stream(flagNames) + .map(ignored -> "flag_name=?") + .collect(Collectors.joining(" OR ")); + + SqlClosure.sqlExecute( + connection -> { + try (PreparedStatement statement = + connection.prepareStatement( + chunkIdQuery( + """ + DELETE FROM flags_player_other_player_enabled + WHERE player_uuid=? + AND other_player_uuid=? + AND ( + """ + + clauses + + ")"))) { + int param = 1; + statement.setString(param++, owner.toString()); + statement.setString(param++, accessor.toString()); + for (String flagName : flagNames) { + statement.setString(param++, flagName); + } + statement.execute(); + return null; + } + }); + } + + public void grantPermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) { + SqlClosure.sqlExecute( + connection -> { + String values = + Arrays.stream(flagNames) + .map( + ignored -> + chunkIdQuery( + "(?, ?, %%SELECT_CHUNK_ID_SQL%%, ?)")) + .collect(Collectors.joining(", ")); + + try (PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE INTO flags_player_chunk_player_enabled ( + player_uuid, + other_player_uuid, + chunk_id, + flag_name + ) VALUES + """ + + values)) { + int param = 1; + for (String flagName : flagNames) { + statement.setString(param++, owner.toString()); + statement.setString(param++, accessor.toString()); + param = setChunkPosParams(statement, param, chunk); + statement.setString(param++, flagName); + } + + statement.execute(); + return null; + } + }); + } + + public void revokePermissionFlagsPlayerChunk( + UUID owner, UUID accessor, ChunkPos chunk, String... flagNames) { + String clauses = + Arrays.stream(flagNames) + .map(ignored -> "flag_name=?") + .collect(Collectors.joining(" OR ")); + + SqlClosure.sqlExecute( + connection -> { + try (PreparedStatement statement = + connection.prepareStatement( + chunkIdQuery( + """ + DELETE FROM flags_player_chunk_player_enabled + WHERE player_uuid=? + AND other_player_uuid=? + AND chunk_id=%%SELECT_CHUNK_ID_SQL%% + AND ( + """ + + clauses + + ")"))) { + int param = 1; + statement.setString(param++, owner.toString()); + statement.setString(param++, accessor.toString()); + param = setChunkPosParams(statement, param, chunk); + for (String flagName : flagNames) { + statement.setString(param++, flagName); + } + statement.execute(); + return null; + } + }); + } + // -- Loading stuff -- // public List getAllPlayers() { @@ -326,7 +577,11 @@ public List getAllPlayers() { .toList(); } - public Collection getAllChunks() { + /** + * @deprecated TODO: Use new method + */ + @Deprecated + public static Collection getAllChunksLegacy() { HashMap> permissions = new HashMap<>(); HashMap owners = new HashMap<>(); diff --git a/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java b/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java index 6162204..c88d67c 100644 --- a/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java +++ b/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java @@ -27,7 +27,8 @@ void ensureColumnExistsMethodWorks() { // Make sure that instantiating SqLiteWrapper created the tables assert SqLiteTableMigrationManager.columnExists("player_data", "player_uuid"); assert SqLiteTableMigrationManager.columnExists("chunk_data", "owner_uuid"); - assert SqLiteTableMigrationManager.columnExists("chunk_permissions", "permission_bits"); + assert SqLiteTableMigrationManager.tableExists("flags_player_chunk_player_enabled"); + assert !SqLiteTableMigrationManager.tableExists("bob_the_builder_no_we_cant"); assert !SqLiteTableMigrationManager.columnExists("chunk_hell", "permission_bits"); assert !SqLiteTableMigrationManager.columnExists("player_data", "fake_col"); } @@ -72,7 +73,8 @@ void ensureNoDataLoss() { assert players.stream().anyMatch(ply -> "queenshit".equals(ply.chunkName)); // Load the chunk after adding it - Collection loadedChunks = wrapper.sql.getAllChunks(); + //noinspection deprecation + Collection loadedChunks = SqLiteWrapper.getAllChunksLegacy(); DataChunk loadedChunk = loadedChunks.iterator().next(); assertNotNull(loadedChunk); @@ -110,8 +112,9 @@ void multiplePermissions() { wrapper.sql.addClaimedChunk(chunkData); // Load the chunk and make sure it contains both accessors + //noinspection deprecation Map loadedPerms = - wrapper.sql.getAllChunks().iterator().next().playerPermissions; + SqLiteWrapper.getAllChunksLegacy().iterator().next().playerPermissions; assert loadedPerms.containsKey(accessor1); assert loadedPerms.containsKey(accessor2); } @@ -137,10 +140,10 @@ void insertOrUpdatePermission() { // Insert the permission and check it wrapper.sql.setPlayerAccess(chunk, accessor, flags1); + //noinspection deprecation assertEquals( flags1, - wrapper.sql - .getAllChunks() + SqLiteWrapper.getAllChunksLegacy() .iterator() .next() .playerPermissions @@ -149,10 +152,10 @@ void insertOrUpdatePermission() { // Update the permission and check it wrapper.sql.setPlayerAccess(chunk, accessor, flags2); + //noinspection deprecation assertEquals( flags2, - wrapper.sql - .getAllChunks() + SqLiteWrapper.getAllChunksLegacy() .iterator() .next() .playerPermissions @@ -161,7 +164,8 @@ void insertOrUpdatePermission() { // Remove the permission and make sure there aren't any permissions now wrapper.sql.removePlayerAccess(chunk, accessor); - assert wrapper.sql.getAllChunks().iterator().next().playerPermissions.isEmpty(); + //noinspection deprecation + assert SqLiteWrapper.getAllChunksLegacy().iterator().next().playerPermissions.isEmpty(); } }