2015-03-29 00:03:24 +01:00
/ *
2020-01-07 21:27:27 +01:00
* Copyright ( C ) 2020 GeorgH93
2015-03-29 00:03:24 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2023-06-15 20:07:38 +02:00
* along with this program . If not , see < https : //www.gnu.org/licenses/>.
2015-03-29 00:03:24 +01:00
* /
2016-12-19 22:06:08 +01:00
package at.pcgamingfreaks.Minepacks.Bukkit.Database ;
2015-03-29 00:03:24 +01:00
2019-05-18 15:50:15 +02:00
import at.pcgamingfreaks.Database.ConnectionProvider.ConnectionProvider ;
2016-12-19 22:06:08 +01:00
import at.pcgamingfreaks.Database.DBTools ;
import at.pcgamingfreaks.Minepacks.Bukkit.API.Callback ;
import at.pcgamingfreaks.Minepacks.Bukkit.Backpack ;
import at.pcgamingfreaks.Minepacks.Bukkit.Minepacks ;
2018-06-04 13:14:15 +02:00
import at.pcgamingfreaks.Utils ;
2016-03-01 00:39:28 +01:00
import org.bukkit.Bukkit ;
2015-03-29 00:03:24 +01:00
import org.bukkit.OfflinePlayer ;
import org.bukkit.entity.Player ;
import org.bukkit.inventory.ItemStack ;
2018-04-30 01:51:52 +02:00
import org.intellij.lang.annotations.Language ;
2019-05-18 15:50:15 +02:00
import org.jetbrains.annotations.NotNull ;
2015-03-29 00:03:24 +01:00
2016-03-21 00:59:25 +01:00
import java.sql.* ;
2015-03-29 00:03:24 +01:00
2015-09-24 17:06:00 +02:00
public abstract class SQL extends Database
2018-06-07 22:10:11 +02:00
{
2020-04-27 00:59:35 +02:00
private final ConnectionProvider dataSource ;
2016-03-01 00:39:28 +01:00
2017-01-24 20:16:21 +01:00
protected String tablePlayers , tableBackpacks , tableCooldowns ; // Table Names
protected String fieldPlayerName , fieldPlayerID , fieldPlayerUUID , fieldBpOwner , fieldBpIts , fieldBpVersion , fieldBpLastUpdate , fieldCdPlayer , fieldCdTime ; // Table Fields
2022-07-08 21:26:09 +02:00
@Language ( " SQL " ) protected String queryUpdatePlayerAdd , queryGetPlayerID , queryInsertBp , queryUpdateBp , queryGetBP , queryDeleteOldBackpacks ; // DB Querys
2018-04-30 01:51:52 +02:00
@Language ( " SQL " ) protected String queryDeleteOldCooldowns , querySyncCooldown , queryGetCooldown ; // DB Querys
2019-07-03 19:30:14 +02:00
protected boolean syncCooldown ;
2016-03-01 00:39:28 +01:00
2019-05-18 15:50:15 +02:00
public SQL ( @NotNull Minepacks plugin , @NotNull ConnectionProvider connectionProvider )
2015-03-29 00:03:24 +01:00
{
2018-08-05 21:59:03 +02:00
super ( plugin ) ;
2015-09-24 17:06:00 +02:00
2019-05-18 15:50:15 +02:00
dataSource = connectionProvider ;
2020-04-27 00:59:35 +02:00
if ( ! dataSource . isAvailable ( ) ) throw new IllegalStateException ( " Failed to initialize database connection! " ) ;
2016-03-01 00:39:28 +01:00
2015-09-24 17:06:00 +02:00
loadSettings ( ) ;
buildQuerys ( ) ;
checkDB ( ) ;
2019-12-01 23:25:38 +01:00
checkUUIDs ( ) ; // Check if there are user accounts without UUID
2015-09-24 17:06:00 +02:00
// Delete old backpacks
if ( maxAge > 0 )
{
2017-01-30 08:00:43 +01:00
try ( Connection connection = getConnection ( ) ; Statement statement = connection . createStatement ( ) )
2015-09-24 17:06:00 +02:00
{
2017-01-30 08:00:43 +01:00
statement . execute ( queryDeleteOldBackpacks ) ;
}
catch ( SQLException e )
{
e . printStackTrace ( ) ;
}
}
// Delete old cooldowns
if ( syncCooldown )
{
try ( Connection connection = getConnection ( ) )
{
DBTools . runStatement ( connection , queryDeleteOldCooldowns , System . currentTimeMillis ( ) ) ;
2015-09-24 17:06:00 +02:00
}
2016-03-01 00:39:28 +01:00
catch ( SQLException e )
2015-09-24 17:06:00 +02:00
{
e . printStackTrace ( ) ;
}
}
}
protected void loadSettings ( )
{
// Load table and field names
2018-06-07 00:30:48 +02:00
tablePlayers = plugin . getConfiguration ( ) . getUserTable ( ) ;
tableBackpacks = plugin . getConfiguration ( ) . getBackpackTable ( ) ;
tableCooldowns = plugin . getConfiguration ( ) . getCooldownTable ( ) ;
fieldPlayerID = plugin . getConfiguration ( ) . getDBFields ( " User.Player_ID " , " id " ) ;
fieldPlayerName = plugin . getConfiguration ( ) . getDBFields ( " User.Name " , " name " ) ;
fieldPlayerUUID = plugin . getConfiguration ( ) . getDBFields ( " User.UUID " , " uuid " ) ;
fieldBpOwner = plugin . getConfiguration ( ) . getDBFields ( " Backpack.Owner_ID " , " owner " ) ;
fieldBpIts = plugin . getConfiguration ( ) . getDBFields ( " Backpack.ItemStacks " , " its " ) ;
fieldBpVersion = plugin . getConfiguration ( ) . getDBFields ( " Backpack.Version " , " version " ) ;
fieldBpLastUpdate = plugin . getConfiguration ( ) . getDBFields ( " Backpack.LastUpdate " , " lastUpdate " ) ;
fieldCdPlayer = plugin . getConfiguration ( ) . getDBFields ( " Cooldown.Player_ID " , " id " ) ;
fieldCdTime = plugin . getConfiguration ( ) . getDBFields ( " Cooldown.Time " , " time " ) ;
syncCooldown = plugin . getConfiguration ( ) . isCommandCooldownSyncEnabled ( ) ;
2015-03-29 00:03:24 +01:00
}
2016-03-01 00:39:28 +01:00
2016-03-26 16:10:41 +01:00
@Override
2015-09-16 13:31:39 +02:00
public void close ( )
2015-04-01 20:56:55 +02:00
{
2016-12-19 22:06:08 +01:00
super . close ( ) ;
2018-06-04 13:14:15 +02:00
Utils . blockThread ( 1 ) ; // Give the database some time to perform async operations
2016-03-01 00:39:28 +01:00
dataSource . close ( ) ;
2015-09-24 17:06:00 +02:00
}
protected void checkUUIDs ( )
{
2016-03-21 00:59:25 +01:00
try ( Connection connection = getConnection ( ) )
2015-09-24 17:06:00 +02:00
{
2022-07-08 21:26:09 +02:00
DBTools . validateUUIDs ( plugin . getLogger ( ) , connection , tablePlayers , fieldPlayerName , fieldPlayerUUID , fieldPlayerID , useUUIDSeparators , onlineUUIDs ) ;
2015-09-24 17:06:00 +02:00
}
2016-03-01 00:39:28 +01:00
catch ( SQLException e )
2015-09-24 17:06:00 +02:00
{
e . printStackTrace ( ) ;
}
2015-04-01 20:56:55 +02:00
}
2015-09-24 17:06:00 +02:00
2018-08-05 21:59:03 +02:00
public Connection getConnection ( ) throws SQLException
2016-03-01 00:39:28 +01:00
{
return dataSource . getConnection ( ) ;
}
2015-09-24 17:06:00 +02:00
protected abstract void checkDB ( ) ;
2016-03-01 00:39:28 +01:00
2015-09-24 17:06:00 +02:00
protected final void buildQuerys ( )
2015-03-29 00:03:24 +01:00
{
2015-09-24 17:06:00 +02:00
// Build the SQL querys with placeholders for the table and field names
2019-12-01 23:25:38 +01:00
queryGetBP = " SELECT {FieldBPOwner},{FieldBPITS},{FieldBPVersion} FROM {TableBackpacks} INNER JOIN {TablePlayers} ON {TableBackpacks}.{FieldBPOwner}={TablePlayers}.{FieldPlayerID} WHERE {FieldUUID}=?; " ;
querySyncCooldown = " INSERT INTO {TableCooldowns} ({FieldCDPlayer},{FieldCDTime}) SELECT {FieldPlayerID},? FROM {TablePlayers} WHERE {FieldUUID}=? ON DUPLICATE KEY UPDATE {FieldCDTime}=?; " ;
queryUpdatePlayerAdd = " INSERT INTO {TablePlayers} ({FieldName},{FieldUUID}) VALUES (?,?) ON DUPLICATE KEY UPDATE {FieldName}=?; " ;
queryGetPlayerID = " SELECT {FieldPlayerID} FROM {TablePlayers} WHERE {FieldUUID}=?; " ;
queryGetCooldown = " SELECT * FROM {TableCooldowns} WHERE {FieldCDPlayer} IN (SELECT {FieldPlayerID} FROM {TablePlayers} WHERE {FieldUUID}=?); " ;
2018-04-02 18:27:27 +02:00
queryInsertBp = " REPLACE INTO {TableBackpacks} ({FieldBPOwner},{FieldBPITS},{FieldBPVersion}) VALUES (?,?,?); " ;
2017-01-30 08:00:43 +01:00
queryUpdateBp = " UPDATE {TableBackpacks} SET {FieldBPITS}=?,{FieldBPVersion}=?,{FieldBPLastUpdate}={NOW} WHERE {FieldBPOwner}=?; " ;
2017-01-24 20:16:21 +01:00
queryDeleteOldBackpacks = " DELETE FROM {TableBackpacks} WHERE {FieldBPLastUpdate} < DATE('now', '-{VarMaxAge} days') " ;
2017-01-30 08:00:43 +01:00
queryDeleteOldCooldowns = " DELETE FROM {TableCooldowns} WHERE {FieldCDTime}<?; " ;
2015-09-24 17:06:00 +02:00
updateQuerysForDialect ( ) ;
2016-12-19 22:06:08 +01:00
setTableAndFieldNames ( ) ;
}
protected void setTableAndFieldNames ( )
{
2015-09-24 17:06:00 +02:00
// Replace the table and filed names with the names from the config
2016-12-19 22:06:08 +01:00
queryUpdatePlayerAdd = replacePlaceholders ( queryUpdatePlayerAdd ) ;
queryGetPlayerID = replacePlaceholders ( queryGetPlayerID ) ;
queryGetBP = replacePlaceholders ( queryGetBP ) ;
2017-01-30 08:00:43 +01:00
queryInsertBp = replacePlaceholders ( queryInsertBp ) ;
queryUpdateBp = replacePlaceholders ( queryUpdateBp ) ;
2016-12-19 22:06:08 +01:00
queryDeleteOldBackpacks = replacePlaceholders ( queryDeleteOldBackpacks . replaceAll ( " \\ {VarMaxAge} " , maxAge + " " ) ) ;
2017-01-24 20:16:21 +01:00
querySyncCooldown = replacePlaceholders ( querySyncCooldown ) ;
2018-06-07 22:10:11 +02:00
queryGetCooldown = replacePlaceholders ( queryGetCooldown ) ;
2017-01-30 08:00:43 +01:00
queryDeleteOldCooldowns = replacePlaceholders ( queryDeleteOldCooldowns ) ;
2015-03-29 00:03:24 +01:00
}
2015-09-24 17:06:00 +02:00
protected abstract void updateQuerysForDialect ( ) ;
2018-04-30 01:51:52 +02:00
protected String replacePlaceholders ( @Language ( " SQL " ) String query )
2016-12-19 22:06:08 +01:00
{
return query . replaceAll ( " ( \\ { \\ w+}) " , " `$1` " ) . replaceAll ( " `( \\ { \\ w+})`_( \\ w+) " , " `$1_$2` " ) . replaceAll ( " fk_`( \\ { \\ w+})`_`( \\ { \\ w+})`_`( \\ { \\ w+})` " , " `fk_$1_$2_$3` " ) // Fix name formatting
. replaceAll ( " \\ {TablePlayers} " , tablePlayers ) . replaceAll ( " \\ {FieldName} " , fieldPlayerName ) . replaceAll ( " \\ {FieldUUID} " , fieldPlayerUUID ) . replaceAll ( " \\ {FieldPlayerID} " , fieldPlayerID ) // Players
. replaceAll ( " \\ {TableBackpacks} " , tableBackpacks ) . replaceAll ( " \\ {FieldBPOwner} " , fieldBpOwner ) . replaceAll ( " \\ {FieldBPITS} " , fieldBpIts ) // Backpacks
2017-01-24 20:16:21 +01:00
. replaceAll ( " \\ {FieldBPVersion} " , fieldBpVersion ) . replaceAll ( " \\ {FieldBPLastUpdate} " , fieldBpLastUpdate ) // Backpacks
. replaceAll ( " \\ {TableCooldowns} " , tableCooldowns ) . replaceAll ( " \\ {FieldCDPlayer} " , fieldCdPlayer ) . replaceAll ( " \\ {FieldCDTime} " , fieldCdTime ) ; // Cooldowns
2016-12-19 22:06:08 +01:00
}
2016-03-06 20:29:12 +01:00
protected void runStatementAsync ( final String query , final Object . . . args )
2015-03-29 00:03:24 +01:00
{
2017-06-10 20:30:39 +02:00
Bukkit . getServer ( ) . getScheduler ( ) . runTaskAsynchronously ( plugin , ( ) - > runStatement ( query , args ) ) ;
2015-03-29 00:03:24 +01:00
}
2016-03-06 20:29:12 +01:00
protected void runStatement ( final String query , final Object . . . args )
2015-09-24 17:06:00 +02:00
{
2016-03-01 00:39:28 +01:00
try ( Connection connection = getConnection ( ) ; PreparedStatement preparedStatement = connection . prepareStatement ( query ) )
2015-09-24 17:06:00 +02:00
{
2016-03-01 00:39:28 +01:00
for ( int i = 0 ; args ! = null & & i < args . length ; i + + )
2015-09-24 17:06:00 +02:00
{
2016-03-01 00:39:28 +01:00
preparedStatement . setObject ( i + 1 , args [ i ] ) ;
2015-09-24 17:06:00 +02:00
}
2016-03-01 00:39:28 +01:00
preparedStatement . execute ( ) ;
2015-09-24 17:06:00 +02:00
}
2016-03-01 00:39:28 +01:00
catch ( SQLException e )
2015-09-24 17:06:00 +02:00
{
2019-07-03 19:30:14 +02:00
plugin . getLogger ( ) . severe ( " Query: " + query ) ;
2015-09-24 17:06:00 +02:00
e . printStackTrace ( ) ;
}
}
2016-03-01 00:39:28 +01:00
// Plugin Functions
2016-03-26 16:10:41 +01:00
@Override
2016-03-01 00:39:28 +01:00
public void updatePlayer ( final Player player )
2015-03-29 00:03:24 +01:00
{
2019-12-01 23:25:38 +01:00
runStatementAsync ( queryUpdatePlayerAdd , player . getName ( ) , getPlayerFormattedUUID ( player ) , player . getName ( ) ) ;
2016-03-01 00:39:28 +01:00
}
2016-03-26 16:10:41 +01:00
@Override
2016-03-01 00:39:28 +01:00
public void saveBackpack ( final Backpack backpack )
{
final byte [ ] data = itsSerializer . serialize ( backpack . getInventory ( ) ) ;
final int id = backpack . getOwnerID ( ) , usedSerializer = itsSerializer . getUsedSerializer ( ) ;
2019-12-01 23:25:38 +01:00
final String nameOrUUID = getPlayerFormattedUUID ( backpack . getOwner ( ) ) , name = backpack . getOwner ( ) . getName ( ) ;
2016-03-01 00:39:28 +01:00
2019-07-13 01:08:41 +02:00
Runnable runnable = ( ) - > {
2017-06-10 20:30:39 +02:00
try ( Connection connection = getConnection ( ) )
2015-03-29 00:03:24 +01:00
{
2017-06-10 20:30:39 +02:00
if ( id < = 0 )
2015-09-24 17:06:00 +02:00
{
2017-06-10 20:30:39 +02:00
try ( PreparedStatement ps = connection . prepareStatement ( queryGetPlayerID ) )
2016-03-01 00:39:28 +01:00
{
2017-06-10 20:30:39 +02:00
ps . setString ( 1 , nameOrUUID ) ;
try ( ResultSet rs = ps . executeQuery ( ) )
2016-03-01 00:39:28 +01:00
{
2017-06-10 20:30:39 +02:00
if ( rs . next ( ) )
2016-03-01 00:39:28 +01:00
{
2018-06-07 22:10:11 +02:00
final int newID = rs . getInt ( fieldPlayerID ) ;
2017-06-10 20:30:39 +02:00
DBTools . runStatement ( connection , queryInsertBp , newID , data , usedSerializer ) ;
plugin . getServer ( ) . getScheduler ( ) . runTask ( plugin , ( ) - > backpack . setOwnerID ( newID ) ) ;
}
else
{
plugin . getLogger ( ) . warning ( " Failed saving backpack for: " + name + " (Unable to get players ID from database) " ) ;
2018-07-25 18:49:54 +02:00
writeBackup ( name , nameOrUUID , usedSerializer , data ) ;
2016-03-01 00:39:28 +01:00
}
}
}
}
2017-06-10 20:30:39 +02:00
else
2016-03-01 00:39:28 +01:00
{
2017-06-10 20:30:39 +02:00
DBTools . runStatement ( connection , queryUpdateBp , data , usedSerializer , id ) ;
2015-09-24 17:06:00 +02:00
}
2015-03-29 00:03:24 +01:00
}
2017-06-10 20:30:39 +02:00
catch ( SQLException e )
{
2018-05-23 20:16:50 +02:00
plugin . getLogger ( ) . warning ( " Failed to save backpack in database! Error: " + e . getMessage ( ) ) ;
2017-06-10 20:30:39 +02:00
e . printStackTrace ( ) ;
2018-07-25 18:49:54 +02:00
writeBackup ( name , nameOrUUID , usedSerializer , data ) ;
2017-06-10 20:30:39 +02:00
}
2019-07-13 01:08:41 +02:00
} ;
if ( asyncSave ) Bukkit . getScheduler ( ) . runTaskAsynchronously ( plugin , runnable ) ; else runnable . run ( ) ;
2016-03-01 00:39:28 +01:00
}
@Override
protected void loadBackpack ( final OfflinePlayer player , final Callback < Backpack > callback )
{
2017-06-10 20:30:39 +02:00
plugin . getServer ( ) . getScheduler ( ) . runTaskAsynchronously ( plugin , ( ) - > {
try ( Connection conn = getConnection ( ) ; PreparedStatement ps = conn . prepareStatement ( queryGetBP ) )
2015-03-29 00:03:24 +01:00
{
2019-12-01 23:25:38 +01:00
ps . setString ( 1 , getPlayerFormattedUUID ( player ) ) ;
2017-06-10 20:30:39 +02:00
final int bpID , version ;
final byte [ ] data ;
try ( ResultSet rs = ps . executeQuery ( ) )
2016-03-01 00:39:28 +01:00
{
2017-06-10 20:30:39 +02:00
if ( rs . next ( ) )
2016-03-01 00:39:28 +01:00
{
2018-06-07 22:10:11 +02:00
bpID = rs . getInt ( fieldBpOwner ) ;
version = rs . getInt ( fieldBpVersion ) ;
data = rs . getBytes ( fieldBpIts ) ;
2016-03-01 00:39:28 +01:00
}
2017-06-10 20:30:39 +02:00
else
2016-03-01 00:39:28 +01:00
{
2017-06-10 20:30:39 +02:00
bpID = - 1 ;
version = 0 ;
data = null ;
}
2016-03-01 00:39:28 +01:00
}
2019-04-26 02:51:29 +02:00
ItemStack [ ] its = itsSerializer . deserialize ( data , version ) ;
final Backpack backpack = ( its ! = null ) ? new Backpack ( player , its , bpID ) : null ;
2017-06-10 20:30:39 +02:00
plugin . getServer ( ) . getScheduler ( ) . runTask ( plugin , ( ) - > {
2019-04-26 02:51:29 +02:00
if ( backpack ! = null )
2017-01-23 06:08:47 +01:00
{
2019-04-26 02:51:29 +02:00
callback . onResult ( backpack ) ;
2017-06-10 20:30:39 +02:00
}
else
{
callback . onFail ( ) ;
}
} ) ;
}
catch ( SQLException e )
{
e . printStackTrace ( ) ;
plugin . getServer ( ) . getScheduler ( ) . runTask ( plugin , callback : : onFail ) ;
2015-03-29 00:03:24 +01:00
}
2016-03-01 00:39:28 +01:00
} ) ;
2015-03-29 00:03:24 +01:00
}
2017-01-24 20:16:21 +01:00
@Override
public void syncCooldown ( Player player , long cooldownTime )
{
2019-07-03 19:30:14 +02:00
Timestamp ts = new Timestamp ( cooldownTime ) ;
2019-12-01 23:25:38 +01:00
runStatementAsync ( querySyncCooldown , ts , getPlayerFormattedUUID ( player ) , ts ) ;
2017-01-24 20:16:21 +01:00
}
2018-06-07 22:10:11 +02:00
@Override
public void getCooldown ( final Player player , final Callback < Long > callback )
{
plugin . getServer ( ) . getScheduler ( ) . runTaskAsynchronously ( plugin , ( ) - > {
try ( Connection conn = getConnection ( ) ; PreparedStatement ps = conn . prepareStatement ( queryGetCooldown ) )
{
2019-12-01 23:25:38 +01:00
ps . setString ( 1 , getPlayerFormattedUUID ( player ) ) ;
2018-06-07 22:10:11 +02:00
try ( ResultSet rs = ps . executeQuery ( ) )
{
2021-04-13 01:13:18 +02:00
final long time = ( rs . next ( ) ) ? rs . getTimestamp ( fieldCdTime ) . getTime ( ) : 0 ;
2018-06-07 22:10:11 +02:00
plugin . getServer ( ) . getScheduler ( ) . runTask ( plugin , ( ) - > callback . onResult ( time ) ) ;
}
}
catch ( SQLException e )
{
e . printStackTrace ( ) ;
plugin . getServer ( ) . getScheduler ( ) . runTask ( plugin , ( ) - > callback . onResult ( 0L ) ) ;
}
} ) ;
}
2015-03-29 00:03:24 +01:00
}