diff --git a/.gitignore b/.gitignore index 2d513a0..9a2c893 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /.idea/ /target/ +/*.iml +/dependency-reduced-pom.xml diff --git a/pom.xml b/pom.xml index fe9f9f1..c4991fe 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,20 @@ + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + @@ -60,9 +74,20 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + papermc + https://repo.papermc.io/repository/maven-public/ + + + com.velocitypowered + velocity-api + 3.0.1 + provided + org.spigotmc spigot-api @@ -76,6 +101,16 @@ provided remapped-mojang + + com.zaxxer + HikariCP + 5.0.1 + compile + + + mysql + mysql-connector-java + 8.0.29 + - \ No newline at end of file diff --git a/src/main/java/com/grubnest/game/core/GrubnestCorePlugin.java b/src/main/java/com/grubnest/game/core/GrubnestCorePlugin.java deleted file mode 100644 index f16b6bd..0000000 --- a/src/main/java/com/grubnest/game/core/GrubnestCorePlugin.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.grubnest.game.core; - -import org.bukkit.plugin.java.JavaPlugin; - -public class GrubnestCorePlugin extends JavaPlugin { - - /** - * Runs when plugin is enabled - */ - @Override - public void onEnable() { - - } - - /** - * Runs when plugin is disabled - */ - @Override - public void onDisable() { - - } -} diff --git a/src/main/java/com/grubnest/game/core/PluginMessage.java b/src/main/java/com/grubnest/game/core/PluginMessage.java new file mode 100644 index 0000000..e1f76fa --- /dev/null +++ b/src/main/java/com/grubnest/game/core/PluginMessage.java @@ -0,0 +1,313 @@ +package com.grubnest.game.core; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import com.grubnest.game.core.paper.GrubnestCorePlugin; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.messaging.PluginMessageListener; + +import java.io.*; + +/** + * @author tamilpp25 + * @created 15/05/2022 + */ +public class PluginMessage implements PluginMessageListener { + + /** + * Plugin message receiver + * triggers when there is a response from a subchannel + * //todo fix forward method later + * @param channel Subchannel as given in spigot docs + * @param player Player that send plugin message to server + * @param message Message + */ + @Override + public void onPluginMessageReceived(String channel, Player player, byte[] message) { + if (!channel.equals("BungeeCord")) { + return; + } + ByteArrayDataInput in = ByteStreams.newDataInput(message); + String subchannel = in.readUTF(); + if (subchannel.equals("PlayerCount")) { + String server = in.readUTF(); // Name of server, as given in the arguments + int playercount = in.readInt(); // list of players + } else if(subchannel.equals("PlayerList")){ + String server = in.readUTF(); // The name of the server you got the player list of, as given in args. + String[] playerList = in.readUTF().split(", "); // gets all players in the server or ALL for whole proxy + } else if(subchannel.equals("GetServers")){ + String[] serverList = in.readUTF().split(", "); // Gets the list of servers defined + } else if(subchannel.equals("GetServer")){ + String servername = in.readUTF(); // get the current server name + }else if(subchannel.equals("UUID")){ + String uuid = in.readUTF(); // get the uuid of sent player + }else if(subchannel.equals("UUIDOther")){ + String playerName = in.readUTF(); // player name + String uuid = in.readUTF(); // player uuid + } else if(subchannel.equals("ServerIP")){ + String serverName = in.readUTF(); + String ip = in.readUTF(); + int port = in.readUnsignedShort(); + }else if(subchannel.equals("Custom sub channel")){ // todo change later the name for custom sub channel + short len = in.readShort(); + byte[] msgbytes = new byte[len]; + in.readFully(msgbytes); + + DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes)); + try { + String somedata = msgin.readUTF(); // Read the data in the same way you wrote it + short somenumber = msgin.readShort(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Connects a player to said subserver. + * + * @receiver player to be teleported + * + * @param player Player to send plugin message to + * @param server name of server to connect to, as defined in BungeeCord config.yml + */ + public static void connect(Player player, String server){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("Connect"); + output.writeUTF(server); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + player.sendMessage(ChatColor.DARK_GRAY + "sending you to " + server + "..."); + } + + /** + * Connect a named player to said subserver + * + * @receiver any player + * + * @param player Player to send plugin message to + * @param named_player name of the player to teleport + * @param server name of server to connect to, as defined in BungeeCord config.yml + */ + public static void connectOther(Player player, String named_player, String server){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("ConnectOther"); + output.writeUTF(named_player); + output.writeUTF(server); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Get the amount of players on a certain server, or on ALL the servers. + * + * @receiver any player + * + * @param player packet carrier + * @param server the name of the server to get the player count of, or ALL to get the global player count + */ + public static void getPlayerCount(Player player, String server){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("PlayerCount"); + output.writeUTF(server); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Get a list of players connected on a certain server, or on ALL of the servers. + * + * @receiver any player + * + * @param player packet carrier + * @param server the name of the server to get the list of connected players, or ALL for global online player list + */ + public static void getPlayerList(Player player, String server){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("PlayerList"); + output.writeUTF(server); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Get a list of server name strings, as defined in BungeeCord's config.yml + * + * @receiver any player + * + * @param player packet carrier + */ + public static void getServers(Player player){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("GetServers"); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Send a message (as in, a chat message) to the specified player. + * + * @receiver any player + * + * @param player packet carrier + * @param proxyPlayer the name of the player to send the chat message, or ALL to send to all players + * @param message the message to send to the player , supports color codes with "&" as translator + */ + public static void sendMessage(Player player,String proxyPlayer,String message){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("Message"); + output.writeUTF(proxyPlayer); + output.writeUTF(ChatColor.translateAlternateColorCodes('&',message)); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Send a raw message (as in, a chat message) to the specified player. The advantage of this method over Message + * is that you can include click events and hover events. + * + * @receiver any player + * + * @param player packet carrier + * @param proxyPlayer the name of the player to send the chat message, or ALL to send to all players + * @param message the message to send to the player + */ + public static void sendRawMessage(Player player,String proxyPlayer,String message){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("MessageRaw"); + output.writeUTF(proxyPlayer); + output.writeUTF(message); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Get this server's name, as defined in BungeeCord's config.yml + * + * @receiver any player + * + * @param player packet carrier + */ + public static void getServer(Player player){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("GetServer"); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Request the UUID of this player + * + * @receiver The player whose UUID you requested + * + * @param player player + */ + public static void getUUID(Player player){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("UUID"); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Request the UUID of any player connected to the BungeeCord proxy + * + * @receiver the sender + * + * @param player packet carrier and receiver + * @param oplayername the name of the player whose UUID you would like + */ + public static void getUUIDOther(Player player,String oplayername){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("UUIDOther"); + output.writeUTF(oplayername); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Request the IP of any server on this proxy + * + * @receiver any player + * + * @param player packet carrier + * @param server the name of the server + */ + public static void getServerIP(Player player,String server){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("ServerIP"); + output.writeUTF(server); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Kick any player on this proxy + * + * @receiver any player + * + * @param player packet carrier + * @param playerToKick player to be kicked + * @param reason reason for kick + */ + public static void kickPlayer(Player player,String playerToKick,String reason){ + ByteArrayDataOutput output = ByteStreams.newDataOutput(); + output.writeUTF("KickPlayer"); + output.writeUTF(playerToKick); + output.writeUTF(reason); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", output.toByteArray()); + } + + /** + * Send a custom plugin message to said server. This is one of the most useful channels ever. + * Remember, the sending and receiving server(s) need to have a player online. + * + * @receiver any player + * + * @param player packet carrier + * @param server server to send to, ALL to send to every server (except the one sending the plugin message), + * or ONLINE to send to every server that's online (except the one sending the plugin message) + * @param subchannel Subchannel for plugin usage. + * @param data message to send //todo change stuff so can send anything + */ + public static void forward(Player player,String server,String subchannel,String data){ + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("Forward"); // So BungeeCord knows to forward it + out.writeUTF(server); // server to send to + out.writeUTF(subchannel); // The channel name to check if this your data + + ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); + DataOutputStream msgout = new DataOutputStream(msgbytes); + try { + //THESE ARE DATA WE WANT TO SEND (example) // remove later + msgout.writeUTF(data); // You can do anything you want with msgout + msgout.writeShort(123); // checking needed + } catch (IOException exception){ + exception.printStackTrace(); + } + + out.writeShort(msgbytes.toByteArray().length); + out.write(msgbytes.toByteArray()); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", out.toByteArray()); + } + + /** + * Send a custom plugin message to specific player. + * @param player packet carrier + * @param playerToForwardTo Playername to send to. + * @param subchannel Subchannel for plugin usage. + * @param data message to send. //todo change stuff so can send anything + */ + public static void forwardToPlayer(Player player,String playerToForwardTo,String subchannel,String data){ + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("ForwardToPlayer"); // So BungeeCord knows to forward it + out.writeUTF(playerToForwardTo); // server to send to + out.writeUTF(subchannel); // The channel name to check if this your data + + ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); + DataOutputStream msgout = new DataOutputStream(msgbytes); + try { + //THESE ARE DATA WE WANT TO SEND (example) //remove later + msgout.writeUTF(data); // You can do anything you want with msgout + msgout.writeShort(123); // checking needed + } catch (IOException exception){ + exception.printStackTrace(); + } + + out.writeShort(msgbytes.toByteArray().length); + out.write(msgbytes.toByteArray()); + player.sendPluginMessage(GrubnestCorePlugin.getInstance(), "BungeeCord", out.toByteArray()); + } + +} \ No newline at end of file diff --git a/src/main/java/com/grubnest/game/core/bridge/entities/GrubnestPlayer.java b/src/main/java/com/grubnest/game/core/bridge/entities/GrubnestPlayer.java new file mode 100644 index 0000000..8c19c5c --- /dev/null +++ b/src/main/java/com/grubnest/game/core/bridge/entities/GrubnestPlayer.java @@ -0,0 +1,7 @@ +package com.grubnest.game.core.bridge.entities; + +public interface GrubnestPlayer { + + void updateUsername(); + +} diff --git a/src/main/java/com/grubnest/game/core/databasehandler/ConnectionPoolManager.java b/src/main/java/com/grubnest/game/core/databasehandler/ConnectionPoolManager.java new file mode 100644 index 0000000..befe4f1 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/databasehandler/ConnectionPoolManager.java @@ -0,0 +1,108 @@ +package com.grubnest.game.core.databasehandler; + +import com.grubnest.game.core.databasehandler.utils.Deactivated; +import com.grubnest.game.core.databasehandler.utils.Disabler; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Handles connection from mysql and uses HikariCP + * + * @author tamilpp25 + * @version 1.0 at 15-5-2022 + */ +public class ConnectionPoolManager implements Deactivated { + + private final MySQLData data; + private HikariDataSource dataSource; + + /** + * Construct mysql HikariCP + * + * @param data MysqlDATA + */ + public ConnectionPoolManager(MySQLData data) { + this.data = data; + setupPool(); + Disabler.getInstance().registerDeactivated(this); + } + + /** + * Setup mysql connection Pool with HikariCP to get multiple connections. + */ + private void setupPool() { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl( + "jdbc:mysql://" + + data.HOST + + ":" + + data.PORT + + "/" + + data.DATABASE + ); + + config.setDriverClassName("com.mysql.cj.jdbc.Driver"); + config.setUsername(data.USERNAME); + config.setPassword(data.PASSWORD); + config.setMinimumIdle(data.minimumConnections); + config.setMaximumPoolSize(data.maximumConnections); + config.setConnectionTimeout(data.connectionTimeout); + config.setConnectionTestQuery("SELECT 1"); + dataSource = new HikariDataSource(config); + } + + /** + * Get MySQL Pool connection + * + * @return Sql Connection + * @throws SQLException if some error.. + */ + public Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + /** + * Temp close method can close using try-with statement too + * Recommending using try-with statement to close automatically! + * + * @param conn Connection + * @param ps PreparedStatement + * @param res ResultSet + */ + public void close(Connection conn, PreparedStatement ps, ResultSet res) { + if (conn != null) try { + conn.close(); + } catch (SQLException ignored) { + } + if (ps != null) try { + ps.close(); + } catch (SQLException ignored) { + } + if (res != null) try { + res.close(); + } catch (SQLException ignored) { + } + } + + /** + * Close pool when everything done... + */ + public void closePool() { + if (dataSource != null && !dataSource.isClosed()) { + dataSource.close(); + } + } + + /** + * Auto disable classes on disable if multiple instance are there too + */ + @Override + public void onDisable() { + closePool(); + } +} diff --git a/src/main/java/com/grubnest/game/core/databasehandler/MySQL.java b/src/main/java/com/grubnest/game/core/databasehandler/MySQL.java new file mode 100644 index 0000000..068df00 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/databasehandler/MySQL.java @@ -0,0 +1,73 @@ +package com.grubnest.game.core.databasehandler; + +import com.velocitypowered.api.proxy.Player; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +/** + * Main class for handling mysql data + * make your methods for getting / setting here in async! + * new MySQL class can be initialized outside main class too! + *

+ * Recommend using getMySQL method from main class as it properly does the work and closes connection on disable! + * make a new instance of this if you really know what you are doing! + * + * @author tamilpp25 + * @version 1.0 at 15-5-2022 + */ +public class MySQL extends ConnectionPoolManager { + public MySQL(MySQLData data) { + super(data); + } + + /** + * Close pool on plugin Disable + */ + public void onDisable() { + closePool(); + } + + /** + * Creates any tables required for the database. Runs at proxy server initialization + */ + public void createTables() { + try { + PreparedStatement statement = getConnection().prepareStatement(""" + CREATE TABLE IF NOT EXISTS `player` ( + uuid varchar(36) PRIMARY KEY, + username varchar(16) + ) + """); + statement.executeUpdate(); + statement.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * Updates a players username stored in the database + * + * @param player the player to store + */ + public void updatePlayerUsername(Player player) { + try { + PreparedStatement statement = getConnection().prepareStatement(""" + INSERT INTO player + (uuid, username) + VALUES + (?, ?) + ON DUPLICATE KEY UPDATE + username = ?; + """); + statement.setString(1, player.getUniqueId().toString()); + statement.setString(2, player.getUsername()); + statement.setString(3, player.getUsername()); + statement.executeUpdate(); + statement.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/grubnest/game/core/databasehandler/MySQLData.java b/src/main/java/com/grubnest/game/core/databasehandler/MySQLData.java new file mode 100644 index 0000000..beadfb5 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/databasehandler/MySQLData.java @@ -0,0 +1,59 @@ +package com.grubnest.game.core.databasehandler; + +import org.yaml.snakeyaml.Yaml; + +import java.io.InputStream; +import java.util.Map; + +/** + * MysqlData object to store credentials etc + * + * @author tamilpp25, Theeef + * @version 1.0 at 5/26/2022 + */ +public class MySQLData { + public final String HOST; + public final String USERNAME; + public final String PASSWORD; + public final int PORT; + public final String DATABASE; + + public final int minimumConnections; + public final int maximumConnections; + public final long connectionTimeout; + + public MySQLData(String host, String username, String password, int port, String database, int minimumConnections, int maximumConnections, long connectionTimeout) { + HOST = host; + USERNAME = username; + PASSWORD = password; + PORT = port; + DATABASE = database; + this.minimumConnections = minimumConnections; + this.maximumConnections = maximumConnections; + this.connectionTimeout = connectionTimeout; + } + + /** + * Initialize data from config.yml + * + * @return MySQLData + */ + public static MySQLData dataInitializer() { + Yaml yaml = new Yaml(); + InputStream inputStream = MySQLData.class.getClassLoader().getResourceAsStream("config.yml"); + Map config; + config = (Map) ((Map) yaml.load(inputStream)).get("Database"); + + String host = (String) config.get("hostname"); + int port = (int) config.get("port"); + String database = (String) config.get("database"); + String username = (String) config.get("username"); + String password = (String) config.get("password"); + + int minimumConnections = (int) config.get("minimumConnections"); + int maximumConnections = (int) config.get("maximumConnections"); + long connectionTimeout = (long) (int) config.get("connectionTimeout"); + + return new MySQLData(host, username, password, port, database, minimumConnections, maximumConnections, connectionTimeout); + } +} diff --git a/src/main/java/com/grubnest/game/core/databasehandler/utils/Deactivated.java b/src/main/java/com/grubnest/game/core/databasehandler/utils/Deactivated.java new file mode 100644 index 0000000..332901c --- /dev/null +++ b/src/main/java/com/grubnest/game/core/databasehandler/utils/Deactivated.java @@ -0,0 +1,12 @@ +package com.grubnest.game.core.databasehandler.utils; + +/** + * Utility class to prevent Memory leak. + * @author tamilpp25 + * @version 1.0 at 15-5-2022 + */ +public interface Deactivated { + + void onDisable(); + +} diff --git a/src/main/java/com/grubnest/game/core/databasehandler/utils/Disabler.java b/src/main/java/com/grubnest/game/core/databasehandler/utils/Disabler.java new file mode 100644 index 0000000..e248f40 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/databasehandler/utils/Disabler.java @@ -0,0 +1,44 @@ +package com.grubnest.game.core.databasehandler.utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Disabler instance to auto disable any used instance of sql + * @author tamilpp25 + * @version 1.0 at 15-5-2022 + */ +public class Disabler { + private static Disabler instance = null; + private final List toDisable = new ArrayList<>(); + + public static Disabler getInstance() { + if (instance != null) return instance; + return instance = new Disabler(); + } + + /** + * close all active mysql connections + */ + public void disableAll() { + for (Deactivated toDeactivated : toDisable) + toDeactivated.onDisable(); + } + + /** + * Disable specific class with mysql connection + * @param sqlinstance SQL instance + */ + public void disable(Deactivated sqlinstance) { + sqlinstance.onDisable(); + } + + /** + * Register a class as mysql connection pool + * @param pDeactivated Class to be registered + */ + public void registerDeactivated(Deactivated pDeactivated) { + toDisable.add(pDeactivated); + } + +} \ No newline at end of file diff --git a/src/main/java/com/grubnest/game/core/paper/GrubnestCorePlugin.java b/src/main/java/com/grubnest/game/core/paper/GrubnestCorePlugin.java new file mode 100644 index 0000000..de7eaa8 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/paper/GrubnestCorePlugin.java @@ -0,0 +1,69 @@ +package com.grubnest.game.core.paper; + +import com.grubnest.game.core.PluginMessage; +import com.grubnest.game.core.databasehandler.MySQL; +import com.grubnest.game.core.databasehandler.MySQLData; +import com.grubnest.game.core.databasehandler.utils.Disabler; +import org.bukkit.ChatColor; +import org.bukkit.plugin.java.JavaPlugin; + +public class GrubnestCorePlugin extends JavaPlugin { + + private MySQL sql; + private static GrubnestCorePlugin instance; + + /** + * Runs when plugin is enabled + */ + @Override + public void onEnable() { + instance = this; + + //Register Plugin messaging channels on enable + this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new PluginMessage()); + + getServer().getConsoleSender().sendMessage(ChatColor.AQUA + "GrubnestCore is Enabled"); + + loadConfig(); + this.sql = new MySQL(MySQLData.dataInitializer()); + } + + /** + * Loads the config and enables copying defaults + */ + public void loadConfig() { + getConfig().options().copyDefaults(true); + saveConfig(); + } + + /** + * Runs when plugin is disabled + */ + @Override + public void onDisable() { + Disabler.getInstance().disableAll(); + //Unregister channels on disable + this.getServer().getMessenger().unregisterOutgoingPluginChannel(this); + this.getServer().getMessenger().unregisterIncomingPluginChannel(this); + } + + /** + * Get SQL Object + * + * @return SQL object + */ + public MySQL getMySQL() { + return sql; + } + + /** + * Get Plugin Instance + * + * @return Plugin Instance + */ + public static GrubnestCorePlugin getInstance() { + return instance; + } + +} diff --git a/src/main/java/com/grubnest/game/core/velocity/VelocityPlugin.java b/src/main/java/com/grubnest/game/core/velocity/VelocityPlugin.java new file mode 100644 index 0000000..c7dd5a0 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/velocity/VelocityPlugin.java @@ -0,0 +1,89 @@ +package com.grubnest.game.core.velocity; + +import com.google.inject.Inject; +import com.grubnest.game.core.databasehandler.MySQL; +import com.grubnest.game.core.databasehandler.MySQLData; +import com.grubnest.game.core.velocity.events.CoreEventListener; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.plugin.Plugin; +import com.velocitypowered.api.proxy.ProxyServer; +import net.kyori.adventure.text.Component; +import org.slf4j.Logger; +import org.yaml.snakeyaml.Yaml; + +import java.io.InputStream; +import java.util.Map; + +/** + * The VelocityPlugin class is an implementation of the Velocity API. + * It provides communication to and from the Velocity Proxy server + * running on the Grubnest network + * + * @author Theeef + * @version 1.2 at 5/26/2022 + */ +@Plugin(id = "grubnestcore", name = "Grubnest Core Plugin", version = "0.1.0-SNAPSHOT", + url = "htts://grubnest.com", description = "Grubnest Core running on Velocity", authors = {"Theeef"}) +public class VelocityPlugin { + + private final ProxyServer server; + private final MySQL sql; + private static VelocityPlugin instance; + + + /** + * Creates an instance of the Velocity Plugin and injects it + * + * @param server The velocity proxy server + * @param logger The proxy server's logger + */ + @Inject + public VelocityPlugin(ProxyServer server, Logger logger) { + this.server = server; + + this.server.sendMessage(Component.text("GrubnestCore is enabled on Velocity!")); + this.sql = new MySQL(MySQLData.dataInitializer()); + + instance = this; + } + + /** + * Runs when the Proxy server initializes + * + * @param event event used in callback + */ + @Subscribe + public void onInitialize(ProxyInitializeEvent event) { + this.server.getEventManager().register(this, new CoreEventListener()); + + getMySQL().createTables(); + } + + /** + * Get SQL Object + * + * @return SQL object + */ + public MySQL getMySQL() { + return this.sql; + } + + /** + * Get the ProxyServer object + * + * @return ProxyServer object + */ + public ProxyServer getServer() { + return this.server; + } + + /** + * Get Plugin Instance + * + * @return Plugin Instance + */ + public static VelocityPlugin getInstance() { + return instance; + } +} diff --git a/src/main/java/com/grubnest/game/core/velocity/entities/VPlayer.java b/src/main/java/com/grubnest/game/core/velocity/entities/VPlayer.java new file mode 100644 index 0000000..0371918 --- /dev/null +++ b/src/main/java/com/grubnest/game/core/velocity/entities/VPlayer.java @@ -0,0 +1,33 @@ +package com.grubnest.game.core.velocity.entities; + +import com.grubnest.game.core.bridge.entities.GrubnestPlayer; +import com.grubnest.game.core.velocity.VelocityPlugin; +import com.velocitypowered.api.proxy.Player; + +/** + * Represents a custom player entity on the Velocity server + * + * @author Theeef + * @version 1.0 at 5/26/2022 + */ +public class VPlayer implements GrubnestPlayer { + + private Player player; + + /** + * Creates a custom player instance for Velocity + * + * @param player the player this represents + */ + public VPlayer(Player player) { + this.player = player; + } + + /** + * Updates the cached username of this player in the database + */ + public void updateUsername() { + VelocityPlugin.getInstance().getMySQL().updatePlayerUsername(this.player); + } + +} diff --git a/src/main/java/com/grubnest/game/core/velocity/events/CoreEventListener.java b/src/main/java/com/grubnest/game/core/velocity/events/CoreEventListener.java new file mode 100644 index 0000000..a82996a --- /dev/null +++ b/src/main/java/com/grubnest/game/core/velocity/events/CoreEventListener.java @@ -0,0 +1,28 @@ +package com.grubnest.game.core.velocity.events; + +import com.grubnest.game.core.velocity.entities.VPlayer; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.player.ServerConnectedEvent; + +/** + * Listens for core events, like Server Connection for Velocity + *

+ * + * @author Theeef + * @version 1.0 at 5/23/2022 + */ +public class CoreEventListener { + + /** + * Logs basic user data to the server database when a user connects + * to a server on our network + * + * @param event The connection event that occurs + */ + @Subscribe + public void onServerConnect(ServerConnectedEvent event) { + VPlayer player = new VPlayer(event.getPlayer()); + player.updateUsername(); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..866e8db --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,10 @@ +# DEFAULT VALUES FOR MYSQL DATABASE update later!! +Database: + hostname: grubnest.com + port: 3306 + database: s4_grubnest + username: u4_xb6o263UWu + password: Sf^R4vzWq6nKl!av!u+JTo81 + minimumConnections: 5 + maximumConnections: 10 + connectionTimeout: 5000 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2cb97c0..ac3f33d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,7 @@ name: GrubnestCore -main: com.grubnest.game.core.GrubnestCorePlugin +main: com.grubnest.game.core.paper.GrubnestCorePlugin version: 1.0 authors: - Theeef -api-version: 1.13 \ No newline at end of file + - tamilpp25 +api-version: 1.18 \ No newline at end of file