diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..b7e42f7 --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + PSHubCore + PSHubCore + v3-dev + + + + maven-compiler-plugin + + 17 + 17 + + + + maven-shade-plugin + + + package + + shade + + + + + PSHubCore + + + + + + + jitpack.io + https://jitpack.io + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + placeholderapi + https://repo.extendedclip.com/content/repositories/placeholderapi/ + + + + + org.spigotmc + spigot-api + 1.18.2-R0.1-SNAPSHOT + provided + + + org.projectlombok + lombok + 1.18.24 + provided + + + me.clip + placeholderapi + 2.9.2 + provided + + + org.hibernate + hibernate-core + 6.1.5.Final + compile + + + diff --git a/pom.xml b/pom.xml index 9e3b3e8..4f8b787 100644 --- a/pom.xml +++ b/pom.xml @@ -10,8 +10,23 @@ org.apache.maven.plugins maven-compiler-plugin - 11 - 11 + 17 + 17 + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + PSHubCore @@ -30,10 +45,6 @@ placeholderapi https://repo.extendedclip.com/content/repositories/placeholderapi/ - - jitpack.io - https://jitpack.io - @@ -61,12 +72,12 @@ org.slf4j slf4j-api - 2.0.1 + 2.0.5 org.slf4j slf4j-simple - 2.0.0 + 2.0.5 com.moandjiezana.toml @@ -90,6 +101,11 @@ 2.9.2 provided + + org.hibernate + hibernate-core + 6.1.5.Final + PSHubCore diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/PSHubCore.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/PSHubCore.java deleted file mode 100644 index 2b5d489..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/PSHubCore.java +++ /dev/null @@ -1,106 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore; - -import com.samjakob.spigui.SpiGUI; -import lombok.Getter; -import lombok.SneakyThrows; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.java.JavaPlugin; -import os.arcadiadevs.playerservers.hubcore.commands.CommandManager; -import os.arcadiadevs.playerservers.hubcore.database.DataBase; -import os.arcadiadevs.playerservers.hubcore.database.DataSource; -import os.arcadiadevs.playerservers.hubcore.events.ClickEvent; -import os.arcadiadevs.playerservers.hubcore.events.HubEvents; -import os.arcadiadevs.playerservers.hubcore.events.JoinEvent; -import os.arcadiadevs.playerservers.hubcore.objects.ServerCache; -import os.arcadiadevs.playerservers.hubcore.placeholders.PlayerCount; - -import java.io.*; -import java.util.Objects; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class PSHubCore extends JavaPlugin { - - private static PSHubCore PSH; - @Getter - private static DataBase dataBase; - @Getter - public YamlConfiguration multinode; - @Getter - private SpiGUI spiGUI; - - @Getter - public ServerCache serverCache; - - @SneakyThrows - @Override - public void onEnable() { - PSH = this; - getConfig().options().copyDefaults(true); - saveConfig(); - createMultiNodeConfig(); - - DataSource ds = new DataSource(); - ds.registerDataSource(); - - if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { - /* - * We register the EventListeneres here, when PlaceholderAPI is installed. - * Since all events are in the main class (this class), we simply use "this" - */ - new PlayerCount(this).register(); - } - - Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); - Bukkit.getPluginManager().registerEvents(new ClickEvent(), this); - Bukkit.getPluginManager().registerEvents(new JoinEvent(), this); - Bukkit.getPluginManager().registerEvents(new HubEvents(), this); - - Objects.requireNonNull(getCommand("servers")).setExecutor(new CommandManager()); - - // Initialize SpiGUI - spiGUI = new SpiGUI(this); - - // Initialize ServerCache - serverCache = new ServerCache(); - - // Create ServerCache refreshing task - ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); - executor.scheduleAtFixedRate(serverCache, 1, getConfig().getInt("cache-time"), TimeUnit.SECONDS); - } - - private void createMultiNodeConfig() throws IOException { - - if (!getConfig().getBoolean("multi-node")) { - return; - } - - File configFile = new File(this.getDataFolder(), "multinode.yml"); - - if (!configFile.exists()) { - InputStream inputStream = getClass().getResourceAsStream("/multinode.yml"); - OutputStream outputStream = new FileOutputStream(configFile); - int read; - byte[] bytes = new byte[1024]; - while ((read = inputStream.read(bytes)) != -1) { - outputStream.write(bytes, 0, read); - } - inputStream.close(); - outputStream.close(); - } - - multinode = YamlConfiguration.loadConfiguration(configFile); - } - - public static PSHubCore getInstance() { - return PSH; - } - - @Override - public void onDisable() { - super.onDisable(); - getServer().getMessenger().unregisterIncomingPluginChannel(this, "BungeeCord"); - } -} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/PsHubCore.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/PsHubCore.java new file mode 100644 index 0000000..3ed4a4f --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/PsHubCore.java @@ -0,0 +1,122 @@ +package os.arcadiadevs.playerservers.hubcore; + +import com.samjakob.spigui.SpiGUI; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Objects; +import lombok.Getter; +import lombok.SneakyThrows; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.hibernate.SessionFactory; +import os.arcadiadevs.playerservers.hubcore.commands.CommandManager; +import os.arcadiadevs.playerservers.hubcore.controllers.NodesController; +import os.arcadiadevs.playerservers.hubcore.controllers.ServersController; +import os.arcadiadevs.playerservers.hubcore.events.ClickEvent; +import os.arcadiadevs.playerservers.hubcore.events.HubEvents; +import os.arcadiadevs.playerservers.hubcore.events.JoinEvent; +import os.arcadiadevs.playerservers.hubcore.models.Node; +import os.arcadiadevs.playerservers.hubcore.models.Server; +import os.arcadiadevs.playerservers.hubcore.placeholders.PlayerCount; + +public class PsHubCore extends JavaPlugin { + + @Getter + private static PsHubCore instance; + + @Getter + private SpiGUI spiGui; + + @Getter + private SessionFactory sessionFactory; + + @Getter + private ServersController serversController; + + @Getter + private NodesController nodesController; + + @SneakyThrows + @Override + public void onEnable() { + instance = this; + getConfig().options().copyDefaults(true); + saveConfig(); + + extractFile("hibernate.cfg.xml"); + + sessionFactory = + new org.hibernate.cfg.Configuration() + .configure(new File(this.getDataFolder().getAbsolutePath() + "/" + "hibernate.cfg.xml")) + .addAnnotatedClass(Server.class) + .addAnnotatedClass(Node.class) + .buildSessionFactory(); + + // Initialize the controllers + serversController = new ServersController(sessionFactory); + nodesController = new NodesController(sessionFactory); + + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { + /* + * We register the EventListeneres here, when PlaceholderAPI is installed. + * Since all events are in the main class (this class), we simply use "this" + */ + new PlayerCount(serversController).register(); + } + + Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + Bukkit.getPluginManager().registerEvents(new ClickEvent(this), this); + Bukkit.getPluginManager().registerEvents(new JoinEvent(this), this); + Bukkit.getPluginManager().registerEvents(new HubEvents(getConfig()), this); + + Objects.requireNonNull(getCommand("servers")).setExecutor(new CommandManager()); + + // Initialize SpiGUI + spiGui = new SpiGUI(this); + + // Initialize ServerCache + //serverCache = new ServerCache(); + + // Create ServerCache refreshing task + //ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + //executor.scheduleAtFixedRate(serverCache, 1, getConfig().getInt("cache-time"), TimeUnit.SECONDS); + } + + /** + * Extracts a file from the jar to the data folder. + * + * @param name The name of the file. + * @return The file + * @throws IOException If the file cannot be extracted. + */ + private File extractFile(String name) throws IOException { + var configFile = new File(this.getDataFolder(), name); + + //noinspection ResultOfMethodCallIgnored + getDataFolder().mkdirs(); + if (configFile.createNewFile()) { + try ( + var fis = getClass().getResourceAsStream("/" + name); + var fos = new FileOutputStream(configFile) + ) { + var buf = new byte[1024]; + int i; + while ((i = Objects.requireNonNull(fis).read(buf)) != -1) { + fos.write(buf, 0, i); + } + } catch (Exception e) { + Bukkit.getLogger() + .warning(String.format("Error extracting %s: %s", name, e.getMessage())); + } + } + + return configFile; + } + + @Override + public void onDisable() { + super.onDisable(); + getServer().getMessenger().unregisterIncomingPluginChannel(this, "BungeeCord"); + } +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/commands/CommandManager.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/commands/CommandManager.java index 54fecd0..a9522b4 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/commands/CommandManager.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/commands/CommandManager.java @@ -4,27 +4,33 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; +import os.arcadiadevs.playerservers.hubcore.guis.SelectorGui; import os.arcadiadevs.playerservers.hubcore.utils.ChatUtil; -import os.arcadiadevs.playerservers.hubcore.utils.GUIUtils; +import os.arcadiadevs.playerservers.hubcore.guis.PlayerMenuGui; public class CommandManager implements CommandExecutor { - @SuppressWarnings("NullableProblems") - @Override - public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) { - if (commandSender instanceof Player) { - if (!PSHubCore.getInstance().getConfig().getBoolean("gui.selector.item.enabled")) { - commandSender.sendMessage(ChatUtil.translate("&9PlayerServers> &7Oops, gui isn't enabled in config file!")); - return true; - } - if (PSHubCore.getInstance().getConfig().getBoolean("gui.selector.item.enabled")) { - if (command.getName().equalsIgnoreCase("servers") || command.getName().equalsIgnoreCase("menu") || command.getName().equalsIgnoreCase("opengui")) { - Player player = (Player) commandSender; - GUIUtils.openSelector(player); - } - } - } - return true; + @Override + public boolean onCommand(CommandSender commandSender, Command command, String s, + String[] strings) { + if (!(commandSender instanceof Player player)) { + ChatUtil.sendMessage(commandSender, + "&9Error> &cYou must be a player to execute this command."); + return true; } + + if (!PsHubCore.getInstance().getConfig().getBoolean("gui.selector.enabled")) { + ChatUtil.sendMessage(player, "&9PlayerServers> &7Oops, this feature is disabled."); + return true; + } + + if (command.getName().equalsIgnoreCase("servers") || + command.getName().equalsIgnoreCase("menu") || + command.getName().equalsIgnoreCase("opengui")) { + SelectorGui.openGui(player); + } + + return true; + } } diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/controllers/NodesController.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/controllers/NodesController.java new file mode 100644 index 0000000..9ac6b16 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/controllers/NodesController.java @@ -0,0 +1,67 @@ +package os.arcadiadevs.playerservers.hubcore.controllers; + +import java.util.List; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import os.arcadiadevs.playerservers.hubcore.models.Node; + +/** + * A class that handles all the database operations for node object. + * + * @author ArcadiaDevs + */ +public class NodesController { + + private final SessionFactory sessionFactory; + + public NodesController(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + /** + * Create a new node in the database. + * + * @param node The node to create + */ + public void createNode(Node node) { + try (Session session = sessionFactory.openSession()) { + session.beginTransaction(); + session.persist(node); + session.getTransaction().commit(); + } + } + + /** + * Gets all the nodes from the database. + * + * @return A list of all the nodes + */ + public List getNodes() { + try (Session session = sessionFactory.openSession()) { + return session.createQuery("from Node", Node.class).list(); + } + } + + /** + * Gets the next available node. + * + * @return The next available node + */ + public Node getNextNode() { + List nodes = getNodes(); + + if (nodes.isEmpty()) { + return null; + } + + Node emptiestNode = nodes.get(0); + + for (Node node : nodes) { + if (node.getServers().size() < emptiestNode.getServers().size()) { + emptiestNode = node; + } + } + + return emptiestNode; + } +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/controllers/ServersController.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/controllers/ServersController.java new file mode 100644 index 0000000..54f01a7 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/controllers/ServersController.java @@ -0,0 +1,152 @@ +package os.arcadiadevs.playerservers.hubcore.controllers; + +import java.util.List; +import java.util.UUID; +import org.bukkit.entity.Player; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import os.arcadiadevs.playerservers.hubcore.models.Server; + +/** + * A class that handles all the database operations for the servers object. + * + * @author ArcadiaDevs + */ +public class ServersController { + + private final SessionFactory sessionFactory; + + /** + * Creates a new instance of the servers controller. + * + * @param sessionFactory The session factory + */ + public ServersController(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + /** + * Create a new server in the database. + * + * @param server The server to create + */ + public void createServer(Server server) { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + session.persist(server); + session.getTransaction().commit(); + } + + /** + * Gets all the servers from the database. + * + * @return A list of all the servers + */ + public List getServers() { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + List servers = session.createQuery("from Server", Server.class).list(); + session.getTransaction().commit(); + return servers; + } + + /** + * Gets the server by the server id. + * + * @param ownerId The owner id + * @return The server + */ + public Server getServer(UUID ownerId) { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + Server server = session + .createQuery("from Server where owner = :owner", Server.class) + .setParameter("owner", ownerId) + .uniqueResult(); + session.getTransaction().commit(); + return server; + } + + public Server getServer(Player player) { + return getServer(player.getUniqueId()); + } + + /** + * Checks if the player has a server. + * + * @param owner The player to check + * @return True if the player has a server, false otherwise + */ + public boolean hasServer(UUID owner) { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + Server server = session + .createQuery("from Server where owner = :owner", Server.class) + .setParameter("owner", owner) + .uniqueResult(); + session.getTransaction().commit(); + return server != null; + } + + public boolean hasServer(Player player) { + return hasServer(player.getUniqueId()); + } + + /** + * Checks if a server exists by the server id. + * + * @param id The server id + * @return True if the server exists, false otherwise + */ + public boolean serverExists(String id) { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + Server server = session + .createQuery("from Server where id = :id", Server.class) + .setParameter("id", id) + .uniqueResult(); + session.getTransaction().commit(); + return server != null; + } + + /** + * Renames the server. + * + * @param owner The owner of the server + * @param id The new id (name) + */ + public void renameServer(UUID owner, String id) { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + Server server = session + .createQuery("from Server where owner = :owner", Server.class) + .setParameter("owner", owner) + .uniqueResult(); + server.setId(id); + session.getTransaction().commit(); + } + + public void renameServer(Player player, String id) { + renameServer(player.getUniqueId(), id); + } + + /** + * Deletes the server. + * + * @param owner The owner of the server + */ + public void removePlayer(UUID owner) { + Session session = this.sessionFactory.getCurrentSession(); + session.beginTransaction(); + Server server = session + .createQuery("from Server where owner = :owner", Server.class) + .setParameter("owner", owner) + .uniqueResult(); + session.remove(server); + session.getTransaction().commit(); + } + + public void removePlayer(Player player) { + removePlayer(player.getUniqueId()); + } +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/database/DataBase.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/database/DataBase.java deleted file mode 100644 index a7bcb70..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/database/DataBase.java +++ /dev/null @@ -1,107 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.database; - -import org.bukkit.entity.Player; -import os.arcadiadevs.playerservers.hubcore.objects.Server; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class DataBase { - - private static final ExecutorService executor = Executors.newFixedThreadPool(10); - - public static boolean containsPort(String port) { - try (Connection connection = DataSource.getConnection()) { - PreparedStatement stmt = connection.prepareStatement("SELECT * FROM PlayerServers"); - ResultSet rs = stmt.executeQuery(); - while(rs.next()) { - if (rs.getString("Port").equals(port)) - return true; - } - return false; - } - catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - public static Future getServer(Player player) { - return executor.submit(() -> { - try (Connection connection = DataSource.getConnection()) { - PreparedStatement stmt = connection.prepareStatement("SELECT * FROM PlayerServers WHERE UUID = ?"); - stmt.setString(1, player.getUniqueId().toString()); - ResultSet rs = stmt.executeQuery(); - if (rs.next()) { - return new Server() - .setServerId(rs.getString("ServerID")) - .setPort(rs.getInt("Port")) - .setPlayerName(rs.getString("PlayerName")) - .setNode(rs.getString("Node")); - } - return null; - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - }); - } - - public static Future> getServersInfo() { - return executor.submit(() -> { - try (Connection connection = DataSource.getConnection()) { - PreparedStatement stmt = connection.prepareStatement("SELECT * FROM PlayerServers"); - ResultSet rs = stmt.executeQuery(); - List servers = new ArrayList<>(); - while (rs.next()) { - servers.add(new Server() - .setServerId(rs.getString("ServerID")) - .setPort(rs.getInt("Port")) - .setPlayerName(rs.getString("PlayerName")) - .setNode(rs.getString("Node"))); - } - return servers; - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - }); - } - - public static String getPortByUUID(String UUID) { - try (Connection connection = DataSource.getConnection()) { - PreparedStatement stmt = connection.prepareStatement("SELECT * FROM PlayerServers WHERE UUID='" + UUID + "'"); - ResultSet rs = stmt.executeQuery(); rs.next(); - return rs.getString("Port"); - } - catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public static boolean containsServer(String UUID) { - try (Connection connection = DataSource.getConnection()) { - PreparedStatement stmt = connection.prepareStatement("SELECT * FROM PlayerServers"); - ResultSet rs = stmt.executeQuery(); - while(rs.next()) { - if (rs.getString("UUID").equals(UUID)) - return true; - } - return false; - } - catch (Exception e) { - e.printStackTrace(); - return false; - } - } -} \ No newline at end of file diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/database/DataSource.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/database/DataSource.java deleted file mode 100644 index 36fa291..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/database/DataSource.java +++ /dev/null @@ -1,43 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.database; - -import com.zaxxer.hikari.HikariDataSource; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; - -import java.sql.Connection; -import java.sql.SQLException; - -public class DataSource -{ - - public static HikariDataSource hikari; - - @SuppressWarnings("ConstantConditions") - public void registerDataSource() throws SQLException { - - final var pl = PSHubCore.getInstance(); - - final var address = pl.getConfig().getString("mysql.hostname"); - final var name = pl.getConfig().getString("mysql.database"); - final var username = pl.getConfig().getString("mysql.username"); - final var password = pl.getConfig().getString("mysql.password"); - final var useSSL = pl.getConfig().getBoolean("mysql.useSSL"); - - hikari = new HikariDataSource(); - hikari.setPoolName("PSHubCore"); - hikari.setMaximumPoolSize(10); - hikari.setLoginTimeout(10); - hikari.setConnectionTimeout(10000); - hikari.setDataSourceClassName("com.mysql.cj.jdbc.MysqlDataSource"); - hikari.addDataSourceProperty("serverName", address); - hikari.addDataSourceProperty("port", "3306"); - hikari.addDataSourceProperty("databaseName", name); - hikari.addDataSourceProperty("user", username); - hikari.addDataSourceProperty("password", password); - hikari.addDataSourceProperty("useSSL", useSSL); - } - - public static Connection getConnection() throws SQLException { - return hikari.getConnection(); - } - -} \ No newline at end of file diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/enums/PowerAction.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/enums/PowerAction.java new file mode 100644 index 0000000..92c88d3 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/enums/PowerAction.java @@ -0,0 +1,6 @@ +package os.arcadiadevs.playerservers.hubcore.enums; + +public enum PowerAction { + START, + STOP, +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/events/ClickEvent.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/events/ClickEvent.java index 08236c9..3713025 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/events/ClickEvent.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/events/ClickEvent.java @@ -9,69 +9,102 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; +import os.arcadiadevs.playerservers.hubcore.guis.SelectorGui; import os.arcadiadevs.playerservers.hubcore.utils.ChatUtil; -import os.arcadiadevs.playerservers.hubcore.utils.GUIUtils; +import os.arcadiadevs.playerservers.hubcore.guis.PlayerMenuGui; -public class ClickEvent implements Listener { +public class ClickEvent implements Listener { - @EventHandler - public void onClick(PlayerInteractEvent event) { - final PSHubCore PSH = PSHubCore.getInstance(); - final var player = event.getPlayer(); + private final PsHubCore instance; - if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) { - return; - } + public ClickEvent(PsHubCore instance) { + this.instance = instance; + } - if (PSH.getConfig().getBoolean("gui.selector.item.enabled") && player.getInventory().getHeldItemSlot() == PSHubCore.getInstance().getConfig().getInt("gui.selector.item.location")) { - if (!player.hasPermission("hubcore.selector")) { - player.sendMessage(ChatUtil.translate(PSH.getConfig().getString("messages.no-permission"))); - return; - } - GUIUtils.openSelector(player); - event.setCancelled(true); - } + /** + * Executes action on player interact event. + * + * @param event the event + */ + @EventHandler + public void onClick(PlayerInteractEvent event) { + final var player = event.getPlayer(); - if (PSH.getConfig().getBoolean("gui.player-menu.item.enabled") && player.getInventory().getHeldItemSlot() == PSHubCore.getInstance().getConfig().getInt("gui.player-menu.item.location")) { - if (!player.hasPermission("hubcore.player-menu")) { - player.sendMessage(ChatUtil.translate(PSH.getConfig().getString("messages.no-permission"))); - return; - } - GUIUtils.openMenu(player); - event.setCancelled(true); - } + if (event.getAction() != Action.RIGHT_CLICK_AIR + && event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; } - @EventHandler - public void inventory(InventoryClickEvent event) { - if (!(event.getWhoClicked() instanceof Player)) { - return; - } - - final var player = (Player) event.getWhoClicked(); - final var inventoryType = event.getInventory().getType(); - final var selectorItemSlot = PSHubCore.getInstance().getConfig().getInt("gui.selector.item.location"); - final var menuItemSlot = PSHubCore.getInstance().getConfig().getInt("gui.player-menu.item.location"); - - if (event.getSlot() == selectorItemSlot && (inventoryType == InventoryType.PLAYER || inventoryType == InventoryType.CRAFTING) - || event.getSlot() == menuItemSlot && (inventoryType == InventoryType.PLAYER || inventoryType == InventoryType.CRAFTING)) { - if (player.getGameMode() == GameMode.CREATIVE) { - player.closeInventory(); - } - - event.setCancelled(true); - } + if (instance.getConfig().getBoolean("gui.selector.item.enabled") + && player.getInventory().getHeldItemSlot() + == PsHubCore.getInstance().getConfig().getInt("gui.selector.item.location")) { + if (!player.hasPermission("hubcore.selector")) { + ChatUtil.sendMessage(player, instance.getConfig().getString("messages.no-permission")); + return; + } + SelectorGui.openGui(player); + event.setCancelled(true); } - @EventHandler - public void drop(PlayerDropItemEvent event) { - final var player = event.getPlayer(); + if (instance.getConfig().getBoolean("gui.player-menu.item.enabled") + && player.getInventory().getHeldItemSlot() + == PsHubCore.getInstance().getConfig().getInt("gui.player-menu.item.location")) { + if (!player.hasPermission("hubcore.player-menu")) { + ChatUtil.sendMessage(player, instance.getConfig().getString("messages.no-permission")); + return; + } - if (player.getInventory().getHeldItemSlot() == PSHubCore.getInstance().getConfig().getInt("gui.selector.item.location") || - player.getInventory().getHeldItemSlot() == PSHubCore.getInstance().getConfig().getInt("gui.player-menu.item.location")) { - event.setCancelled(true); - } + PlayerMenuGui.openGui(player); + event.setCancelled(true); } + } + + /** + * Prevents player from moving items in their inventory. + * + * @param event The event. + */ + @EventHandler + public void inventory(InventoryClickEvent event) { + if (!(event.getWhoClicked() instanceof final Player player)) { + return; + } + + final var inventoryType = event.getInventory().getType(); + final var selectorItemSlot = + PsHubCore.getInstance().getConfig().getInt("gui.selector.item.location"); + final var menuItemSlot = + PsHubCore.getInstance().getConfig().getInt("gui.player-menu.item.location"); + + if (event.getSlot() == selectorItemSlot + && (inventoryType == InventoryType.PLAYER || inventoryType == InventoryType.CRAFTING) + || event.getSlot() == menuItemSlot + && (inventoryType == InventoryType.PLAYER || inventoryType == InventoryType.CRAFTING)) { + if (player.getGameMode() == GameMode.CREATIVE) { + player.closeInventory(); + } + + event.setCancelled(true); + } + } + + /** + * Prevents players from dropping the selector item. + * + * @param event The event. + */ + @EventHandler + public void drop(PlayerDropItemEvent event) { + final var player = event.getPlayer(); + + if (player.getInventory().getHeldItemSlot() + == PsHubCore.getInstance().getConfig().getInt("gui.selector.item.location") + || player.getInventory().getHeldItemSlot() + == PsHubCore.getInstance().getConfig().getInt("gui.player-menu.item.location") + ) { + event.setCancelled(true); + } + } } diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/events/HubEvents.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/events/HubEvents.java index cca22ca..146dac3 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/events/HubEvents.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/events/HubEvents.java @@ -1,25 +1,34 @@ package os.arcadiadevs.playerservers.hubcore.events; +import org.bukkit.configuration.Configuration; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.weather.WeatherChangeEvent; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; public class HubEvents implements Listener { - @EventHandler - public void weatherChange(WeatherChangeEvent e) { - if (PSHubCore.getInstance().getConfig().getBoolean("miscellaneous.disable-weather")) { - e.setCancelled(true); - } - } + private final Configuration config; - @EventHandler - public void entityDamage(EntityDamageEvent e) { - if (e.getEntity() instanceof Player && PSHubCore.getInstance().getConfig().getBoolean("miscellaneous.disable-damage")) - e.setCancelled(true); + public HubEvents(FileConfiguration config) { + this.config = config; + } + + @EventHandler + public void weatherChange(WeatherChangeEvent e) { + if (config.getBoolean("miscellaneous.disable-weather")) { + e.setCancelled(true); } + } + + @EventHandler + public void entityDamage(EntityDamageEvent e) { + if (e.getEntity() instanceof Player && config.getBoolean("miscellaneous.disable-damage")) { + e.setCancelled(true); + } + } } diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/events/JoinEvent.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/events/JoinEvent.java index 36c7b51..322d193 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/events/JoinEvent.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/events/JoinEvent.java @@ -6,73 +6,83 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.ItemStack; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; -import os.arcadiadevs.playerservers.hubcore.utils.ChatUtil; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; import java.util.ArrayList; import java.util.List; +import os.arcadiadevs.playerservers.hubcore.utils.ChatUtil; public class JoinEvent implements Listener { - final PSHubCore PSH = PSHubCore.getInstance(); + private final PsHubCore instance; - @EventHandler - public void onJoin(PlayerJoinEvent e) { + public JoinEvent(PsHubCore instance) { + this.instance = instance; + } - final var selectorConfigMaterial = PSH.getConfig().getString("gui.selector.item.material"); - final var menuConfigMaterial = PSH.getConfig().getString("gui.player-menu.item.material"); - final var selectorMaterial = XMaterial.matchXMaterial(selectorConfigMaterial).orElse(XMaterial.COMPASS).parseMaterial(); - final var menuMaterial = XMaterial.matchXMaterial(menuConfigMaterial).orElse(XMaterial.EMERALD).parseMaterial(); - final var player = e.getPlayer(); - - if (!PSH.getConfig().getBoolean("gui.selector.item.enabled")) { - player.getInventory().forEach(item -> { - if (item != null && item.getType() == selectorMaterial) { - player.getInventory().remove(item); - } - }); + @EventHandler + public void onJoin(PlayerJoinEvent e) { + + final var selectorConfigMaterial = instance.getConfig().getString("gui.selector.item.material"); + final var menuConfigMaterial = instance.getConfig().getString("gui.player-menu.item.material"); + final var selectorMaterial = + XMaterial.matchXMaterial(selectorConfigMaterial).orElse(XMaterial.COMPASS).parseMaterial(); + final var menuMaterial = + XMaterial.matchXMaterial(menuConfigMaterial).orElse(XMaterial.EMERALD).parseMaterial(); + final var player = e.getPlayer(); + + if (!instance.getConfig().getBoolean("gui.selector.item.enabled")) { + player.getInventory().forEach(item -> { + if (item != null && item.getType() == selectorMaterial) { + player.getInventory().remove(item); } - - if (!PSH.getConfig().getBoolean("gui.player-menu.item.enabled")) { - player.getInventory().forEach(item -> { - if (item != null && item.getType() == menuMaterial) { - player.getInventory().remove(item); - } - }); - } - - new Thread(() -> { - final var selectorItemStack = new ItemStack(selectorMaterial); - final var menuItemStack = new ItemStack(menuMaterial); - final var selectorItemMeta = selectorItemStack.getItemMeta(); - final var menuItemMeta = menuItemStack.getItemMeta(); - - selectorItemMeta.setDisplayName(ChatUtil.translate(PSH.getConfig().getString("gui.selector.item.name"))); - menuItemMeta.setDisplayName(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.item.name"))); - - final List lore = PSH.getConfig().getStringList("gui.selector.item.description") - .stream() - .map(ChatUtil::translate) - .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); - - final List lore1 = PSH.getConfig().getStringList("gui.player-menu.item.description") - .stream() - .map(ChatUtil::translate) - .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); - - selectorItemMeta.setLore(lore); - menuItemMeta.setLore(lore1); - selectorItemStack.setItemMeta(selectorItemMeta); - menuItemStack.setItemMeta(menuItemMeta); - - if (PSH.getConfig().getBoolean("gui.selector.item.enabled")) { - Bukkit.getScheduler().runTask(PSH, () -> player.getInventory().setItem(PSH.getConfig().getInt("gui.selector.item.location"), selectorItemStack)); - } - - if (PSH.getConfig().getBoolean("gui.player-menu.item.enabled")) { - Bukkit.getScheduler().runTask(PSH, () -> player.getInventory().setItem(PSH.getConfig().getInt("gui.player-menu.item.location"), menuItemStack)); - } - }).start(); - + }); } + + if (!instance.getConfig().getBoolean("gui.player-menu.item.enabled")) { + player.getInventory().forEach(item -> { + if (item != null && item.getType() == menuMaterial) { + player.getInventory().remove(item); + } + }); + } + + new Thread(() -> { + final var selectorItemStack = new ItemStack(selectorMaterial); + final var menuItemStack = new ItemStack(menuMaterial); + final var selectorItemMeta = selectorItemStack.getItemMeta(); + final var menuItemMeta = menuItemStack.getItemMeta(); + + selectorItemMeta.setDisplayName( + ChatUtil.translate(instance.getConfig().getString("gui.selector.item.name"))); + menuItemMeta.setDisplayName( + ChatUtil.translate(instance.getConfig().getString("gui.player-menu.item.name"))); + + final List lore = instance.getConfig().getStringList("gui.selector.item.description") + .stream() + .map(ChatUtil::translate) + .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + + final List lore1 = instance.getConfig().getStringList("gui.player-menu.item.description") + .stream() + .map(ChatUtil::translate) + .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + + selectorItemMeta.setLore(lore); + menuItemMeta.setLore(lore1); + selectorItemStack.setItemMeta(selectorItemMeta); + menuItemStack.setItemMeta(menuItemMeta); + + if (instance.getConfig().getBoolean("gui.selector.item.enabled")) { + Bukkit.getScheduler().runTask(instance, () -> player.getInventory() + .setItem(instance.getConfig().getInt("gui.selector.item.location"), selectorItemStack)); + } + + if (instance.getConfig().getBoolean("gui.player-menu.item.enabled")) { + Bukkit.getScheduler().runTask(instance, () -> player.getInventory() + .setItem(instance.getConfig().getInt("gui.player-menu.item.location"), menuItemStack)); + } + }).start(); + + } } diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/guis/PlayerMenuGui.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/guis/PlayerMenuGui.java new file mode 100644 index 0000000..b47fa46 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/guis/PlayerMenuGui.java @@ -0,0 +1,227 @@ +package os.arcadiadevs.playerservers.hubcore.guis; + +import com.cryptomorin.xseries.XMaterial; +import com.cryptomorin.xseries.XSound; +import com.samjakob.spigui.buttons.SGButton; +import com.samjakob.spigui.item.ItemBuilder; +import java.util.ArrayList; +import org.bukkit.entity.Player; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; +import os.arcadiadevs.playerservers.hubcore.enums.PowerAction; +import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; +import os.arcadiadevs.playerservers.hubcore.models.Server; +import os.arcadiadevs.playerservers.hubcore.utils.BungeeUtil; +import os.arcadiadevs.playerservers.hubcore.utils.ChatUtil; +import os.arcadiadevs.playerservers.hubcore.utils.GuiUtils; + +public class PlayerMenuGui { + + public static void openGui(Player player) { + final var instance = PsHubCore.getInstance(); + final var serversController = instance.getServersController(); + + if (!serversController.hasServer(player)) { + final var menu = instance.getSpiGui().create( + ChatUtil.translate(instance.getConfig().getString("gui.player-menu.menu.name")), 3); + + menu.setAutomaticPaginationEnabled(false); + menu.setBlockDefaultInteractions(true); + + for (int i = 0; i < 9 * 4; i++) { + menu.setButton( + i, + new SGButton(new ItemBuilder(XMaterial.GRAY_STAINED_GLASS_PANE.parseItem()).build()) + ); + } + + var itemCreate = new ItemBuilder(XMaterial.DIAMOND_BLOCK.parseMaterial()) + .name(instance.getConfig().getString("gui.player-menu.menu.create.name")) + .lore(instance.getConfig().getStringList("gui.player-menu.menu.create.lore")) + .build(); + + menu.setButton(0, 13, new SGButton(itemCreate).withListener( + listener -> { + BungeeUtil.createServer(player); + XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(player); + })); + + player.openInventory(menu.getInventory()); + return; + } + + final var rows = 5; + final var menu = instance.getSpiGui() + .create(ChatUtil.translate(instance.getConfig().getString("gui.player-menu.menu.name")), + rows); + menu.setAutomaticPaginationEnabled(false); + menu.setBlockDefaultInteractions(true); + + GuiUtils.addBorder(menu, rows); + + final var server = serversController.getServer(player); + + if (server == null) { + player.sendMessage(ChatUtil.translate("&9Error> &cCould not find your server!")); + return; + } + + final var online = server.getStatus() == ServerStatus.ONLINE; + + var lore = instance.getConfig().getStringList(online + ? "gui.player-menu.menu.info.online.lore" + : "gui.player-menu.menu.info.offline.lore" + ); + + lore = lore.stream() + .map(s -> s.replaceAll("%server%", server.getId())) + .map(s -> s.replaceAll("%status%", online ? "&aOnline" : "&cOffline")) + .map(s -> s.replaceAll("%players%", online ? server.getInfo().players() + "" : "0")) + .map(s -> s.replaceAll("%maxplayers%", online ? server.getInfo().maxPlayers() + "" : "0")) + .map(s -> s.replaceAll("%port%", server.getPort() + "")) + .map(s -> s.replaceAll("%motd%", online ? server.getInfo().motd() : "&cOffline")) + .map(s -> s.replaceAll("%node%", server.getNode().getName())) + .map(s -> s.replaceAll("%owner%", server.getOfflinePlayer().getName())) + .map(s -> s.replaceAll("%ip%", server.getNode().getIp())) + .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + + final var itemPlayer = new SGButton( + new ItemBuilder(XMaterial.PLAYER_HEAD.parseMaterial()) + .name(ChatUtil.translate(instance.getConfig().getString(online + ? "gui.player-menu.menu.info.online.name" + : "gui.player-menu.menu.info.offline.name") + .replaceAll("%server%", server.getId()))) + .skullOwner(player.getName()) + .lore(lore) + .build() + ); + + final var itemDelete = new SGButton(new ItemBuilder(XMaterial.BARRIER.parseMaterial()) + .name(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.delete.name"))) + .lore(instance.getConfig().getStringList("gui.player-menu.menu.delete.lore")) + .build()) + .withListener(listener -> openDeleteConfirmation(player, server)); + + if (online) { + final var itemJoin = new SGButton(new ItemBuilder(XMaterial.DARK_OAK_DOOR.parseItem()) + .name(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.join.name"))) + .lore(instance.getConfig().getStringList("gui.player-menu.menu.join.lore")) + .build()) + .withListener(listener -> server.connect()); + + final var itemStop = new SGButton(new ItemBuilder(XMaterial.RED_TERRACOTTA.parseItem()) + .name(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.stop.name"))) + .lore(instance.getConfig().getStringList("gui.player-menu.menu.stop.lore")) + .build()) + .withListener(listener -> openStopConfirmation(player, server)); + + menu.setButton(22, itemJoin); + menu.setButton(20, itemStop); + } + + if (!online) { + final var itemStart = new SGButton(new ItemBuilder(XMaterial.GREEN_TERRACOTTA.parseItem()) + .name(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.start.name"))) + .lore(instance.getConfig().getStringList("gui.player-menu.menu.start.lore")) + .build()) + .withListener(listener -> server.executePowerAction(PowerAction.START)); + + menu.setButton(20, itemStart); + } + + menu.setButton(0, 24, itemDelete); + + menu.setButton(0, 4, itemPlayer); + + XSound.BLOCK_NOTE_BLOCK_BASS.play(player); + player.openInventory(menu.getInventory()); + } + + public static void openDeleteConfirmation(Player player, Server server) { + XSound.BLOCK_NOTE_BLOCK_BASS.play(player); + final var instance = PsHubCore.getInstance(); + + final var deleteConfirmationMenu = instance.getSpiGui().create(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.delete.confirmation.name")), 3); + + deleteConfirmationMenu.setAutomaticPaginationEnabled(false); + deleteConfirmationMenu.setBlockDefaultInteractions(true); + + final var yesButton = new SGButton(new ItemBuilder(XMaterial.GREEN_TERRACOTTA.parseItem()) + .name(ChatUtil.translate( + instance.getConfig() + .getString("gui.player-menu.menu.delete.confirmation.accept.name"))) + .lore( + instance.getConfig() + .getStringList("gui.player-menu.menu.delete.confirmation.accept.lore")) + .build()) + .withListener(listener2 -> { + XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(player); + server.delete(); + player.closeInventory(); + }); + + final var noButton = new SGButton(new ItemBuilder(XMaterial.RED_TERRACOTTA.parseItem()) + .name(ChatUtil.translate( + instance.getConfig() + .getString("gui.player-menu.menu.delete.confirmation.decline.name"))) + .lore(instance.getConfig() + .getStringList("gui.player-menu.menu.delete.confirmation.decline.lore")) + .build()) + .withListener(listener -> { + player.closeInventory(); + XSound.BLOCK_NOTE_BLOCK_BASS.play(player); + }); + + deleteConfirmationMenu.setButton(0, 11, yesButton); + + deleteConfirmationMenu.setButton(0, 15, noButton); + + player.openInventory(deleteConfirmationMenu.getInventory()); + } + + public static void openStopConfirmation(Player player, Server server) { + final var instance = PsHubCore.getInstance(); + + final var stopConfirmationMenu = instance.getSpiGui().create(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.stop.confirmation.name")), 3); + + stopConfirmationMenu.setAutomaticPaginationEnabled(false); + stopConfirmationMenu.setBlockDefaultInteractions(true); + + final var yesButton = new SGButton(new ItemBuilder(XMaterial.GREEN_TERRACOTTA.parseItem()) + .name(ChatUtil.translate( + instance.getConfig().getString("gui.player-menu.menu.stop.confirmation.accept.name"))) + .lore(instance.getConfig() + .getStringList("gui.player-menu.menu.stop.confirmation.accept.lore")) + .build()) + .withListener(listener2 -> { + XSound.ENTITY_EXPERIENCE_ORB_PICKUP.play(player); + server.executePowerAction(PowerAction.STOP); + player.closeInventory(); + }); + + final var noButton = new SGButton(new ItemBuilder(XMaterial.RED_TERRACOTTA.parseItem()) + .name(ChatUtil.translate( + instance.getConfig() + .getString("gui.player-menu.menu.stop.confirmation.decline.name"))) + .lore( + instance.getConfig() + .getStringList("gui.player-menu.menu.stop.confirmation.decline.lore")) + .build()) + .withListener(listener -> { + XSound.BLOCK_NOTE_BLOCK_BASS.play(player); + player.closeInventory(); + }); + + stopConfirmationMenu.setButton(0, 11, yesButton); + + stopConfirmationMenu.setButton(0, 15, noButton); + + player.openInventory(stopConfirmationMenu.getInventory()); + } + +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/guis/SelectorGui.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/guis/SelectorGui.java new file mode 100644 index 0000000..7845102 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/guis/SelectorGui.java @@ -0,0 +1,80 @@ +package os.arcadiadevs.playerservers.hubcore.guis; + +import com.cryptomorin.xseries.XMaterial; +import com.samjakob.spigui.buttons.SGButton; +import com.samjakob.spigui.item.ItemBuilder; +import java.util.ArrayList; +import org.bukkit.entity.Player; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; +import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; +import os.arcadiadevs.playerservers.hubcore.utils.BungeeUtil; +import os.arcadiadevs.playerservers.hubcore.utils.ChatUtil; + +public class SelectorGui { + + public static void openGui(Player player) { + + final var instance = PsHubCore.getInstance(); + final var menu = instance.getSpiGui() + .create(ChatUtil.translate(instance.getConfig().getString("gui.selector.menu.name")), 5); + + menu.setAutomaticPaginationEnabled(true); + menu.setBlockDefaultInteractions(true); + + final var onlinexMaterial = + XMaterial.matchXMaterial(instance.getConfig().getString("gui.selector.menu.online.block")) + .orElse(XMaterial.PLAYER_HEAD).parseMaterial(); + final var offlinexMaterial = + XMaterial.matchXMaterial(instance.getConfig().getString("gui.selector.menu.offline.block")) + .orElse(XMaterial.RED_TERRACOTTA).parseMaterial(); + + final var servers = PsHubCore.getInstance() + .getServersController() + .getServers(); + + servers.forEach(server -> { + final var itemBuilder = new ItemBuilder( + server.getStatus() == ServerStatus.ONLINE ? onlinexMaterial : offlinexMaterial); + final var online = server.getStatus() == ServerStatus.ONLINE; + + var lore = instance.getConfig().getStringList( + server.getStatus() == ServerStatus.ONLINE ? "gui.selector.menu.online.lore" : + "gui.selector.menu.offline.lore"); + + lore = lore.stream() + .map(s -> s.replaceAll("%server%", server.getId())) + .map(s -> s.replaceAll("%status%", online ? "&aOnline" : "&cOffline")) + .map(s -> s.replaceAll("%players%", online ? server.getInfo().players() + "" : "0")) + .map(s -> s.replaceAll("%maxplayers%", online ? server.getInfo().maxPlayers() + "" : "0")) + .map(s -> s.replaceAll("%port%", server.getPort() + "")) + .map(s -> s.replaceAll("%motd%", online ? server.getInfo().motd() : "&cOffline")) + .map(s -> s.replaceAll("%node%", server.getNode().getName())) + .map(s -> s.replaceAll("%owner%", server.getOfflinePlayer().getName())) + .map(s -> s.replaceAll("%ip%", server.getNode().getIp())) + .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + + var item = itemBuilder + .name(ChatUtil.translate(instance.getConfig().getString( + online ? "gui.selector.menu.online.name" : "gui.selector.menu.offline.name") + .replaceAll("%server%", server.getId()) + .replaceAll("%status%", online ? "&aOnline" : "&cOffline") + .replaceAll("%players%", online ? server.getInfo().players() + "" : "0") + .replaceAll("%maxplayers%", online ? server.getInfo().maxPlayers() + "" : "0") + .replaceAll("%port%", server.getPort() + "") + .replaceAll("%motd%", online ? server.getInfo().motd() : "&cOffline") + .replaceAll("%node%", server.getNode().getName()) + .replaceAll("%owner%", server.getOfflinePlayer().getName()) + .replaceAll("%ip%", server.getNode().getIp()) + )) + .lore(lore) + .build(); + + menu.setButton(0, menu.getInventory().firstEmpty(), new SGButton(item).withListener( + listener -> BungeeUtil.connectPlayer(player))); + }); + + player.openInventory(menu.getInventory()); + + } + +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/models/Node.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/models/Node.java new file mode 100644 index 0000000..26770c9 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/models/Node.java @@ -0,0 +1,79 @@ +package os.arcadiadevs.playerservers.hubcore.models; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.net.InetSocketAddress; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +/** + * The node object. + * + * @author ArcadiaDevs + */ +@Entity +@Table(name = "nodes") +@Getter +@Setter +public class Node { + + @Id + @Column(name = "id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + + @Column(name = "name") + private String name; + + @Column(name = "ip") + private String ip; + + @Column(name = "port") + private int port; + + @Column(name = "min_port") + private int minPort; + + @Column(name = "max_port") + private int maxPort; + + @Column(name = "max_servers") + private short maxServers; + + @Column(name = "token") + private String token; + + @Column(name = "servers") + @OneToMany(mappedBy = "node", fetch = FetchType.EAGER) + private List servers; + + /** + * Get the full address of the server as ip:port. + * + * @return The full address + */ + public String getFullAddress() { + return this.ip + ":" + this.port; + } + + /** + * Get the address of the node as InetSocketAddress. + * + * @return The address + */ + public InetSocketAddress getInetAddress() { + return new InetSocketAddress(this.ip, this.port); + } + + public String getNumericAddress() { + return getIp().replaceAll("localhost", "127.0.0.1"); + } + +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/models/Server.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/models/Server.java new file mode 100644 index 0000000..2b13c6b --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/models/Server.java @@ -0,0 +1,140 @@ +package os.arcadiadevs.playerservers.hubcore.models; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import os.arcadiadevs.playerservers.hubcore.enums.PowerAction; +import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; +import os.arcadiadevs.playerservers.hubcore.utils.BungeeUtil; +import os.arcadiadevs.playerservers.hubcore.utils.ServerPinger; + +/** + * The model of a server. + * + * @author ArcadiaDevs + */ +@Entity +@Table(name = "servers") +@Getter +@Setter +public class Server { + + @Id + @Column(name = "id") + private String id; + + @Column(name = "owner") + private UUID owner; + + @Column(name = "port") + private Integer port; + + @ManyToOne + @JoinColumn(name = "node", nullable = false) + private Node node; + + public String getFullAddress() { + return (this.node.getIp() + ":" + this.port) + .replaceAll("localhost", "127.0.0.1"); + } + + /** + * Gets the owner of the server as a OfflinePlayer. + * + * @return The owner of the server + */ + public OfflinePlayer getOfflinePlayer() { + return Bukkit.getOfflinePlayer(owner); + } + + /** + * Gets the owner of the server as a player. + * + * @return The owner of the server + */ + public Player getPlayer() { + return Bukkit.getPlayer(owner); + } + + public void connect() { + BungeeUtil.connectPlayer(getPlayer()); + } + + /** + * Gets the InetSocketAddress of the server. + * + * @return The InetSocketAddress + */ + public InetSocketAddress getInetAddress() { + return new InetSocketAddress(this.node.getIp(), this.port); + } + + /** + * Gets the status of the server. + * + * @return The status of the server + */ + public ServerStatus getStatus() { + final var address = node.getNumericAddress(); + + var status = ServerStatus.UNKNOWN; + try { + Socket s = new Socket(address, port); + if (s.isConnected()) { + status = ServerStatus.ONLINE; + } + s.close(); + } catch (IOException ignored) { + status = ServerStatus.OFFLINE; + } + + return status; + } + + /** + * Gets the MOTD and player count of the server. + * + * @return The status of the server + */ + public ServerPinger.PingResult getInfo() { + try { + return ServerPinger.ping(this.getInetAddress(), 1000).get(); + } catch (InterruptedException | ExecutionException e) { + return null; + } + } + + /** + * Execute a power action on the server. + * + * @param action The action to execute + */ + public void executePowerAction(PowerAction action) { + switch (action) { + case START -> BungeeUtil.startServer(getPlayer()); + case STOP -> BungeeUtil.stopServer(getPlayer()); + default -> throw new IllegalStateException("Unexpected value: " + action); + } + } + + /** + * Deletes the server. + */ + public void delete() { + BungeeUtil.deleteServer(getPlayer()); + } + +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/Node.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/Node.java deleted file mode 100644 index a794cb9..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/Node.java +++ /dev/null @@ -1,36 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.objects; - -import lombok.Getter; - -@Getter -public class Node { - - private String name; - private String hostname; - private String token; - private int port; - - public String getFullAddress() { - return hostname + ":" + port; - } - - public Node setName(String name) { - this.name = name; - return this; - } - - public Node setHostname(String hostname) { - this.hostname = hostname; - return this; - } - - public Node setToken(String token) { - this.token = token; - return this; - } - - public Node setPort(int port) { - this.port = port; - return this; - } -} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/PingInfoStructure.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/PingInfoStructure.java deleted file mode 100644 index 372eb59..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/PingInfoStructure.java +++ /dev/null @@ -1,26 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.objects; - -public class PingInfoStructure { - - private final int online; - private final int max; - private final String MOTD; - - public PingInfoStructure(int online, int max, String MOTD) { - this.online = online; - this.max = max; - this.MOTD = MOTD; - } - - public int getMax() { - return max; - } - - public int getOnline() { - return online; - } - - public String getMOTD() { - return MOTD; - } -} \ No newline at end of file diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/Server.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/Server.java deleted file mode 100644 index 7f14976..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/Server.java +++ /dev/null @@ -1,137 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.objects; - -import lombok.Getter; -import lombok.Setter; -import lombok.SneakyThrows; -import org.bukkit.entity.Player; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; -import os.arcadiadevs.playerservers.hubcore.database.DataBase; -import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.Socket; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.atomic.AtomicBoolean; - -@Getter -public class Server { - - private String serverId; - private String playerName; - private String node; - private Integer port; - - @Setter private PingInfoStructure cachedData; - @Setter private ServerStatus cachedStatus; - - public String getShortId() { - return serverId.split("-")[0]; - } - - public Server() {} - - @SneakyThrows - public Server(Player player) { - final var server = DataBase.getServer(player).get(); - this.serverId = server.getServerId(); - this.playerName = server.getPlayerName(); - this.node = server.getNode(); - this.port = server.getPort(); - } - - @SuppressWarnings("ResultOfMethodCallIgnored") - public ServerStatus getServerStatus() { - AtomicBoolean isOnline = new AtomicBoolean(false); - - ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1); - - executor.execute(() -> { - try { - Socket socket = new Socket(getHostname(), port); - isOnline.set(true); - socket.close(); - } catch (IOException e) { - isOnline.set(false); - } - }); - - try { - Thread.sleep(200); - executor.shutdown(); - executor.awaitTermination(1, java.util.concurrent.TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - return isOnline.get() ? ServerStatus.ONLINE : ServerStatus.OFFLINE; - - } - - public Node getNodeObject() { - final var config = PSHubCore - .getInstance() - .getMultinode() - .getConfigurationSection("nodes." + this.node); - - return new Node() - .setName(this.node) - .setHostname(config.getString("host")) - .setToken(config.getString("token")) - .setPort(config.getInt("port")); - } - - public PingInfoStructure getData() { - try (Socket sock = new Socket(getHostname(), port)) { - DataOutputStream out = new DataOutputStream(sock.getOutputStream()); - DataInputStream in = new DataInputStream(sock.getInputStream()); - - out.write(0xFE); - - int b; - StringBuilder str = new StringBuilder(); - while ((b = in.read()) != -1) { - if (b > 16 && b != 255 && b != 23 && b != 24) { - str.append((char) b); - } - } - - String[] data = str.toString().split("§"); - String serverMotd = data[0]; - int onlinePlayers = Integer.parseInt(data[1]); - int maxPlayers = Integer.parseInt(data[2]); - - return new PingInfoStructure(onlinePlayers, maxPlayers, serverMotd); - - } catch (IOException e) { - return null; - } - } - - public String getHostname() { - return node.equalsIgnoreCase("local") ? "localhost" : getNodeObject().getHostname(); - } - - public Server setServerId(String serverId) { - this.serverId = serverId; - return this; - } - - public Server setPlayerName(String playerName) { - this.playerName = playerName; - return this; - } - - public Server setNode(String node) { - this.node = node; - return this; - } - - public Server setPort(int port) { - this.port = port; - return this; - } - -} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/ServerCache.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/ServerCache.java deleted file mode 100644 index 9ebf527..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/objects/ServerCache.java +++ /dev/null @@ -1,48 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.objects; - -import lombok.Getter; -import lombok.Setter; -import os.arcadiadevs.playerservers.hubcore.database.DataBase; -import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; - -import java.util.List; -import java.util.concurrent.ExecutionException; - -public class ServerCache implements Runnable { - - @Getter @Setter - private List servers; - - @Override - public void run() { - final List servers; - - try { - servers = DataBase.getServersInfo().get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - return; - } - - servers.forEach(server -> { - server.setCachedData(server.getData()); - server.setCachedStatus(server.getServerStatus()); - }); - - servers.sort((s1, s2) -> { - final var p1 = s1.getServerStatus() == ServerStatus.ONLINE; - final var p2 = s2.getServerStatus() == ServerStatus.ONLINE; - - if (p1 && !p2) { - return -1; - } else if (!p1 && p2) { - return 1; - } else { - return 0; - } - }); - - setServers(servers); - } - -} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/placeholders/PlayerCount.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/placeholders/PlayerCount.java index e391221..49f0ab0 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/placeholders/PlayerCount.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/placeholders/PlayerCount.java @@ -3,62 +3,59 @@ package os.arcadiadevs.playerservers.hubcore.placeholders; import lombok.SneakyThrows; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.OfflinePlayer; -import org.bukkit.plugin.Plugin; -import os.arcadiadevs.playerservers.hubcore.database.DataBase; +import os.arcadiadevs.playerservers.hubcore.controllers.ServersController; import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; -import os.arcadiadevs.playerservers.hubcore.objects.Server; public class PlayerCount extends PlaceholderExpansion { - Plugin plugin; + private final ServersController controller; - public PlayerCount(Plugin plugin){ - this.plugin = plugin; - } + public PlayerCount(ServersController controller) { + this.controller = controller; + } - @Override - public boolean canRegister() { - return true; - } + @Override + public boolean canRegister() { + return true; + } - @Override - public String getIdentifier() { - return "playerservers"; - } + @Override + public String getIdentifier() { + return "playerservers"; + } - @Override - public String getName() { - return "placeholders"; - } + @Override + public String getName() { + return "placeholders"; + } - @Override - public String getAuthor() { - return "OpenSource/Cuftica"; - } + @Override + public String getAuthor() { + return "OpenSource/Cuftica"; + } - @Override - public String getVersion() { - return "1.0.0"; - } + @Override + public String getVersion() { + return "1.0.0"; + } - @SneakyThrows - @Override - public String onRequest(OfflinePlayer p, String params) { - switch (params) { - case "online": - final var server = new Server(p.getPlayer()); - return server.getServerStatus() == ServerStatus.ONLINE ? "Online" : "Offline"; - case "serveronline": - final var online = (int) DataBase - .getServersInfo() - .get() - .stream() - .filter(_server -> _server.getServerStatus() == ServerStatus.ONLINE) - .count(); + @SneakyThrows + @Override + public String onRequest(OfflinePlayer player, String params) { + return switch (params) { + case "online" -> { + final var server = controller.getServer(player.getUniqueId()); + yield server.getStatus() == ServerStatus.ONLINE ? "Online" : "Offline"; + } + case "serveronline" -> { + final var online = (int) controller.getServers() + .stream() + .filter(server -> server.getStatus() == ServerStatus.ONLINE) + .count(); - return String.valueOf(online); - } - - return null; - } + yield String.valueOf(online); + } + default -> throw new IllegalArgumentException("Invalid placeholder: " + params); + }; + } } diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/BungeeUtil.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/BungeeUtil.java index 59621c3..46e3546 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/BungeeUtil.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/BungeeUtil.java @@ -5,82 +5,70 @@ import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; +import os.arcadiadevs.playerservers.hubcore.PsHubCore; @SuppressWarnings("UnstableApiUsage") public class BungeeUtil { - public static void connectPlayer(InventoryClickEvent event, Player player, String server) { - if (event.getCurrentItem().getType() == XMaterial.REDSTONE_BLOCK.parseMaterial()) { - player.sendMessage(ChatUtil.translate("&9PlayerServers> &7Oops, the server you tried to connect to is offline.")); - return; - } + public static void connectPlayer(Player player) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - - try { - out.writeUTF("Connect"); - out.writeUTF(server); - } catch (Exception e) { - e.printStackTrace(); - } - - player.sendPluginMessage(PSHubCore.getInstance(), "BungeeCord", out.toByteArray()); - event.getWhoClicked().closeInventory(); + try { + out.writeUTF("Connect"); + } catch (Exception e) { + e.printStackTrace(); } - public static void stopServer(InventoryClickEvent event, Player player, String server) { + player.sendPluginMessage(PsHubCore.getInstance(), "BungeeCord", out.toByteArray()); + player.closeInventory(); + } - ByteArrayDataOutput out = ByteStreams.newDataOutput(); + public static void stopServer(Player player) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); - try { - out.writeUTF("stop"); - out.writeUTF(server); - } catch (Exception e) { - e.printStackTrace(); - } - player.sendPluginMessage(PSHubCore.getInstance(), "BungeeCord", out.toByteArray()); - event.getWhoClicked().closeInventory(); + try { + out.writeUTF("stop"); + } catch (Exception e) { + e.printStackTrace(); } + player.sendPluginMessage(PsHubCore.getInstance(), "BungeeCord", out.toByteArray()); + player.closeInventory(); + } - public static void deleteServer(InventoryClickEvent event, Player player, String server) { + public static void deleteServer(Player player) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - - try { - out.writeUTF("delete"); - out.writeUTF(server); - } catch (Exception e) { - e.printStackTrace(); - } - player.sendPluginMessage(PSHubCore.getInstance(), "BungeeCord", out.toByteArray()); - event.getWhoClicked().closeInventory(); + try { + out.writeUTF("delete"); + } catch (Exception e) { + e.printStackTrace(); } + player.sendPluginMessage(PsHubCore.getInstance(), "BungeeCord", out.toByteArray()); + player.closeInventory(); + } - public static void createServer(InventoryClickEvent event, Player player, String server) { - ByteArrayDataOutput out = ByteStreams.newDataOutput(); + public static void createServer(Player player) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); - try { - out.writeUTF("create"); - out.writeUTF(server); - } catch (Exception e) { - e.printStackTrace(); - } - player.sendPluginMessage(PSHubCore.getInstance(), "BungeeCord", out.toByteArray()); - event.getWhoClicked().closeInventory(); + try { + out.writeUTF("create"); + } catch (Exception e) { + e.printStackTrace(); } + player.sendPluginMessage(PsHubCore.getInstance(), "BungeeCord", out.toByteArray()); + player.closeInventory(); + } - public static void startServer(InventoryClickEvent event, Player player, String server) { - ByteArrayDataOutput out = ByteStreams.newDataOutput(); + public static void startServer(Player player) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); - try { - out.writeUTF("start"); - out.writeUTF(server); - } catch (Exception e) { - e.printStackTrace(); - } - player.sendPluginMessage(PSHubCore.getInstance(), "BungeeCord", out.toByteArray()); - event.getWhoClicked().closeInventory(); + try { + out.writeUTF("start"); + } catch (Exception e) { + e.printStackTrace(); } + player.sendPluginMessage(PsHubCore.getInstance(), "BungeeCord", out.toByteArray()); + player.closeInventory(); + } } \ No newline at end of file diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ChatUtil.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ChatUtil.java index 30b40ff..81bf5f5 100644 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ChatUtil.java +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ChatUtil.java @@ -1,11 +1,22 @@ package os.arcadiadevs.playerservers.hubcore.utils; import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; public class ChatUtil { - public static String translate(String text) { - return ChatColor.translateAlternateColorCodes('&', text); + public static String translate(String s) { + return ChatColor.translateAlternateColorCodes('&', s); + } + + public static void sendMessage(CommandSender sender, String message) { + sender.sendMessage(translate(message)); + } + + public static void sendMessage(CommandSender sender, String... message) { + for (String s : message) { + sender.sendMessage(translate(s)); } + } } diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/GUIUtils.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/GUIUtils.java deleted file mode 100644 index 90d9e30..0000000 --- a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/GUIUtils.java +++ /dev/null @@ -1,238 +0,0 @@ -package os.arcadiadevs.playerservers.hubcore.utils; - -import com.cryptomorin.xseries.XMaterial; -import com.samjakob.spigui.buttons.SGButton; -import com.samjakob.spigui.item.ItemBuilder; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import os.arcadiadevs.playerservers.hubcore.PSHubCore; -import os.arcadiadevs.playerservers.hubcore.database.DataBase; -import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; - -import java.util.ArrayList; - -public class GUIUtils { - - public static void openSelector(Player player) { - - final var PSH = PSHubCore.getInstance(); - final var menu = PSH.getSpiGUI().create(ChatUtil.translate(PSH.getConfig().getString("gui.selector.menu.name")), 5); - - menu.setAutomaticPaginationEnabled(true); - menu.setBlockDefaultInteractions(true); - - final var onlineXMaterialOptional = XMaterial.matchXMaterial(PSH.getConfig().getString("gui.selector.menu.online.block")); - final var offlineXMaterialOptional = XMaterial.matchXMaterial(PSH.getConfig().getString("gui.selector.menu.offline.block")); - - final var onlineXMaterial = onlineXMaterialOptional.orElse(XMaterial.EMERALD_BLOCK).parseMaterial(); - final var offlineXMaterial = offlineXMaterialOptional.orElse(XMaterial.REDSTONE_BLOCK).parseMaterial(); - - new Thread(() -> { - final var servers = PSHubCore.getInstance().getServerCache().getServers(); - - servers.forEach(server -> { - final var itemBuilder = new ItemBuilder(server.getCachedStatus() == ServerStatus.ONLINE ? onlineXMaterial : offlineXMaterial); - - var lore = PSH.getConfig().getStringList(server.getCachedStatus() == ServerStatus.ONLINE ? "gui.selector.menu.online.lore" : "gui.selector.menu.offline.lore"); - - lore = lore.stream() - .map(s -> s.replaceAll("%server%", server.getPlayerName())) - .map(s -> s.replaceAll("%status%", server.getCachedStatus() == ServerStatus.ONLINE ? "&aOnline" : "&cOffline")) - .map(s -> s.replaceAll("%players%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getOnline() + "" : "0")) - .map(s -> s.replaceAll("%maxplayers%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getMax() + "" : "0")) - .map(s -> s.replaceAll("%port%", server.getPort() + "")) - .map(s -> s.replaceAll("%motd%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getMOTD() : "&cOffline")) - .map(s -> s.replaceAll("%node%", server.getNode())) - .map(s -> s.replaceAll("%owner%", server.getPlayerName())) - .map(s -> s.replaceAll("%ip%", server.getHostname())) - .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); - - var item = itemBuilder - .name(ChatUtil.translate(PSH.getConfig().getString(server.getCachedStatus() == ServerStatus.ONLINE ? "gui.selector.menu.online.name" : "gui.selector.menu.offline.name") - .replaceAll("%server%", server.getPlayerName()) - .replaceAll("%status%", server.getCachedStatus() == ServerStatus.ONLINE ? "&aOnline" : "&cOffline")) - .replaceAll("%players%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getOnline() + "" : "0") - .replaceAll("%maxplayers%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getMax() + "" : "0") - .replaceAll("%port%", server.getPort() + "") - .replaceAll("%motd%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getMOTD() : "&cOffline") - .replaceAll("%node%", server.getNode()) - .replaceAll("%owner%", server.getPlayerName()) - .replaceAll("%ip%", server.getHostname()) - ) - .lore(lore) - .build(); - - menu.setButton(0, menu.getInventory().firstEmpty(), new SGButton(item).withListener(listener -> BungeeUtil.connectPlayer(listener, player, server.getPlayerName()))); - }); - - Bukkit.getScheduler().runTask(PSHubCore.getInstance(), () -> player.openInventory(menu.getInventory())); - }).start(); - } - - public static void openMenu(Player player) { - - final var PSH = PSHubCore.getInstance(); - - new Thread(() -> { - if (!DataBase.containsServer(player.getUniqueId().toString())) { - final var menu = PSH.getSpiGUI().create(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.name")), 3); - menu.setAutomaticPaginationEnabled(false); - menu.setBlockDefaultInteractions(true); - - var itemCreate = new ItemBuilder(XMaterial.DIAMOND_BLOCK.parseMaterial()) - .name(PSH.getConfig().getString("gui.player-menu.menu.create.name")) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.create.lore")) - .build(); - - menu.setButton(0, 13, new SGButton(itemCreate).withListener(listener -> BungeeUtil.createServer(listener, player, player.getDisplayName()))); - - for (int i = 0; i < 9 * 4; i++) { - if (menu.getButton(i) == null) { - menu.setButton(i, new SGButton(new ItemBuilder(XMaterial.GRAY_STAINED_GLASS_PANE.parseItem()).name(" ").build())); - } - } - - Bukkit.getScheduler().runTask(PSHubCore.getInstance(), () -> player.openInventory(menu.getInventory())); - return; - } - - final var menu = PSH.getSpiGUI().create(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.name")), 4); - menu.setAutomaticPaginationEnabled(false); - menu.setBlockDefaultInteractions(true); - - final var deleteConfirmationMenu = PSH.getSpiGUI().create(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.delete.confirmation.name")), 3); - deleteConfirmationMenu.setAutomaticPaginationEnabled(false); - deleteConfirmationMenu.setBlockDefaultInteractions(true); - - final var stopConfirmationMenu = PSH.getSpiGUI().create(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.stop.confirmation.name")), 3); - stopConfirmationMenu.setAutomaticPaginationEnabled(false); - stopConfirmationMenu.setBlockDefaultInteractions(true); - - final var server = PSH - .getServerCache() - .getServers() - .stream() - .filter(_server -> _server.getPlayerName().equals(player.getName())) - .findFirst() - .orElse(null); - - if (server == null) { - player.sendMessage(ChatUtil.translate("&9Error> &cCould not find your server!")); - return; - } - - var lore = PSH.getConfig().getStringList(server.getCachedStatus() == ServerStatus.ONLINE ? "gui.player-menu.menu.info.online.lore" : "gui.player-menu.menu.info.offline.lore"); - - lore = lore.stream() - .map(s -> s.replaceAll("%server%", server.getPlayerName())) - .map(s -> s.replaceAll("%status%", server.getCachedStatus() == ServerStatus.ONLINE ? "&aOnline" : "&cOffline")) - .map(s -> s.replaceAll("%players%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getOnline() + "" : "0")) - .map(s -> s.replaceAll("%maxplayers%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getMax() + "" : "0")) - .map(s -> s.replaceAll("%port%", server.getPort() + "")) - .map(s -> s.replaceAll("%motd%", server.getCachedStatus() == ServerStatus.ONLINE ? server.getCachedData().getMOTD() : "&cOffline")) - .map(s -> s.replaceAll("%node%", server.getNode())) - .map(s -> s.replaceAll("%owner%", server.getPlayerName())) - .map(s -> s.replaceAll("%ip%", server.getHostname())) - .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); - - final var itemPlayer = new ItemBuilder(XMaterial.OAK_SIGN.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString(server.getCachedStatus() == ServerStatus.ONLINE ? "gui.player-menu.menu.info.online.name" : "gui.player-menu.menu.info.offline.name") - .replaceAll("%server%", server.getPlayerName()))) - .lore(lore) - .build(); - - final var itemDelete = new ItemBuilder(XMaterial.BARRIER.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.delete.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.delete.lore")) - .build(); - - final var itemDeleteQuestionYes = new ItemBuilder(XMaterial.EMERALD_BLOCK.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.delete.confirmation.accept.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.delete.confirmation.accept.lore")) - .build(); - - final var itemDeleteQuestionNo = new ItemBuilder(XMaterial.REDSTONE_BLOCK.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.delete.confirmation.decline.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.delete.confirmation.decline.lore")) - .build(); - - final var itemStopQuestionYes = new ItemBuilder(XMaterial.EMERALD_BLOCK.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.stop.confirmation.accept.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.stop.confirmation.accept.lore")) - .build(); - - final var itemStopQuestionNo = new ItemBuilder(XMaterial.REDSTONE_BLOCK.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.stop.confirmation.decline.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.stop.confirmation.decline.lore")) - .build(); - - if (server.getCachedStatus() == ServerStatus.ONLINE) { - final var itemJoin = new ItemBuilder(XMaterial.OAK_DOOR.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.join.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.join.lore")) - .build(); - final var itemStop = new ItemBuilder(XMaterial.REDSTONE_BLOCK.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.stop.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.stop.lore")) - .build(); - - menu.setButton(0, 22, new SGButton(itemJoin).withListener(listener -> BungeeUtil.connectPlayer(listener, player, player.getDisplayName()))); - menu.setButton(0, 20, new SGButton(itemStop).withListener(listener -> { - stopConfirmationMenu.setButton(0, 11, new SGButton(itemStopQuestionYes).withListener(listener2 -> { - BungeeUtil.stopServer(listener2, player, player.getDisplayName()); - player.closeInventory(); - })); - stopConfirmationMenu.setButton(0, 15, new SGButton(itemStopQuestionNo).withListener(listener2 -> { - player.closeInventory(); - })); - - for (int i = 0; i < 9 * 4; i++) { - if (stopConfirmationMenu.getButton(i) == null) { - stopConfirmationMenu.setButton(i, new SGButton(new ItemBuilder(XMaterial.GRAY_STAINED_GLASS_PANE.parseItem()).name(" ").build())); - } - } - - player.openInventory(stopConfirmationMenu.getInventory()); - })); - } - - if (server.getCachedStatus() == ServerStatus.OFFLINE) { - final var itemStart = new ItemBuilder(XMaterial.EMERALD_BLOCK.parseMaterial()) - .name(ChatUtil.translate(PSH.getConfig().getString("gui.player-menu.menu.start.name"))) - .lore(PSH.getConfig().getStringList("gui.player-menu.menu.start.lore")) - .build(); - - menu.setButton(0, 20, new SGButton(itemStart).withListener(listener -> BungeeUtil.startServer(listener, player, player.getDisplayName()))); - } - - menu.setButton(0, 24, new SGButton(itemDelete).withListener(listener -> { - deleteConfirmationMenu.setButton(0, 11, new SGButton(itemDeleteQuestionYes).withListener(listener2 -> { - BungeeUtil.deleteServer(listener2, player, player.getDisplayName()); - player.closeInventory(); - })); - deleteConfirmationMenu.setButton(0, 15, new SGButton(itemDeleteQuestionNo).withListener(listener2 -> { - player.closeInventory(); - })); - - for (int i = 0; i < 9 * 4; i++) { - if (deleteConfirmationMenu.getButton(i) == null) { - deleteConfirmationMenu.setButton(i, new SGButton(new ItemBuilder(XMaterial.GRAY_STAINED_GLASS_PANE.parseItem()).name(" ").build())); - } - } - - player.openInventory(deleteConfirmationMenu.getInventory()); - })); - - menu.setButton(0, 4, new SGButton(itemPlayer)); - - // Fill all empty slots with glass pane - for (int i = 0; i < 9 * 4; i++) { - if (menu.getButton(i) == null) { - menu.setButton(i, new SGButton(new ItemBuilder(XMaterial.GRAY_STAINED_GLASS_PANE.parseItem()).name(" ").build())); - } - } - - Bukkit.getScheduler().runTask(PSHubCore.getInstance(), () -> player.openInventory(menu.getInventory())); - }).start(); - } -} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/GuiUtils.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/GuiUtils.java new file mode 100644 index 0000000..cee98bd --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/GuiUtils.java @@ -0,0 +1,40 @@ +package os.arcadiadevs.playerservers.hubcore.utils; + +import com.cryptomorin.xseries.XMaterial; +import com.samjakob.spigui.SGMenu; +import com.samjakob.spigui.buttons.SGButton; +import com.samjakob.spigui.item.ItemBuilder; + +public class GuiUtils { + + public static void addBorder(SGMenu menu, int rows) { + for (int i = 0; i < 9; i++) { + menu.setButton( + i, + new SGButton(new ItemBuilder(XMaterial.WHITE_STAINED_GLASS_PANE.parseItem()).build()) + ); + } + + for (int i = 0; i < rows; i++) { + menu.setButton( + i * 9, + new SGButton(new ItemBuilder(XMaterial.WHITE_STAINED_GLASS_PANE.parseItem()).build()) + ); + } + + for (int i = 0; i < rows; i++) { + menu.setButton( + i * 9 + 8, + new SGButton(new ItemBuilder(XMaterial.WHITE_STAINED_GLASS_PANE.parseItem()).build()) + ); + } + + for (int i = (rows - 1) * 9; i < ((rows - 1) * 9) + 9; i++) { + menu.setButton( + i, + new SGButton(new ItemBuilder(XMaterial.WHITE_STAINED_GLASS_PANE.parseItem()).build()) + ); + } + } + +} diff --git a/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ServerPinger.java b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ServerPinger.java new file mode 100644 index 0000000..d8e5648 --- /dev/null +++ b/src/main/java/os/arcadiadevs/playerservers/hubcore/utils/ServerPinger.java @@ -0,0 +1,100 @@ +/* + * MIT License. + * + * Copyright (c) 2021 MrMicky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package os.arcadiadevs.playerservers.hubcore.utils; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import os.arcadiadevs.playerservers.hubcore.enums.ServerStatus; + +/** + * Simple tool to ping a Minecraft server to get MOTD, online players and max players. + * + * @author MrMicky + */ +public class ServerPinger { + + public static CompletableFuture ping(InetSocketAddress address, int timeout) { + return CompletableFuture.supplyAsync(() -> { + try (Socket socket = new Socket()) { + + socket.setSoTimeout(timeout); + socket.connect(address, timeout); + + try (DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + InputStream in = socket.getInputStream(); + InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_16BE)) { + + out.write(new byte[] {(byte) 0xFE, 0x01}); + + int packetId = in.read(); + int length = reader.read(); + + if (packetId != 0xFF) { + return new PingResult(ServerStatus.UNKNOWN, null, null, null); + } + + if (length <= 0) { + return new PingResult(ServerStatus.UNKNOWN, null, null, null); + } + + char[] chars = new char[length]; + + if (reader.read(chars, 0, length) != length) { + return new PingResult(ServerStatus.UNKNOWN, null, null, null); + } + + String string = new String(chars); + + if (!string.startsWith("§")) { + return new PingResult(ServerStatus.UNKNOWN, null, null, null); + } + + String[] data = string.split("\000"); + + int players = Integer.parseInt(data[4]); + int maxPlayers = Integer.parseInt(data[5]); + + return new PingResult(ServerStatus.ONLINE, players, maxPlayers, data[3]); + } + } catch (IOException e) { + return new PingResult(ServerStatus.OFFLINE, null, null, null); + } + }); + } + + public record PingResult(ServerStatus status, Integer players, Integer maxPlayers, String motd) { + + @Override + public String toString() { + return "PingResult{players=" + this.players + ", maxPlayers=" + this.maxPlayers + '}'; + } + } +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a2c5793..9cc3830 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -13,6 +13,8 @@ messages: gui: selector: + enabled: true + item: enabled: true name: "&aQuick Compass" @@ -44,6 +46,8 @@ gui: - '&7Ip: &c%ip%&8:&c%port%' player-menu: + enabled: true + item: enabled: true name: "&eMy Server" diff --git a/src/main/resources/hibernate.cfg.xml b/src/main/resources/hibernate.cfg.xml new file mode 100644 index 0000000..01cb1e4 --- /dev/null +++ b/src/main/resources/hibernate.cfg.xml @@ -0,0 +1,35 @@ + + + + + + + + com.mysql.cj.jdbc.Driver + jdbc:mysql://localhost:3306/my_prod_db?useSSL=false&serverTimezone=UTC + prod + prod + + + 1 + + + org.hibernate.dialect.MySQLDialect + + + false + + + false + + + thread + + + update + + + + \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 9f0d1de..9809e04 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: PSHubCore -main: os.arcadiadevs.playerservers.hubcore.PSHubCore +main: os.arcadiadevs.playerservers.hubcore.PsHubCore version: 3-dev author: OpenSource