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; + } + } +}