diff --git a/src/main/java/com/cjburkey/claimchunk/chunk/ChunkPlayerPermissions.java b/src/main/java/com/cjburkey/claimchunk/chunk/ChunkPlayerPermissions.java index a8b7ee8..bb17ccc 100644 --- a/src/main/java/com/cjburkey/claimchunk/chunk/ChunkPlayerPermissions.java +++ b/src/main/java/com/cjburkey/claimchunk/chunk/ChunkPlayerPermissions.java @@ -18,6 +18,7 @@ public static final class Masks { public static int INTERACT_BLOCK = 1 << 6; public static int CONTAINERS = 1 << 7; public static int PVP = 1 << 8; + public static int ATTACK_ENTITY = 1 << 9; } /** @@ -116,6 +117,14 @@ public void allowAttackPlayer(final boolean allow) { setAllow(Masks.PVP, allow); } + public boolean canAttackEntities() { + return checkMask(Masks.ATTACK_ENTITY); + } + + public void allowAttackEntities(final boolean allow) { + setAllow(Masks.ATTACK_ENTITY, allow); + } + public Map toPermissionsMap() { HashMap permissionsMap = new HashMap<>(); @@ -128,6 +137,7 @@ public Map toPermissionsMap() { permissionsMap.put("interactBlocks", this.canInteractBlocks()); permissionsMap.put("useContainers", this.canUseContainers()); permissionsMap.put("pvp", this.canAttackPlayer()); + permissionsMap.put("attackEntities", this.canAttackEntities()); return permissionsMap; } @@ -148,6 +158,7 @@ public Map toPermissionsMap() { case "interactBlocks" -> chunkPlayerPermissions.allowInteractBlocks(permVal); case "useContainers" -> chunkPlayerPermissions.allowUseContainers(permVal); case "pvp" -> chunkPlayerPermissions.allowAttackPlayer(permVal); + case "attackEntities" -> chunkPlayerPermissions.allowAttackEntities(permVal); } } 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 abdbe3b..6e8dceb 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/newdata/JsonDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/newdata/JsonDataHandler.java @@ -154,7 +154,13 @@ public void addPlayer( joinedPlayers.put( player, new FullPlayerData( - player, lastIgn, chunkName, lastOnlineTime, alerts, extraMaxClaims, new ChunkPlayerPermissions(0))); + player, + lastIgn, + chunkName, + lastOnlineTime, + alerts, + extraMaxClaims, + new ChunkPlayerPermissions(0))); } @Override @@ -410,7 +416,8 @@ private void loadPre0024Data() throws Exception { player.chunkName, player.lastOnlineTime, player.alert, - 0, new ChunkPlayerPermissions())); + 0, + new ChunkPlayerPermissions())); // Grant default permissions on all this player's chunks to all players in // "permitted" for (DataChunk chunk : 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 6fbc626..df33d81 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/newdata/MySQLDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/newdata/MySQLDataHandler.java @@ -694,7 +694,8 @@ public FullPlayerData[] getFullPlayerData() { result.getString(3), result.getLong(4), result.getBoolean(5), - result.getInt(6), new ChunkPlayerPermissions(0))); + result.getInt(6), + new ChunkPlayerPermissions(0))); } } catch (Exception e) { Utils.err("Failed to retrieve all players data: %s", e.getMessage()); 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 5220244..a9a0409 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteDataHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteDataHandler.java @@ -129,7 +129,13 @@ public void addPlayer( int extraMaxClaims) { addPlayer( new FullPlayerData( - player, lastIgn, chunkName, lastOnlineTime, alerts, extraMaxClaims, new ChunkPlayerPermissions(0))); + player, + lastIgn, + chunkName, + lastOnlineTime, + alerts, + extraMaxClaims, + new ChunkPlayerPermissions(0))); } @Override 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 06c85d2..7ed37b6 100644 --- a/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteTableMigrationManager.java +++ b/src/main/java/com/cjburkey/claimchunk/data/sqlite/SqLiteTableMigrationManager.java @@ -15,8 +15,8 @@ public static void go() { // Call migration check methods here. // Migration method naming scheme: - // migrate_{{MAJOR}}_{{MINOR}}_{{PATCH}}_{{DISCRIMINATOR}} - migrate_0_0_25_1(); + // migrate_{{MAJOR}}_{{MINOR}}_{{PATCH}} + migrate_0_0_25(); } private static void tryCreateTables() { @@ -63,9 +63,17 @@ FOREIGN KEY(other_player_uuid) REFERENCES player_data(player_uuid) """); } - private static void migrate_0_0_25_1() { + // Whenever a column is added or moved or transformed or whatever, add a + // method here to perform that transformation and call it in initialize_tables. + // I've heard it is really difficult to perform column modification operations, so our best bet + // in that scenario would be to create a temporary table, copy the data to it, delete and + // recreate the table, then copy the data back whilst manually transforming the row data for the + // changed column(s) + + private static void migrate_0_0_25() { if (!columnExists("player_data", "default_chunk_permissions")) { - Q2Sql.executeUpdate(""" + Q2Sql.executeUpdate( + """ ALTER TABLE player_data ADD default_chunk_permissions INTEGER NOT NULL DEFAULT 0 """); @@ -90,8 +98,4 @@ SELECT COUNT(*) FROM pragma_table_info(?) WHERE name=? } }); } - - // Whenever a column is added or moved or transformed or whatever, add a - // method here to perform that transformation and call it in initialize_tables. - } diff --git a/src/main/java/com/cjburkey/claimchunk/event/WorldProfileEventHandler.java b/src/main/java/com/cjburkey/claimchunk/event/WorldProfileEventHandler.java index 95f11ee..4bdad2b 100644 --- a/src/main/java/com/cjburkey/claimchunk/event/WorldProfileEventHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/event/WorldProfileEventHandler.java @@ -573,6 +573,12 @@ private void onEntityEvent( @NotNull Player player, @NotNull Entity entity, @NotNull EntityAccess.EntityAccessType accessType) { + boolean isPlayerRecipient = entity instanceof Player; + + // I don't think interacting with a player really matters + if (isPlayerRecipient && accessType == EntityAccess.EntityAccessType.INTERACT) { + return; + } // Get the profile for this world ClaimChunkWorldProfile profile = @@ -592,7 +598,11 @@ private void onEntityEvent( final String permissionNeeded = entityClass != null && entityClass.equalsIgnoreCase("VEHICLES") ? "interactVehicles" - : (entity instanceof Player ? "pvp" : "interactEntities"); + : (isPlayerRecipient + ? "pvp" + : (accessType == EntityAccess.EntityAccessType.DAMAGE + ? "attackEntities" + : "interactEntities")); final boolean isOwner = (chunkOwner != null && chunkOwner.equals(ply)); final boolean isOwnerOrAccess = @@ -667,8 +677,12 @@ && shouldProtectOwnerChunks( cancel.run(); // Send cancellation message - final String ownerName = + String ownerName = claimChunk.getPlayerHandler().getChunkName(neighborOwner); + ownerName = + ownerName == null + ? claimChunk.getMessages().unknownChunkOwner + : ownerName; Utils.toPlayer( player, // TODO: FIX THIS METHOD diff --git a/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java b/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java index cecafe5..d7a3c6f 100644 --- a/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java +++ b/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java @@ -251,6 +251,7 @@ public final class V2JsonMessages { public String argRedstone = "redstone"; public String argInteractVehicles = "interactVehicles"; public String argInteractEntities = "interactEntities"; + public String argAttackEntities = "attackEntities"; public String argInteractBlocks = "interactBlocks"; public String argUseContainers = "useContainers"; public String argPvp = "pvp"; @@ -263,6 +264,7 @@ public final class V2JsonMessages { argRedstone, argInteractVehicles, argInteractEntities, + argAttackEntities, argInteractBlocks, argUseContainers, argPvp, @@ -272,7 +274,7 @@ public final class V2JsonMessages { // Argument types public String argTypeBoolTrue = "true"; public String argTypeBoolFalse = "false"; - public String argTypePlayer = "Player"; + // public String argTypePlayer = "Player"; // PlaceholderAPI public String placeholderApiUnclaimedChunkOwner = "nobody"; diff --git a/src/main/java/com/cjburkey/claimchunk/player/FullPlayerData.java b/src/main/java/com/cjburkey/claimchunk/player/FullPlayerData.java index f977e2e..98a356c 100644 --- a/src/main/java/com/cjburkey/claimchunk/player/FullPlayerData.java +++ b/src/main/java/com/cjburkey/claimchunk/player/FullPlayerData.java @@ -21,7 +21,8 @@ public FullPlayerData( String chunkName, long lastOnlineTime, boolean alert, - int extraMaxClaims, ChunkPlayerPermissions defaultChunkPermissions) { + int extraMaxClaims, + ChunkPlayerPermissions defaultChunkPermissions) { this.player = player; this.lastIgn = lastIgn; this.chunkName = chunkName; @@ -38,7 +39,8 @@ public FullPlayerData(SqlDataPlayer player) { player.chunkName, player.lastOnlineTime, player.alert, - player.extraMaxClaims, new ChunkPlayerPermissions(player.defaultChunkPermissions)); + player.extraMaxClaims, + new ChunkPlayerPermissions(player.defaultChunkPermissions)); } private FullPlayerData(FullPlayerData clone) { @@ -48,7 +50,8 @@ private FullPlayerData(FullPlayerData clone) { clone.chunkName, clone.lastOnlineTime, clone.alert, - clone.extraMaxClaims, clone.defaultChunkPermissions); + clone.extraMaxClaims, + clone.defaultChunkPermissions); } public SimplePlayerData toSimplePlayer() { diff --git a/src/main/java/com/cjburkey/claimchunk/player/PlayerHandler.java b/src/main/java/com/cjburkey/claimchunk/player/PlayerHandler.java index 93f5485..0536313 100644 --- a/src/main/java/com/cjburkey/claimchunk/player/PlayerHandler.java +++ b/src/main/java/com/cjburkey/claimchunk/player/PlayerHandler.java @@ -28,7 +28,8 @@ public Collection getJoinedPlayers() { public List getJoinedPlayersFromName(String start) { List out = new ArrayList<>(); for (SimplePlayerData ply : dataHandler.getPlayers()) { - if (ply.lastIgn() != null && ply.lastIgn().toLowerCase().startsWith(start.toLowerCase())) { + if (ply.lastIgn() != null + && ply.lastIgn().toLowerCase().startsWith(start.toLowerCase())) { out.add(ply.lastIgn()); } } diff --git a/src/main/java/com/cjburkey/claimchunk/player/SimplePlayerData.java b/src/main/java/com/cjburkey/claimchunk/player/SimplePlayerData.java index 1fdc62c..06d34a8 100644 --- a/src/main/java/com/cjburkey/claimchunk/player/SimplePlayerData.java +++ b/src/main/java/com/cjburkey/claimchunk/player/SimplePlayerData.java @@ -13,5 +13,4 @@ public boolean equals(Object o) { && player.equals(that.player) && lastIgn.equals(that.lastIgn); } - } diff --git a/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/AccessCmd.java b/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/AccessCmd.java index c0f7d86..084d298 100644 --- a/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/AccessCmd.java +++ b/src/main/java/com/cjburkey/claimchunk/smartcommand/sub/ply/AccessCmd.java @@ -1,6 +1,7 @@ package com.cjburkey.claimchunk.smartcommand.sub.ply; import com.cjburkey.claimchunk.ClaimChunk; +import com.cjburkey.claimchunk.chunk.ChunkPlayerPermissions; import com.cjburkey.claimchunk.smartcommand.CCSubCommand; import de.goldmensch.commanddispatcher.Executor; @@ -20,18 +21,7 @@ public class AccessCmd extends CCSubCommand { private static final String[] nonPlayerArguments = - new String[] { - "break", - "place", - "doors", - "redstone", - "interactVehicles", - "interactEntities", - "interactBlocks", - "useContainers", - "pvp", - "allChunks" - }; + new ChunkPlayerPermissions().toPermissionsMap().keySet().toArray(new String[0]); public AccessCmd(ClaimChunk claimChunk) { // TODO: CREATE `/chunk admin access ` to allow listing from @@ -54,6 +44,7 @@ public CCArg[] getPermittedArguments() { new CCArg(claimChunk.getMessages().argRedstone, CCAutoComplete.PERMISSION), new CCArg(claimChunk.getMessages().argInteractVehicles, CCAutoComplete.PERMISSION), new CCArg(claimChunk.getMessages().argInteractEntities, CCAutoComplete.PERMISSION), + new CCArg(claimChunk.getMessages().argAttackEntities, CCAutoComplete.PERMISSION), new CCArg(claimChunk.getMessages().argInteractBlocks, CCAutoComplete.PERMISSION), new CCArg(claimChunk.getMessages().argUseContainers, CCAutoComplete.PERMISSION), new CCArg(claimChunk.getMessages().argPvp, CCAutoComplete.PERMISSION), diff --git a/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java b/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java index 5e81f77..e3535fb 100644 --- a/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java +++ b/src/test/java/com/cjburkey/claimchunk/TestSQLPlease.java @@ -9,9 +9,9 @@ import com.cjburkey.claimchunk.data.sqlite.SqLiteTableMigrationManager; import com.cjburkey.claimchunk.data.sqlite.SqLiteWrapper; import com.cjburkey.claimchunk.player.FullPlayerData; - import com.zaxxer.q2o.Q2Sql; import com.zaxxer.q2o.q2o; + import org.junit.jupiter.api.Test; import org.sqlite.SQLiteDataSource; @@ -50,21 +50,22 @@ void ensureMigrationWorks() throws IOException { // Old table format Q2Sql.executeUpdate( """ - CREATE TABLE IF NOT EXISTS player_data ( - player_uuid TEXT PRIMARY KEY NOT NULL, - last_ign TEXT NOT NULL, - chunk_name TEXT, - last_online_time INTEGER NOT NULL, - alerts_enabled INTEGER NOT NULL, - extra_max_claims INTEGER NOT NULL - ) STRICT - """); + CREATE TABLE IF NOT EXISTS player_data ( + player_uuid TEXT PRIMARY KEY NOT NULL, + last_ign TEXT NOT NULL, + chunk_name TEXT, + last_online_time INTEGER NOT NULL, + alerts_enabled INTEGER NOT NULL, + extra_max_claims INTEGER NOT NULL + ) STRICT + """); q2o.deinitialize(); } try (TestQlWrap ignoredWrapper = new TestQlWrap()) { // Make sure the migration code added the column to the existing table - assert SqLiteTableMigrationManager.columnExists("player_data", "default_chunk_permissions"); + assert SqLiteTableMigrationManager.columnExists( + "player_data", "default_chunk_permissions"); } } @@ -76,7 +77,13 @@ void ensureNoDataLoss() { UUID ply2Uuid = UUID.randomUUID(); wrapper.sql.addPlayer( new FullPlayerData( - ply1Uuid, "SomeGuysName", null, System.currentTimeMillis(), true, 0, new ChunkPlayerPermissions(0))); + ply1Uuid, + "SomeGuysName", + null, + System.currentTimeMillis(), + true, + 0, + new ChunkPlayerPermissions(0))); wrapper.sql.addPlayer( new FullPlayerData( ply2Uuid, @@ -84,7 +91,8 @@ void ensureNoDataLoss() { "queenshit", System.currentTimeMillis(), false, - 0, new ChunkPlayerPermissions(0))); + 0, + new ChunkPlayerPermissions(0))); // Make fake accessors and permissions UUID accessorUuid1 = UUID.randomUUID(); @@ -133,13 +141,31 @@ void multiplePermissions() { // Add the players wrapper.sql.addPlayer( new FullPlayerData( - owner, "PersonHere", null, System.currentTimeMillis(), true, 0, new ChunkPlayerPermissions(0))); + owner, + "PersonHere", + null, + System.currentTimeMillis(), + true, + 0, + new ChunkPlayerPermissions(0))); wrapper.sql.addPlayer( new FullPlayerData( - accessor1, "PersonThere", null, System.currentTimeMillis(), true, 0, new ChunkPlayerPermissions(0))); + accessor1, + "PersonThere", + null, + System.currentTimeMillis(), + true, + 0, + new ChunkPlayerPermissions(0))); wrapper.sql.addPlayer( new FullPlayerData( - accessor2, "AnotherOne", null, System.currentTimeMillis(), true, 0, new ChunkPlayerPermissions(0))); + accessor2, + "AnotherOne", + null, + System.currentTimeMillis(), + true, + 0, + new ChunkPlayerPermissions(0))); // Add the chunk wrapper.sql.addClaimedChunk(chunkData); @@ -164,10 +190,22 @@ void insertOrUpdatePermission() { // Add the players and the chunk wrapper.sql.addPlayer( new FullPlayerData( - owner, "PersonHere", null, System.currentTimeMillis(), true, 0, new ChunkPlayerPermissions(0))); + owner, + "PersonHere", + null, + System.currentTimeMillis(), + true, + 0, + new ChunkPlayerPermissions(0))); wrapper.sql.addPlayer( new FullPlayerData( - accessor, "PersonThere", null, System.currentTimeMillis(), true, 0, new ChunkPlayerPermissions(0))); + accessor, + "PersonThere", + null, + System.currentTimeMillis(), + true, + 0, + new ChunkPlayerPermissions(0))); wrapper.sql.addClaimedChunk(new DataChunk(chunk, owner, new HashMap<>(), false)); // Insert the permission and check it