diff --git a/build.gradle.kts b/build.gradle.kts index 9106479..d563205 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ repositories { } mavenCentral() - mavenLocal() +// mavenLocal() } dependencies { diff --git a/src/main/java/dev/plex/extras/TFMExtras.java b/src/main/java/dev/plex/extras/TFMExtras.java index b288ed0..45b86b3 100755 --- a/src/main/java/dev/plex/extras/TFMExtras.java +++ b/src/main/java/dev/plex/extras/TFMExtras.java @@ -9,6 +9,7 @@ import dev.plex.config.ModuleConfig; import dev.plex.extras.command.slime.MyWorldCommand; import dev.plex.extras.command.slime.SlimeManagerCommand; import dev.plex.extras.hook.SlimeWorldHook; +import dev.plex.extras.island.storage.IslandHandler; import dev.plex.extras.jumppads.JumpPads; import dev.plex.listener.PlexListener; import dev.plex.module.PlexModule; @@ -34,7 +35,10 @@ public class TFMExtras extends PlexModule private ModuleConfig config; @Getter - private SlimeWorldHook slimeWorldHook; + private SlimeWorldHook slimeWorldHook = new SlimeWorldHook(); + + @Getter + private final IslandHandler islandHandler = new IslandHandler(); @Override public void load() @@ -110,6 +114,7 @@ public class TFMExtras extends PlexModule addDefaultMessage("selfPlayerWorldNotFound", "Hey! You don't seem to own a world yet. Go ahead and run /myworld create and then run /myworld for more help!"); 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!"); } @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 11570c9..9f8a560 100644 --- a/src/main/java/dev/plex/extras/command/slime/MyWorldCommand.java +++ b/src/main/java/dev/plex/extras/command/slime/MyWorldCommand.java @@ -6,6 +6,8 @@ import dev.plex.command.annotation.CommandPermissions; import dev.plex.command.exception.PlayerNotFoundException; import dev.plex.command.source.RequiredCommandSource; 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; @@ -73,6 +75,14 @@ public class MyWorldCommand extends PlexCommand { return messageComponent("worldLoadError"); } + final PlayerWorld playerWorld = TFMExtras.getModule().getIslandHandler().loadedIslands().get(target.getUniqueId()); + if (playerWorld != null) + { + if (playerWorld.visitPermission() == IslandPermissions.NOBODY || (playerWorld.visitPermission() == IslandPermissions.MEMBERS && !playerWorld.members().contains(target.getUniqueId()))) + { + return messageComponent("cannotAccessIsland"); + } + } player.teleportAsync(world.getSpawnLocation()); player.playSound(player.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1f, 1f); 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 dbb5302..ac1c0f3 100644 --- a/src/main/java/dev/plex/extras/hook/SlimeWorldHook.java +++ b/src/main/java/dev/plex/extras/hook/SlimeWorldHook.java @@ -16,6 +16,7 @@ import dev.plex.util.PlexLog; import java.io.IOException; 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; @@ -54,6 +55,8 @@ public class SlimeWorldHook implements IHook PlexLog.log("Enabling SWM Hook"); this.loader = plugin().getLoader("mysql"); + this.loadAllWorlds(); + TFMExtras.getModule().getIslandHandler().loadIslands(); } @Override @@ -66,10 +69,17 @@ public class SlimeWorldHook implements IHook final World world = Bukkit.getWorld(s); if (world != null) { - world.save(); + Bukkit.unloadWorld(world, true); i.getAndIncrement(); } }); + + loadedWorlds.clear(); + + CompletableFuture.runAsync(() -> { + TFMExtras.getModule().getIslandHandler().loadedIslands().values().forEach(playerWorld -> TFMExtras.getModule().getIslandHandler().updateIsland(playerWorld)); + TFMExtras.getModule().getIslandHandler().loadedIslands().clear(); + }); PlexLog.log("SWM Hook saved " + i.get() + " worlds"); } diff --git a/src/main/java/dev/plex/extras/hook/slime/PlayerWorld.java b/src/main/java/dev/plex/extras/hook/slime/PlayerWorld.java deleted file mode 100644 index 1a21548..0000000 --- a/src/main/java/dev/plex/extras/hook/slime/PlayerWorld.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.plex.extras.hook.slime; - -import com.google.common.collect.Lists; -import dev.plex.storage.annotation.PrimaryKey; -import dev.plex.storage.annotation.SQLTable; -import java.util.List; -import java.util.UUID; -import lombok.Data; - -/** - * @author Taah - * @since 9:26 PM [24-08-2023] - */ -@Data -@SQLTable("player_worlds") -public class PlayerWorld -{ - @PrimaryKey - private final UUID owner; - private final List members = Lists.newArrayList(); - private boolean anyoneCanEdit; - private boolean anyoneCanVisit; -} diff --git a/src/main/java/dev/plex/extras/island/PlayerWorld.java b/src/main/java/dev/plex/extras/island/PlayerWorld.java new file mode 100644 index 0000000..696e632 --- /dev/null +++ b/src/main/java/dev/plex/extras/island/PlayerWorld.java @@ -0,0 +1,54 @@ +package dev.plex.extras.island; + +import com.google.common.collect.Lists; +import dev.plex.extras.TFMExtras; +import dev.plex.extras.island.info.IslandPermissions; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +/** + * @author Taah + * @since 9:26 PM [24-08-2023] + */ +@AllArgsConstructor +//@SQLTable("player_worlds") +@Getter +@Setter +@Accessors(fluent = true) +public class PlayerWorld +{ +// @PrimaryKey + private final UUID owner; + private final List members; + private IslandPermissions editPermission; + private IslandPermissions visitPermission; + + public boolean addMember(UUID member) + { + if (members.contains(member)) + { + return false; + } + CompletableFuture.runAsync(() -> TFMExtras.getModule().getIslandHandler().insertMember(this.owner, member)); + this.members.add(member); + return true; + } + + public boolean removeMember(UUID member) + { + if (!members.contains(member)) + { + return false; + } + CompletableFuture.runAsync(() -> TFMExtras.getModule().getIslandHandler().deleteMember(this.owner, member)); + this.members.remove(member); + return true; + } +} diff --git a/src/main/java/dev/plex/extras/island/info/IslandPermissions.java b/src/main/java/dev/plex/extras/island/info/IslandPermissions.java new file mode 100644 index 0000000..5960a02 --- /dev/null +++ b/src/main/java/dev/plex/extras/island/info/IslandPermissions.java @@ -0,0 +1,12 @@ +package dev.plex.extras.island.info; + +/** + * @author Taah + * @since 10:44 PM [05-01-2024] + */ +public enum IslandPermissions +{ + ANYONE, + NOBODY, + MEMBERS +} diff --git a/src/main/java/dev/plex/extras/island/storage/IslandHandler.java b/src/main/java/dev/plex/extras/island/storage/IslandHandler.java new file mode 100644 index 0000000..709bee4 --- /dev/null +++ b/src/main/java/dev/plex/extras/island/storage/IslandHandler.java @@ -0,0 +1,157 @@ +package dev.plex.extras.island.storage; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import dev.plex.Plex; +import dev.plex.extras.island.PlayerWorld; +import dev.plex.extras.island.info.IslandPermissions; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * @author Taah + * @since 10:53 PM [05-01-2024] + */ +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_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`=?;"; + + @Getter + @Accessors(fluent = true) + private final Map loadedIslands = Maps.newHashMap(); + + public void loadIslands() + { + // Member to Islands Mapping + final Map> mappedMembers = Maps.newHashMap(); + + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + final PreparedStatement loadIslands = connection.prepareStatement(LOAD_ISLANDS); + final PreparedStatement loadMembers = connection.prepareStatement(LOAD_MEMBERS); + + final ResultSet membersQuery = loadMembers.executeQuery(); + while (membersQuery.next()) + { + final UUID uuid = UUID.fromString(membersQuery.getString("uuid")); + List islands = mappedMembers.getOrDefault(uuid, Lists.newArrayList()); + islands.add(UUID.fromString(membersQuery.getString("island_owner_uuid"))); + mappedMembers.put(uuid, islands); + } + + + final ResultSet islandsQuery = loadIslands.executeQuery(); + while (islandsQuery.next()) + { + final UUID owner = UUID.fromString(islandsQuery.getString("owner")); + 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)); + } + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + } + + public void insertIsland(PlayerWorld world) + { + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + final PreparedStatement statement = connection.prepareStatement(INSERT_ISLAND); + statement.setString(1, world.owner().toString()); + statement.setString(2, world.editPermission().name()); + statement.setString(3, world.visitPermission().name()); + + statement.execute(); + + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + } + + public void insertMember(UUID islandOwner, UUID member) + { + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + final PreparedStatement statement = connection.prepareStatement(INSERT_MEMBER); + statement.setString(1, member.toString()); + statement.setString(2, islandOwner.toString()); + statement.execute(); + + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + } + + public void deleteMember(UUID islandOwner, UUID member) + { + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + final PreparedStatement statement = connection.prepareStatement(DELETE_MEMBER); + statement.setString(1, member.toString()); + statement.setString(2, islandOwner.toString()); + statement.execute(); + + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + } + + public void deleteIsland(UUID islandOwner) + { + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + final PreparedStatement statement = connection.prepareStatement(DELETE_ISLAND); + statement.setString(1, islandOwner.toString()); + statement.execute(); + + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + } + + public void updateIsland(PlayerWorld world) + { + try (Connection connection = Plex.get().getSqlConnection().getCon()) + { + 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.executeUpdate(); + + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + } + +}