From 6a655dfc2cb125a5df3df788c476cee4e4074cb3 Mon Sep 17 00:00:00 2001 From: Taah Date: Fri, 3 May 2024 16:27:35 -0700 Subject: [PATCH] Add Player World settings storage implementation Add Visit permissions Add Edit Permissions Add Interact Permissions TODO: Banning members, adding members to world, removing all non-members from world if visit is set to nobody --- src/main/java/dev/plex/extras/TFMExtras.java | 3 + .../extras/command/slime/MyWorldCommand.java | 40 ++++++- .../dev/plex/extras/hook/SlimeWorldHook.java | 60 ++++++---- .../dev/plex/extras/island/PlayerWorld.java | 1 + .../extras/island/storage/IslandHandler.java | 27 ++++- .../plex/extras/listener/WorldListener.java | 105 ++++++++++++++++++ 6 files changed, 208 insertions(+), 28 deletions(-) create mode 100644 src/main/java/dev/plex/extras/listener/WorldListener.java diff --git a/src/main/java/dev/plex/extras/TFMExtras.java b/src/main/java/dev/plex/extras/TFMExtras.java index 45b86b3..efb271f 100755 --- a/src/main/java/dev/plex/extras/TFMExtras.java +++ b/src/main/java/dev/plex/extras/TFMExtras.java @@ -115,6 +115,9 @@ public class TFMExtras extends PlexModule addDefaultMessage("playerWorldNotFound", "Hey! This player's world does not seem to exist. Are they online?"); addDefaultMessage("worldLoadError", "Hey! It looks like something went wrong when this world was being loaded in, please try asking the player (or if it is yours, then rejoin) to rejoin and if not, tell the world owner to contact support on our Discord"); addDefaultMessage("cannotAccessIsland", "Unfortunately you cannot access this player's island!"); + addDefaultMessage("islandPermissionUpdated", "Your island permission for {0} has been updated to {1}.", "0 - Permission name", "1 - New value"); + addDefaultMessage("cantModifyIsland", "You can't modify this player's island!"); + addDefaultMessage("cantVisitIsland", "You can't visit this player's island!"); } @Override diff --git a/src/main/java/dev/plex/extras/command/slime/MyWorldCommand.java b/src/main/java/dev/plex/extras/command/slime/MyWorldCommand.java index 9f8a560..7fba007 100644 --- a/src/main/java/dev/plex/extras/command/slime/MyWorldCommand.java +++ b/src/main/java/dev/plex/extras/command/slime/MyWorldCommand.java @@ -9,9 +9,11 @@ import dev.plex.extras.TFMExtras; import dev.plex.extras.island.PlayerWorld; import dev.plex.extras.island.info.IslandPermissions; import dev.plex.util.PlexUtils; + import java.util.Arrays; import java.util.Collections; import java.util.List; + import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Sound; @@ -48,10 +50,10 @@ public class MyWorldCommand extends PlexCommand { if (args.length == 1) { - if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(player.getUniqueId().toString())) - { - return messageComponent("selfPlayerWorldNotFound"); - } + if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(player.getUniqueId().toString())) + { + return messageComponent("selfPlayerWorldNotFound"); + } World world = Bukkit.getWorld(player.getUniqueId().toString()); if (world == null) { @@ -87,6 +89,36 @@ public class MyWorldCommand extends PlexCommand player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1f, 1f); return null; } + case "settings" -> + { + if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(player.getUniqueId().toString())) + { + return messageComponent("selfPlayerWorldNotFound"); + } + if (args.length == 1) + { + return usage("/myworld settings "); + } + if (!args[1].equalsIgnoreCase("interact") && !args[1].equalsIgnoreCase("edit") && !args[1].equalsIgnoreCase("visit")) + { + return usage("/myworld settings "); + } + final PlayerWorld playerWorld = TFMExtras.getModule().getIslandHandler().loadedIslands().get(player.getUniqueId()); + try { + final IslandPermissions permissions = IslandPermissions.valueOf(args[2].toUpperCase()); + switch (args[1].toLowerCase()) + { + case "interact" -> playerWorld.interactPermission(permissions); + case "edit" -> playerWorld.editPermission(permissions); + case "visit" -> playerWorld.visitPermission(permissions); + } + return messageComponent("islandPermissionUpdated", args[1].toUpperCase(), permissions.name()); + + } catch (IllegalArgumentException e) + { + return usage("/myworld settings "); + } + } } return null; } diff --git a/src/main/java/dev/plex/extras/hook/SlimeWorldHook.java b/src/main/java/dev/plex/extras/hook/SlimeWorldHook.java index ac1c0f3..0f21089 100644 --- a/src/main/java/dev/plex/extras/hook/SlimeWorldHook.java +++ b/src/main/java/dev/plex/extras/hook/SlimeWorldHook.java @@ -1,5 +1,6 @@ package dev.plex.extras.hook; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.infernalsuite.aswm.api.SlimePlugin; import com.infernalsuite.aswm.api.exceptions.CorruptedWorldException; @@ -11,13 +12,20 @@ import com.infernalsuite.aswm.api.loaders.SlimeLoader; import com.infernalsuite.aswm.api.world.SlimeWorld; import com.infernalsuite.aswm.api.world.properties.SlimeProperties; import com.infernalsuite.aswm.api.world.properties.SlimePropertyMap; +import dev.plex.Plex; import dev.plex.extras.TFMExtras; +import dev.plex.extras.island.PlayerWorld; +import dev.plex.extras.island.info.IslandPermissions; import dev.plex.util.PlexLog; + import java.io.IOException; +import java.sql.*; +import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; + import lombok.Getter; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Bukkit; @@ -56,6 +64,17 @@ public class SlimeWorldHook implements IHook this.loader = plugin().getLoader("mysql"); this.loadAllWorlds(); + + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + connection.prepareStatement("ALTER TABLE `islands` ADD COLUMN IF NOT EXISTS `interactPermission` VARCHAR(10);").execute(); + + } catch (SQLException e) + { + throw new RuntimeException(e); + } + + TFMExtras.getModule().getIslandHandler().createTables(); TFMExtras.getModule().getIslandHandler().loadIslands(); } @@ -76,7 +95,8 @@ public class SlimeWorldHook implements IHook loadedWorlds.clear(); - CompletableFuture.runAsync(() -> { + CompletableFuture.runAsync(() -> + { TFMExtras.getModule().getIslandHandler().loadedIslands().values().forEach(playerWorld -> TFMExtras.getModule().getIslandHandler().updateIsland(playerWorld)); TFMExtras.getModule().getIslandHandler().loadedIslands().clear(); }); @@ -97,13 +117,11 @@ public class SlimeWorldHook implements IHook SlimeWorld world = this.plugin().loadWorld(this.loader, s, false, slimePropertyMap); this.plugin().loadWorld(world); this.loader.unlockWorld(s); - } - catch (UnknownWorldException | WorldLockedException | CorruptedWorldException | NewerFormatException | - IllegalArgumentException ex) + } catch (UnknownWorldException | WorldLockedException | CorruptedWorldException | NewerFormatException | + IllegalArgumentException ex) { PlexLog.error(ex.getMessage()); - } - catch (IOException e) + } catch (IOException e) { PlexLog.error(STORAGE_FAILURE); return; @@ -129,10 +147,12 @@ public class SlimeWorldHook implements IHook world.getWorldBorder().setSize(configuratedSize == 0 ? 500 : configuratedSize); world.getWorldBorder().setDamageAmount(0); world.getWorldBorder().setDamageBuffer(0); + + Bukkit.getPluginManager().callEvent(new WorldLoadEvent(world)); + PlexLog.debug("Loaded {0}", s); }); - } - catch (IOException | IllegalArgumentException ex) + } catch (IOException | IllegalArgumentException ex) { PlexLog.error(ex.getMessage()); } @@ -152,8 +172,7 @@ public class SlimeWorldHook implements IHook Bukkit.unloadWorld(world, false); } this.loader.deleteWorld(world); - } - catch (UnknownWorldException | IOException e) + } catch (UnknownWorldException | IOException e) { PlexLog.error(e.getMessage()); } @@ -173,27 +192,23 @@ public class SlimeWorldHook implements IHook final SlimeWorld slimeWorld = this.plugin().createEmptyWorld(this.loader, uuid.toString(), false, slimePropertyMap); this.plugin().loadWorld(slimeWorld); newWorld = true; - } - catch (WorldAlreadyExistsException e) + } catch (WorldAlreadyExistsException e) { try { SlimeWorld world = this.plugin().loadWorld(this.loader, uuid.toString(), false, slimePropertyMap); this.plugin().loadWorld(world); this.loader.unlockWorld(uuid.toString()); - } - catch (WorldLockedException | CorruptedWorldException | NewerFormatException | UnknownWorldException | - IOException | IllegalArgumentException ex) + } catch (WorldLockedException | CorruptedWorldException | NewerFormatException | UnknownWorldException | + IOException | IllegalArgumentException ex) { PlexLog.error(ex.getMessage()); } - } - catch (IOException e) + } catch (IOException e) { PlexLog.error(STORAGE_FAILURE); - } - catch (WorldLockedException | UnknownWorldException e) + } catch (WorldLockedException | UnknownWorldException e) { throw new RuntimeException(e); } @@ -227,6 +242,11 @@ public class SlimeWorldHook implements IHook final WorldLoadEvent event = new WorldLoadEvent(world); Bukkit.getServer().getPluginManager().callEvent(event); + final PlayerWorld playerWorld = new PlayerWorld(uuid, Lists.newArrayList(), IslandPermissions.NOBODY, IslandPermissions.ANYONE, IslandPermissions.ANYONE); + + TFMExtras.getModule().getIslandHandler().insertIsland(playerWorld); + TFMExtras.getModule().getIslandHandler().loadedIslands().put(uuid, playerWorld); + return Pair.of(world, newWorld); } @@ -238,6 +258,6 @@ public class SlimeWorldHook implements IHook @Override public SlimePlugin plugin() { - return (SlimePlugin)Bukkit.getPluginManager().getPlugin("SlimeWorldManager"); + return (SlimePlugin) Bukkit.getPluginManager().getPlugin("SlimeWorldManager"); } } diff --git a/src/main/java/dev/plex/extras/island/PlayerWorld.java b/src/main/java/dev/plex/extras/island/PlayerWorld.java index 696e632..da97080 100644 --- a/src/main/java/dev/plex/extras/island/PlayerWorld.java +++ b/src/main/java/dev/plex/extras/island/PlayerWorld.java @@ -29,6 +29,7 @@ public class PlayerWorld private final List members; private IslandPermissions editPermission; private IslandPermissions visitPermission; + private IslandPermissions interactPermission; public boolean addMember(UUID member) { diff --git a/src/main/java/dev/plex/extras/island/storage/IslandHandler.java b/src/main/java/dev/plex/extras/island/storage/IslandHandler.java index 709bee4..4569a9b 100644 --- a/src/main/java/dev/plex/extras/island/storage/IslandHandler.java +++ b/src/main/java/dev/plex/extras/island/storage/IslandHandler.java @@ -25,16 +25,29 @@ public class IslandHandler //TODO: Create Table statements private static final String LOAD_ISLANDS = "SELECT * FROM `islands`;"; private static final String LOAD_MEMBERS = "SELECT * FROM `island_members`;"; - private static final String INSERT_ISLAND = "INSERT INTO `islands` (`owner`, `editPermission`, `visitPermission`) VALUES(?, ?, ?);"; + private static final String INSERT_ISLAND = "INSERT INTO `islands` (`owner`, `editPermission`, `visitPermission`, `interactPermission`) VALUES(?, ?, ?, ?);"; private static final String INSERT_MEMBER = "INSERT INTO `island_members` (`uuid`, `island_owner_uuid`) VALUES(?, ?);"; private static final String DELETE_ISLAND = "DELETE FROM `islands` WHERE `owner`=?;"; private static final String DELETE_MEMBER = "DELETE FROM `island_members` WHERE `uuid`=? AND `island_owner_uuid`=?;"; - private static final String UPDATE_ISLAND = "UPDATE `islands` SET `editPermission`=?, `visitPermission`=? WHERE `owner`=?;"; + private static final String UPDATE_ISLAND = "UPDATE `islands` SET `editPermission`=?, `visitPermission`=?, `interactPermission`=? WHERE `owner`=?;"; + private static final String CREATE_ISLANDS_TABLE = "CREATE TABLE IF NOT EXISTS `islands` (`owner` VARCHAR(36) NOT NULL PRIMARY KEY, `editPermission` VARCHAR(10), `visitPermission` VARCHAR(10), `interactPermission` VARCHAR(10));"; + private static final String CREATE_MEMBERS_TABLE = "CREATE TABLE IF NOT EXISTS `island_members` (`uuid` VARCHAR(36), `island_owner_uuid` VARCHAR(36));"; @Getter @Accessors(fluent = true) private final Map loadedIslands = Maps.newHashMap(); + public void createTables() + { + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + connection.prepareStatement(CREATE_ISLANDS_TABLE).execute(); + connection.prepareStatement(CREATE_MEMBERS_TABLE).execute(); + } catch (SQLException e) + { + throw new RuntimeException(e); + } + } public void loadIslands() { // Member to Islands Mapping @@ -62,7 +75,11 @@ public class IslandHandler final List members = mappedMembers.entrySet().stream().filter(uuiduuidEntry -> uuiduuidEntry.getValue().stream().anyMatch(owners -> owners.equals(owner))).map(Map.Entry::getKey).toList(); final IslandPermissions editPerm = IslandPermissions.valueOf(islandsQuery.getString("editPermission").toUpperCase()); final IslandPermissions visitPerm = IslandPermissions.valueOf(islandsQuery.getString("visitPermission").toUpperCase()); - loadedIslands.put(owner, new PlayerWorld(owner, members, editPerm, visitPerm)); + + final String interactPermission = islandsQuery.getString("interactPermission"); + + final IslandPermissions interactPerm = interactPermission == null ? IslandPermissions.NOBODY : IslandPermissions.valueOf(interactPermission.toUpperCase()); + loadedIslands.put(owner, new PlayerWorld(owner, members, editPerm, visitPerm, interactPerm)); } } catch (SQLException e) @@ -79,6 +96,7 @@ public class IslandHandler statement.setString(1, world.owner().toString()); statement.setString(2, world.editPermission().name()); statement.setString(3, world.visitPermission().name()); + statement.setString(4, world.interactPermission().name()); statement.execute(); @@ -143,7 +161,8 @@ public class IslandHandler final PreparedStatement statement = connection.prepareStatement(UPDATE_ISLAND); statement.setString(1, world.editPermission().name()); statement.setString(2, world.visitPermission().name()); - statement.setString(3, world.owner().toString()); + statement.setString(3, world.interactPermission().name()); + statement.setString(4, world.owner().toString()); statement.executeUpdate(); diff --git a/src/main/java/dev/plex/extras/listener/WorldListener.java b/src/main/java/dev/plex/extras/listener/WorldListener.java new file mode 100644 index 0000000..2f5bf5a --- /dev/null +++ b/src/main/java/dev/plex/extras/listener/WorldListener.java @@ -0,0 +1,105 @@ +package dev.plex.extras.listener; + +import dev.plex.extras.TFMExtras; +import dev.plex.extras.island.PlayerWorld; +import dev.plex.extras.island.info.IslandPermissions; +import dev.plex.listener.PlexListener; +import dev.plex.util.PlexUtils; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import java.util.UUID; + +public class WorldListener extends PlexListener +{ + @EventHandler + public void onBuild(BlockPlaceEvent event) + { + if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(event.getPlayer().getWorld().getName())) return; + final UUID worldOwner = UUID.fromString(event.getPlayer().getWorld().getName()); + final PlayerWorld world = TFMExtras.getModule().getIslandHandler().loadedIslands().get(worldOwner); + if (world.owner().equals(event.getPlayer().getUniqueId())) return; + if (world.editPermission() == IslandPermissions.NOBODY) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantModifyIsland")); + event.setCancelled(true); + event.setBuild(false); + return; + } + + if (world.editPermission() == IslandPermissions.MEMBERS && !world.members().contains(event.getPlayer().getUniqueId())) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantModifyIsland")); + event.setCancelled(true); + event.setBuild(false); + } + } + + @EventHandler + public void onBreak(BlockBreakEvent event) + { + if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(event.getPlayer().getWorld().getName())) return; + final UUID worldOwner = UUID.fromString(event.getPlayer().getWorld().getName()); + final PlayerWorld world = TFMExtras.getModule().getIslandHandler().loadedIslands().get(worldOwner); + if (world.owner().equals(event.getPlayer().getUniqueId())) return; + if (world.editPermission() == IslandPermissions.NOBODY) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantModifyIsland")); + event.setCancelled(true); + return; + } + + if (world.editPermission() == IslandPermissions.MEMBERS && !world.members().contains(event.getPlayer().getUniqueId())) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantModifyIsland")); + event.setCancelled(true); + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(event.getPlayer().getWorld().getName())) return; + final UUID worldOwner = UUID.fromString(event.getPlayer().getWorld().getName()); + final PlayerWorld world = TFMExtras.getModule().getIslandHandler().loadedIslands().get(worldOwner); + if (world.owner().equals(event.getPlayer().getUniqueId())) return; + if (world.interactPermission() == IslandPermissions.NOBODY) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantModifyIsland")); + event.setCancelled(true); + return; + } + + if (world.interactPermission() == IslandPermissions.MEMBERS && !world.members().contains(event.getPlayer().getUniqueId())) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantModifyIsland")); + event.setCancelled(true); + } + } + + @EventHandler + public void onWorldChange(PlayerChangedWorldEvent event) + { + if (!TFMExtras.getModule().getSlimeWorldHook().isWorldLoaded(event.getPlayer().getWorld().getName())) return; + final UUID worldOwner = UUID.fromString(event.getPlayer().getWorld().getName()); + final PlayerWorld world = TFMExtras.getModule().getIslandHandler().loadedIslands().get(worldOwner); + if (world.owner().equals(event.getPlayer().getUniqueId())) return; + if (world.visitPermission() == IslandPermissions.NOBODY) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantVisitIsland")); + event.getPlayer().teleportAsync(event.getFrom().getSpawnLocation()); + return; + } + + if (world.visitPermission() == IslandPermissions.MEMBERS && !world.members().contains(event.getPlayer().getUniqueId())) + { + event.getPlayer().sendMessage(PlexUtils.messageComponent("cantVisitIsland")); + event.getPlayer().teleportAsync(event.getFrom().getSpawnLocation()); + return; + } + } +}