diff --git a/README.md b/README.md index 913dc72..b6ba100 100644 --- a/README.md +++ b/README.md @@ -74,3 +74,5 @@ This project is licensed under the [GNU GPL v3 License](https://www.gnu.org/lice @PhastixTV @zCreeperYT @ProJakob +@liyanic +@CrAfTsArMy diff --git a/pom.xml b/pom.xml index 3b88267..6fffc8e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,19 +2,19 @@ - 4.0.0 + 4.0.0 - de.codeblocksmc.codelib - CodeLib - 3.6.4 - jar + de.codeblocksmc.codelib + CodeLib + 3.6.4 + jar - CodeLib + CodeLib - - 21 - UTF-8 - + + 21 + UTF-8 + @@ -23,79 +23,90 @@ - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.14.0 - - 21 - 21 - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - package - - shade - - - - - - - - src/main/resources - true - - - + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + 21 + 21 + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + + + + + + src/main/resources + true + + + - - - papermc-repo - https://repo.papermc.io/repository/maven-public/ - - - sonatype - https://oss.sonatype.org/content/groups/public/ - - + - - - io.papermc.paper - paper-api - 1.21.6-R0.1-SNAPSHOT - provided - - - io.github.leonardosnt - bungeechannelapi - 1.0.0-SNAPSHOT - - - fr.mrmicky - fastboard - 2.1.5 - - - org.projectlombok - lombok - 1.18.42 - provided - - - - com.arcaniax - HeadDatabase-API - 1.3.2 - provided - - + + + codemc-repo + https://repo.codemc.org/repository/maven-public/ + + + + papermc-repo + https://repo.papermc.io/repository/maven-public/ + + + sonatype + https://oss.sonatype.org/content/groups/public/ + + + + + + + + + + io.papermc.paper + paper-api + 1.21.6-R0.1-SNAPSHOT + provided + + + io.github.leonardosnt + bungeechannelapi + 1.0.0-SNAPSHOT + + + fr.mrmicky + fastboard + 2.1.5 + + + org.projectlombok + lombok + 1.18.42 + provided + + + + com.arcaniax + HeadDatabase-API + 1.3.2 + provided + + \ No newline at end of file diff --git a/src/main/java/de/codeblocksmc/codelib/database/MSSQLTemplate.java b/src/main/java/de/codeblocksmc/codelib/database/MSSQLTemplate.java new file mode 100644 index 0000000..4b7f603 --- /dev/null +++ b/src/main/java/de/codeblocksmc/codelib/database/MSSQLTemplate.java @@ -0,0 +1,88 @@ +package de.codeblocksmc.codelib.database; + +import lombok.Getter; + +/** + * Abstract Microsoft SQL Server specific implementation of {@link SQLTemplate}. + * + * @author JustCody + * @author CrAfTs_ArMy + * @version 2.0 + */ +public abstract non-sealed class MSSQLTemplate extends SQLTemplate { + + /** + * Additional JDBC connection flags appended to the connection URL. + */ + @Getter + private final String additionalFlags; + + /** + * Creates a new MSSQLTemplate without any additional connection flags. + * + * @param host The database host + * @param port The database port + * @param database The database name + * @param user The database user + * @param password The database password + */ + public MSSQLTemplate(String host, int port, String database, String user, String password) { + super(host, port, database, user, password); + this.additionalFlags = ""; + } + + /** + * Creates a new MSSQLTemplate with additional JDBC connection flags. + *

+ * Each flag should be provided in the format {@code key=value}. + * Multiple flags will be joined using {@code ;}. + *

+ * + * @param host The database host + * @param port The database port + * @param database The database name + * @param user The database user + * @param password The database password + * @param additionalFlags Optional JDBC connection flags + */ + public MSSQLTemplate(String host, int port, String database, String user, String password, String... additionalFlags) { + super(host, port, database, user, password); + this.additionalFlags = String.join(";", additionalFlags); + } + + /** + * Returns the fully qualified Microsoft SQL Server JDBC driver class name. + * + * @return The SQL Server JDBC driver class + */ + @Override + protected String getDriverClass() { + return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + } + + /** + * Builds the Microsoft SQL Server JDBC connection URL. + *

+ * The URL follows the format: + * {@code jdbc:sqlserver://host:port;databaseName=database} + * and optionally appends additional connection properties. + *

+ * + * @return The JDBC connection URL template + */ + @Override + protected String getConnectionUrl() { + String url = "jdbc:sqlserver://%host%:%port%;databaseName=%database%"; + return url + (hasAdditionalFlags() ? ";" + additionalFlags : ""); + } + + /** + * Checks whether any additional JDBC connection flags are defined. + * + * @return {@code true} if additional flags are present, otherwise {@code false} + */ + public boolean hasAdditionalFlags() { + return additionalFlags != null && !additionalFlags.isBlank(); + } + +} diff --git a/src/main/java/de/codeblocksmc/codelib/database/MySQLTemplate.java b/src/main/java/de/codeblocksmc/codelib/database/MySQLTemplate.java new file mode 100644 index 0000000..149e210 --- /dev/null +++ b/src/main/java/de/codeblocksmc/codelib/database/MySQLTemplate.java @@ -0,0 +1,88 @@ +package de.codeblocksmc.codelib.database; + +import lombok.Getter; + +/** + * Abstract MySQL-specific implementation of {@link SQLTemplate}. + * + * @author JustCody + * @author CrAfTs_ArMy + * @version 2.0 + */ +public abstract non-sealed class MySQLTemplate extends SQLTemplate { + + /** + * Additional JDBC connection flags appended to the connection URL. + */ + @Getter + private final String additionalFlags; + + /** + * Creates a new MySQLTemplate without any additional connection flags. + * + * @param host The database host + * @param port The database port + * @param database The database name + * @param user The database user + * @param password The database password + */ + public MySQLTemplate(String host, int port, String database, String user, String password) { + super(host, port, database, user, password); + this.additionalFlags = ""; + } + + /** + * Creates a new MySQLTemplate with additional JDBC connection flags. + *

+ * Each flag should be provided in the format {@code key=value}. + * Multiple flags will be joined using {@code &}. + *

+ * + * @param host The database host + * @param port The database port + * @param database The database name + * @param user The database user + * @param password The database password + * @param additionalFlags Optional JDBC connection flags + */ + public MySQLTemplate(String host, int port, String database, String user, String password, String... additionalFlags) { + super(host, port, database, user, password); + this.additionalFlags = String.join("&", additionalFlags); + } + + /** + * Returns the fully qualified MySQL JDBC driver class name. + * + * @return The MySQL JDBC driver class + */ + @Override + protected String getDriverClass() { + return "com.mysql.cj.jdbc.Driver"; + } + + /** + * Builds the MySQL JDBC connection URL. + *

+ * The URL follows the format: + * {@code jdbc:mysql://host:port/database} + * and optionally appends query parameters if additional flags are present. + *

+ * + * @return The JDBC connection URL template + */ + @Override + protected String getConnectionUrl() { + String url = "jdbc:mysql://%host%:%port%/%database%"; + return url + (hasAdditionalFlags() ? "?" + additionalFlags : ""); + } + + /** + * Checks whether any additional JDBC connection flags are defined. + * + * @return {@code true} if additional flags are present, otherwise {@code false} + */ + public boolean hasAdditionalFlags() { + return additionalFlags != null && !additionalFlags.isBlank(); + } + +} diff --git a/src/main/java/de/codeblocksmc/codelib/database/SQLTemplate.java b/src/main/java/de/codeblocksmc/codelib/database/SQLTemplate.java new file mode 100644 index 0000000..58bf9b4 --- /dev/null +++ b/src/main/java/de/codeblocksmc/codelib/database/SQLTemplate.java @@ -0,0 +1,161 @@ +package de.codeblocksmc.codelib.database; + +import lombok.Getter; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +/** + * Abstract base class for SQL database templates. + * + * @author CrAfTs_ArMy + * @version 1.0 + */ +public sealed abstract class SQLTemplate permits MSSQLTemplate, MySQLTemplate { + + /** + * The database host address. + */ + private final String host; + + /** + * The port on which the database server is running. + */ + private final int port; + + /** + * The name of the database schema to connect to. + */ + private final String database; + + /** + * The username used for database authentication. + */ + private final String user; + + /** + * The password used for database authentication. + */ + private final String password; + + /** + * The active JDBC connection. + */ + @Getter + private Connection connection; + + /** + * Creates a new {@link SQLTemplate} with the given connection parameters. + * + * @param host The database host + * @param port The database port + * @param database The database name + * @param user The database user + * @param password The database password + */ + public SQLTemplate(String host, int port, String database, String user, String password) { + this.host = host; + this.port = port; + this.database = database; + this.user = user; + this.password = password; + } + + /** + * Hook method that is called after a successful database connection. + */ + protected abstract void afterSuccessfulConnection(); + + /** + * Returns the JDBC connection URL template. + *

+ * The returned string may contain the placeholders: + *

+ * which will be replaced before establishing the connection. + *

+ * + * @return The JDBC connection URL template + */ + protected abstract String getConnectionUrl(); + + /** + * Returns the fully qualified class name of the JDBC driver. + *

+ * If {@code null} is returned, no explicit driver loading will be attempted. + *

+ * + * @return The JDBC driver class name or {@code null} + */ + protected abstract String getDriverClass(); + + /** + * Establishes a connection to the database. + *

+ * This method loads the JDBC driver (if provided), builds the connection URL, + * and opens a connection using {@link DriverManager}. + *

+ * + * @return The established {@link Connection} + * @throws RuntimeException If the driver cannot be loaded or the connection fails + */ + public Connection connect() { + try { + String driverClass = getDriverClass(); + if (driverClass != null) { + Class.forName(driverClass); + } + + String connectionUrl = getConnectionUrl() + .replace("%host%", host) + .replace("%port%", String.valueOf(port)) + .replace("%database%", database); + + connection = DriverManager.getConnection(connectionUrl, user, password); + afterSuccessfulConnection(); + return connection; + } catch (ClassNotFoundException e) { + throw new RuntimeException("Failed to load driver: " + e.getMessage()); + } catch (SQLException e) { + throw new RuntimeException("Failed to connect: " + e.getMessage(), e); + } + } + + /** + * Closes the current database connection. + * + * @throws RuntimeException if closing the connection fails + */ + public void disconnect() { + try { + getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException("Failed to disconnect: " + e.getMessage(), e); + } + } + + /** + * Checks whether the database connection is active. + *

+ * If the connection is {@code null} or already closed, + * a new connection will be established automatically. + *

+ * + * @throws RuntimeException if checking the connection fails + */ + public void checkConnection() { + try { + Connection connection = getConnection(); + if (connection == null || connection.isClosed()) { + this.connect(); + } + } catch (SQLException e) { + throw new RuntimeException("Failed to check the connection: " + e.getMessage(), e); + } + } + +} diff --git a/src/main/java/de/codeblocksmc/codelib/databsae/DatabaseObject.java b/src/main/java/de/codeblocksmc/codelib/databsae/DatabaseObject.java deleted file mode 100644 index eb40cc9..0000000 --- a/src/main/java/de/codeblocksmc/codelib/databsae/DatabaseObject.java +++ /dev/null @@ -1,4 +0,0 @@ -package de.codeblocksmc.codelib.databsae; - -public class DatabaseObject { -} diff --git a/src/main/java/de/codeblocksmc/codelib/databsae/MSSQLTemplate.java b/src/main/java/de/codeblocksmc/codelib/databsae/MSSQLTemplate.java deleted file mode 100644 index cc7b197..0000000 --- a/src/main/java/de/codeblocksmc/codelib/databsae/MSSQLTemplate.java +++ /dev/null @@ -1,58 +0,0 @@ -package de.codeblocksmc.codelib.databsae; - -import lombok.Getter; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.logging.Logger; - -public class MSSQLTemplate extends DatabaseObject { - @Getter - public Connection conn; - private final Logger log; - private final String DB_NAME; - private final String DB_USER; - private final String DB_PASSWORD; - private final int DB_PORT; - private final String DB_HOST; - - public MSSQLTemplate(Logger log, String DB_NAME, String DB_USER, String DB_PASSWORD, int DB_PORT, String DB_HOST) { - this.log = log; - this.DB_NAME = DB_NAME; - this.DB_USER = DB_USER; - this.DB_PASSWORD = DB_PASSWORD; - this.DB_PORT = DB_PORT; - this.DB_HOST = DB_HOST; - } - - public Connection connect() { - String CONNECTION_STRING = "jdbc:sqlserver://HOST;databaseName=DATABASE;encrypt=false;trustServerCertificate=true;" - .replace("HOST", DB_HOST).replace("DATABASE", DB_NAME); - try { - Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - conn = DriverManager.getConnection(CONNECTION_STRING, DB_USER, DB_PASSWORD); - log.info("MSSQL Connection established."); - conn.createStatement().execute("USE " + DB_NAME); - return conn; - } - catch(Exception ex) { - log.warning(ex.getMessage()); - } - return null; - } - - public void checkConnection() { - try { - if (conn == null || conn.isClosed()) connect(); - } catch (SQLException ignored) {} - } - public void disconnect() { - try { - conn.close(); - log.info("SQL Connection destroyed."); - } catch (SQLException e) { - log.severe(e.getMessage()); - } - } -} diff --git a/src/main/java/de/codeblocksmc/codelib/databsae/MySQLTemplate.java b/src/main/java/de/codeblocksmc/codelib/databsae/MySQLTemplate.java deleted file mode 100644 index 0596f8d..0000000 --- a/src/main/java/de/codeblocksmc/codelib/databsae/MySQLTemplate.java +++ /dev/null @@ -1,98 +0,0 @@ -package de.codeblocksmc.codelib.databsae; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.logging.Logger; - -/** - * Template class for creating MySQL connections. - * This class provides methods for connecting to a MySQL database and checking the connection status. - * It works in conjunction with {@link Logger} for logging any issues or errors during the connection process. - * This is commonly used in Bukkit and Paper plugins for logging database-related activities. - * - * @author JustCody - * @version 1.0 - */ -public abstract class MySQLTemplate extends DatabaseObject { - - // The connection object to the MySQL database - public Connection conn; - - // Logger for logging messages related to the connection - public final Logger log; - - // MySQL connection details - public final String host; - public final int port; - public final String database; - public final String user; - public final String password; - - /** - * Constructor for initializing the MySQL connection template. - * - * @param log {@link Logger} of the plugin, typically used to log connection issues. - * @param host Hostname of the MySQL server (e.g., "localhost"). - * @param port Port of the MySQL server. Default is 3306. - * @param database Name of the MySQL database to connect to. - * @param user Username to authenticate with the MySQL server. - * @param password Password for the given username. - */ - public MySQLTemplate(Logger log, String host, int port, String database, String user, String password) { - this.log = log; - this.host = host; - this.port = port; - this.database = database; - this.user = user; - this.password = password; - } - - /** - * Establishes a connection to the MySQL server and creates a {@link Connection} object. - * This method loads the MySQL JDBC driver, attempts to connect to the database, - * and logs any exceptions if the connection fails. - */ - public void connect() { - final String DB_NAME = "jdbc:mysql://"+host+":"+port+"/"+database+"?useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&autoReconnect=true"; - - try { - // Load MySQL JDBC driver class - Class.forName("com.mysql.cj.jdbc.Driver"); - - // Establish a connection using the provided connection details - conn = DriverManager.getConnection(DB_NAME, user, password); - - afterSuccessfulConnection(); - } catch (Exception ex) { - // Log any exception that occurs during the connection process - log.warning("MySQL connection failed: " + ex.getMessage()); - } - } - - /** - * Checks the current MySQL connection to verify if it is still open and valid. - * If the connection is closed or null, this method will attempt to reconnect using {@link MySQLTemplate#connect()}. - */ - public void checkConnection() { - try { - if (conn == null || conn.isClosed()) { - // Attempt to reconnect if the connection is null or closed - connect(); - } - } catch (SQLException e) { - // Log any exceptions encountered while checking the connection status - log.warning("MySQL connection check failed: " + e.getMessage()); - } - } - - public void disconnect() { - try { - conn.close(); - } catch (SQLException e) { - log.severe(e.getMessage()); - } - } - - public abstract void afterSuccessfulConnection(); -} diff --git a/src/main/java/de/codeblocksmc/codelib/databsae/MySQLTemplateVelocity.java b/src/main/java/de/codeblocksmc/codelib/databsae/MySQLTemplateVelocity.java deleted file mode 100644 index 0f33d84..0000000 --- a/src/main/java/de/codeblocksmc/codelib/databsae/MySQLTemplateVelocity.java +++ /dev/null @@ -1,73 +0,0 @@ -package de.codeblocksmc.codelib.databsae; - -import org.slf4j.Logger; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; - - -/** - * Template class for creating MySQL connections - */ -public abstract class MySQLTemplateVelocity extends DatabaseObject { - - public Connection conn; - public final Logger log; - - private final String host; - private final int port; - private final String database; - private final String user; - private final String password; - - /** - * - * @param log {@link Logger} of the Plugin - * @param host Hostname - * @param port Port of the server. Default: 3306 - * @param database Database name - * @param user Username - * @param password Password - */ - public MySQLTemplateVelocity(Logger log, String host, int port, String database, String user, String password) { - this.log = log; - this.host = host; - this.port = port; - this.database = database; - this.user = user; - this.password = password; - } - - /** - * Connects to the MySQL server and creates a {@link Connection} object - */ - public void connect() { - final String DB_NAME = "jdbc:mysql://"+host+":"+port+"/"+database+"?useJDBCCompliantTimezoneShift=true&useLeg" + - "acyDatetimeCode=false&serverTimezone=UTC&autoReconnect=true"; - - try { - Class.forName("com.mysql.cj.jdbc.Driver"); //Gets the driver class - - conn = DriverManager.getConnection(DB_NAME, user, password); //Gets a connection to the database using the details you provided. - afterSuccessfulConnection(); - - } - catch(Exception ex) { - log.warn(ex.getMessage()); - } - } - - /** - * Checks if the connection is ok, otherwise it will try to {@link MySQLTemplate#connect()} to the server - */ - public void checkConnection() { - try { - if (conn == null || conn.isClosed()) connect(); - } catch (SQLException e) { - log.warn(e.getMessage()); - } - } - - public abstract void afterSuccessfulConnection(); -} diff --git a/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapper.java b/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapper.java index d161785..32f093a 100644 --- a/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapper.java +++ b/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapper.java @@ -4,7 +4,10 @@ import lombok.Setter; import lombok.NoArgsConstructor; +import java.util.Objects; + /** + * @author Try * A wrapper class for representing and saving positions in JSON files. * *

This class is designed to store positional data in a safe and @@ -18,55 +21,16 @@ @Getter @Setter @NoArgsConstructor -public class LocationWrapper { +public class LocationWrapper extends LocationWrapperReduced { /** * The name of the world where the location exists. */ private String world; - /** - * The X-coordinate of the location. - */ - private double x; - - /** - * The Y-coordinate of the location. - */ - private double y; - - /** - * The Z-coordinate of the location. - */ - private double z; - - /** - * The yaw (rotation on the Y-axis) of the location. - */ - private float yaw; - - /** - * The pitch (rotation on the X-axis) of the location. - */ - private float pitch; - - /** - * Constructs a {@link LocationWrapper} with the specified values. - * - * @param world the name of the {@link org.bukkit.World} where the location exists. - * @param x the X-coordinate of the location. - * @param y the Y-coordinate of the location. - * @param z the Z-coordinate of the location. - * @param yaw the yaw (rotation on the Y-axis) of the location. - * @param pitch the pitch (rotation on the X-axis) of the location. - */ public LocationWrapper(String world, double x, double y, double z, float yaw, float pitch) { + super(x,y,z,yaw,pitch); this.world = world; - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; } /** @@ -80,6 +44,7 @@ public boolean isValid() { return world != null && !world.isEmpty(); } + /** * Provides a string representation of the {@link LocationWrapper}. * @@ -88,7 +53,7 @@ public boolean isValid() { @Override public String toString() { return String.format("LocationWrapper[world=%s, x=%.2f, y=%.2f, z=%.2f, yaw=%.2f, pitch=%.2f]", - world, x, y, z, yaw, pitch); + world, getX(), getY(), getZ(), getYaw(), getPitch()); } /** @@ -101,35 +66,17 @@ public String toString() { */ @Override public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; + boolean result = super.equals(obj); - LocationWrapper other = (LocationWrapper) obj; - return Double.compare(other.x, x) == 0 && - Double.compare(other.y, y) == 0 && - Double.compare(other.z, z) == 0 && - Float.compare(other.yaw, yaw) == 0 && - Float.compare(other.pitch, pitch) == 0 && - (world != null ? world.equals(other.world) : other.world == null); + if (obj instanceof LocationWrapper other) + return result&& (Objects.equals(world, other.world)); + else{ + return false; + } } - /** - * Generates a hash code for the {@link LocationWrapper}. - * - * @return a hash code based on the fields of the object. - */ @Override public int hashCode() { - int result = (world != null ? world.hashCode() : 0); - long temp; - temp = Double.doubleToLongBits(x); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(y); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(z); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + Float.floatToIntBits(yaw); - result = 31 * result + Float.floatToIntBits(pitch); - return result; + return Objects.hash(super.hashCode(), world); } } diff --git a/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapperReduced.java b/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapperReduced.java index 25a49a2..dd50aaa 100644 --- a/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapperReduced.java +++ b/src/main/java/de/codeblocksmc/codelib/locations/LocationWrapperReduced.java @@ -4,7 +4,10 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.Objects; + /** + * @author Try * A wrapper class for representing and saving positions in JSON files. * *

This class is designed to store positional data in a safe and @@ -84,8 +87,8 @@ public LocationWrapper toWrapper(String world) { */ @Override public String toString() { - return String.format("LocationWrapper[world=%s, x=%.2f, y=%.2f, z=%.2f, yaw=%.2f, pitch=%.2f]", - "unknown", x, y, z, yaw, pitch); + return String.format("LocationWrapperReduced[ x=%.2f, y=%.2f, z=%.2f, yaw=%.2f, pitch=%.2f]", + x, y, z, yaw, pitch); } /** @@ -98,15 +101,19 @@ public String toString() { */ @Override public boolean equals(Object obj) { + if (obj == null ) return false; if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - - LocationWrapperReduced other = (LocationWrapperReduced) obj; - return Double.compare(other.x, x) == 0 && - Double.compare(other.y, y) == 0 && - Double.compare(other.z, z) == 0 && - Float.compare(other.yaw, yaw) == 0 && - Float.compare(other.pitch, pitch) == 0; + + if(obj instanceof LocationWrapperReduced other){ + return Double.compare(other.x, x) == 0 && + Double.compare(other.y, y) == 0 && + Double.compare(other.z, z) == 0 && + Float.compare(other.yaw, yaw) == 0 && + Float.compare(other.pitch, pitch) == 0; + } + + return false; + } /** @@ -114,14 +121,9 @@ public boolean equals(Object obj) { * * @return a hash code based on the fields of the object. */ + @Override public int hashCode() { - int result = 0; - result = 31 * result + Double.hashCode(x); - result = 31 * result + Double.hashCode(y); - result = 31 * result + Double.hashCode(z); - result = 31 * result + Float.floatToIntBits(yaw); - result = 31 * result + Float.floatToIntBits(pitch); - return result; + return Objects.hash(x, y, z, yaw, pitch); } } diff --git a/src/main/java/de/codeblocksmc/codelib/util/ParticleUtil.java b/src/main/java/de/codeblocksmc/codelib/util/ParticleUtil.java index e01ed6f..0b5b161 100644 --- a/src/main/java/de/codeblocksmc/codelib/util/ParticleUtil.java +++ b/src/main/java/de/codeblocksmc/codelib/util/ParticleUtil.java @@ -1,12 +1,20 @@ package de.codeblocksmc.codelib.util; +import com.google.common.util.concurrent.AtomicDouble; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.World; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.Vector; +/* + * @author Try + * @version 1.1 + */ + public class ParticleUtil { public static void spawnParticleCircle(Location center, double radius, Particle particle, int points) { World world = center.getWorld(); @@ -25,29 +33,25 @@ public static void spawnRotatingCircle(Location center, double radius, Particle World world = center.getWorld(); if (world == null) return; - new BukkitRunnable() { - int ticks = 0; - double angleOffset = 0; - @Override - public void run() { - if (ticks >= durationTicks) { - cancel(); - return; - } - for (int i = 0; i < points; i++) { - double angle = 2 * Math.PI * i / points + angleOffset; - double x = Math.cos(angle) * radius; - double z = Math.sin(angle) * radius; - Location loc = center.clone().add(new Vector(x, 0, z)); - world.spawnParticle(particle, loc, 1, 0, 0, 0, 0); - } - angleOffset += angularVelocity; - ticks += 2; + final AtomicDouble angleOffset = new AtomicDouble(0); + + BukkitTask particleTask = Bukkit.getScheduler().runTaskTimer(plugin,()->{ + + for (int i = 0; i < points; i++) { + double angle = 2 * Math.PI * i / points + angleOffset.get(); + double x = Math.cos(angle) * radius; + double z = Math.sin(angle) * radius; + Location loc = center.clone().add(new Vector(x, 0, z)); + world.spawnParticle(particle, loc, 1, 0, 0, 0, 0); } - }.runTaskTimer(plugin, 0, 2L); + angleOffset.addAndGet(angularVelocity); + + }, 0, 2L); + + Bukkit.getScheduler().runTaskLater(plugin, particleTask::cancel, durationTicks); } diff --git a/src/main/java/de/codeblocksmc/codelib/util/ServerConnector.java b/src/main/java/de/codeblocksmc/codelib/util/ServerConnector.java index 6d4ea1a..86d6a0e 100644 --- a/src/main/java/de/codeblocksmc/codelib/util/ServerConnector.java +++ b/src/main/java/de/codeblocksmc/codelib/util/ServerConnector.java @@ -1,11 +1,15 @@ package de.codeblocksmc.codelib.util; import io.github.leonardosnt.bungeechannelapi.BungeeChannelApi; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitRunnable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; /** * This class handles the connection of players to available servers, taking into account party-related restrictions. @@ -18,9 +22,15 @@ * This class operates asynchronously, querying the BungeeCord server list and checking for server availability. * * @author JustCody - * @version 1.0 + * @author Try + * @version 1.1 */ public class ServerConnector { + private final ConcurrentHashMap serverMaxPlayerCount = new ConcurrentHashMap<>(); + + @Setter + @Getter + private int defaultMaxPlayerCount = 30; // Prefix that is used for messages sent to players private final String prefix; @@ -56,59 +66,64 @@ protected ServerConnector(JavaPlugin plugin, String prefix) { *

* The method will search for a server that is less than 30 players, and if found, it will connect the player to it. * - * @param player The player to be connected. - * @param servername The name of the server to connect to (partial match). + * @param player The player to be connected. + * @param serverPattern A pattern to match server names. + * @param searchDescription The description which is show to the player when the searching is starting. */ - public void connect(Player player, String servername) { - // Check if the player is in a party and not the leader - //TODO: Use new party system + public void connect(Player player, Pattern serverPattern, String searchDescription) { + + //If the pattern is not known register it with the default player count. + if (!serverMaxPlayerCount.containsKey(serverPattern)) + serverMaxPlayerCount.put(serverPattern, defaultMaxPlayerCount); + - // Notify the player that the search for a free server is starting - player.sendMessage(prefix + "§aLooking for free server in §e" + servername + "§a..."); + player.sendMessage(prefix + "§aLooking for free server in §e" + searchDescription + "§a..."); - // Get the BungeeChannelApi instance to interact with BungeeCord BungeeChannelApi api = BungeeChannelApi.of(plugin); - // Run the connection task asynchronously - new BukkitRunnable() { - - @Override - public void run() { - // Fetch the list of available servers - api.getServers().whenComplete((result, error) -> { - AtomicBoolean found = new AtomicBoolean(false); - - // Loop through the servers and check if one matches the specified servername - for (String server : result) { - if (!server.startsWith(servername)) continue; - - // Get the player count for the current server - api.getPlayerCount(server).whenComplete((count, err) -> { - // If the server has less than 30 players, connect the player - if (count < 30) { - api.connect(player, server); - found.set(true); - } - }); - } + Bukkit.getScheduler().runTaskLater(plugin, () -> { + api.getServers().whenComplete((result, error) -> { + AtomicBoolean found = new AtomicBoolean(false); + - // Notify the player if no free server was found after the search - new BukkitRunnable() { - @Override - public void run() { - try { - if (!found.get()) { - player.sendMessage(prefix + "§7We could not find a free server. Sorry for the inconvenience!"); - } - } catch (Exception e) { - // Handle any errors when notifying the player - plugin.getLogger().warning(e.getMessage()); - } + for (String server : result) { + if (!serverPattern.matcher(server).hasMatch()) continue; + + + + api.getPlayerCount(server).whenComplete((count, err) -> { + + if (count < serverMaxPlayerCount.get(serverPattern)) { + api.connect(player, server); + found.set(true); } - }.runTaskLater(plugin, 5); // Delay to allow for the server search to complete - }); - } + }); + + //stop the search if a server is found + if(found.get()) + break; + } + + //There is no reason to start a task if the server is found. + if (found.get()) return; + + Bukkit.getScheduler().runTaskLater(plugin, () -> { + + try { + player.sendMessage(prefix + "§7We could not find a free server. Sorry for the inconvenience!"); + } catch (Exception e) { + plugin.getLogger().warning(e.getMessage()); + } + + }, 5); + }); + + }, 0); + + } + - }.runTaskLater(plugin, 0); // Run the task immediately + public void setServerMaxPlayerCount(Pattern serverPattern, int playerCount) { + this.serverMaxPlayerCount.put(serverPattern, playerCount); } }