2012-01-09 20:00:13 +01:00
package com.gmail.nossr50 ;
import java.sql.Connection ;
import java.sql.DriverManager ;
import java.sql.ResultSet ;
import java.sql.SQLException ;
2012-03-07 07:42:43 +01:00
import java.sql.PreparedStatement ;
2012-01-09 20:00:13 +01:00
import java.util.HashMap ;
import java.util.ArrayList ;
2012-03-07 07:42:43 +01:00
import java.util.Properties ;
2012-01-09 20:00:13 +01:00
2012-03-12 22:28:13 +01:00
import org.bukkit.Bukkit ;
2012-03-23 20:30:27 +01:00
import org.bukkit.entity.Player ;
2012-03-12 22:28:13 +01:00
2012-01-09 20:00:13 +01:00
import com.gmail.nossr50.config.LoadProperties ;
2012-03-07 22:38:48 +01:00
import com.gmail.nossr50.datatypes.DatabaseUpdate ;
2012-03-23 20:30:27 +01:00
import com.gmail.nossr50.datatypes.PlayerProfile ;
2012-03-07 07:42:43 +01:00
2012-01-09 20:00:13 +01:00
public class Database {
2012-03-07 07:42:43 +01:00
private String connectionString = " jdbc:mysql:// " + LoadProperties . MySQLserverName + " : " + LoadProperties . MySQLport + " / " + LoadProperties . MySQLdbName + " ?user= " + LoadProperties . MySQLuserName + " &password= " + LoadProperties . MySQLdbPass ;
private Connection conn = null ;
2012-03-22 20:59:26 +01:00
private mcMMO plugin = null ;
private long reconnectTimestamp = 0 ;
2012-03-07 07:42:43 +01:00
public Database ( mcMMO instance ) {
2012-03-22 20:59:26 +01:00
plugin = instance ;
2012-03-07 07:42:43 +01:00
connect ( ) ; //Connect to MySQL
// Load the driver instance
try {
Class . forName ( " com.mysql.jdbc.Driver " ) ;
DriverManager . getConnection ( connectionString ) ;
}
catch ( ClassNotFoundException e ) {
2012-03-12 22:28:13 +01:00
Bukkit . getLogger ( ) . warning ( e . getLocalizedMessage ( ) ) ;
2012-03-07 07:42:43 +01:00
}
catch ( SQLException ex ) {
2012-03-12 22:28:13 +01:00
Bukkit . getLogger ( ) . warning ( ex . getLocalizedMessage ( ) ) ;
2012-03-07 07:42:43 +01:00
printErrors ( ex ) ;
}
}
/ * *
* Attempt to connect to the mySQL database .
* /
public void connect ( ) {
try {
System . out . println ( " [mcMMO] Attempting connection to MySQL... " ) ;
Properties conProperties = new Properties ( ) ;
2012-03-22 20:59:26 +01:00
conProperties . put ( " autoReconnect " , " false " ) ;
conProperties . put ( " maxReconnects " , " 0 " ) ;
2012-03-07 07:42:43 +01:00
conn = DriverManager . getConnection ( connectionString , conProperties ) ;
2012-03-22 20:59:26 +01:00
System . out . println ( " [mcMMO] Connection to MySQL was a success! " ) ;
2012-03-07 07:42:43 +01:00
}
catch ( SQLException ex ) {
2012-03-22 20:59:26 +01:00
System . out . println ( " [mcMMO] Connection to MySQL failed! " ) ;
2012-03-07 07:42:43 +01:00
ex . printStackTrace ( ) ;
printErrors ( ex ) ;
}
}
/ * *
* Attempt to create the database structure .
* /
public void createStructure ( ) {
write ( " CREATE TABLE IF NOT EXISTS ` " + LoadProperties . MySQLtablePrefix + " huds` (`user_id` int(10) unsigned NOT NULL, "
+ " `hudtype` varchar(50) NOT NULL DEFAULT '', "
+ " PRIMARY KEY (`user_id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; " ) ;
write ( " CREATE TABLE IF NOT EXISTS ` " + LoadProperties . MySQLtablePrefix + " users` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, "
+ " `user` varchar(40) NOT NULL, "
+ " `lastlogin` int(32) unsigned NOT NULL, "
+ " `party` varchar(100) NOT NULL DEFAULT '', "
+ " PRIMARY KEY (`id`), "
+ " UNIQUE KEY `user` (`user`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1; " ) ;
write ( " CREATE TABLE IF NOT EXISTS ` " + LoadProperties . MySQLtablePrefix + " cooldowns` (`user_id` int(10) unsigned NOT NULL, "
+ " `taming` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `mining` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `woodcutting` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `repair` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `unarmed` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `herbalism` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `excavation` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `archery` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `swords` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `axes` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `acrobatics` int(32) unsigned NOT NULL DEFAULT '0', "
+ " `blast_mining` int(32) unsigned NOT NULL DEFAULT '0', "
+ " PRIMARY KEY (`user_id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; " ) ;
write ( " CREATE TABLE IF NOT EXISTS ` " + LoadProperties . MySQLtablePrefix + " skills` (`user_id` int(10) unsigned NOT NULL, "
+ " `taming` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `mining` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `woodcutting` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `repair` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `unarmed` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `herbalism` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `excavation` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `archery` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `swords` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `axes` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `acrobatics` int(10) unsigned NOT NULL DEFAULT '0', "
+ " PRIMARY KEY (`user_id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; " ) ;
write ( " CREATE TABLE IF NOT EXISTS ` " + LoadProperties . MySQLtablePrefix + " experience` (`user_id` int(10) unsigned NOT NULL, "
+ " `taming` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `mining` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `woodcutting` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `repair` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `unarmed` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `herbalism` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `excavation` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `archery` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `swords` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `axes` int(10) unsigned NOT NULL DEFAULT '0', "
+ " `acrobatics` int(10) unsigned NOT NULL DEFAULT '0', "
+ " PRIMARY KEY (`user_id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; " ) ;
2012-01-09 20:00:13 +01:00
2012-03-07 07:42:43 +01:00
checkDatabaseStructure ( DatabaseUpdate . FISHING ) ;
checkDatabaseStructure ( DatabaseUpdate . BLAST_MINING ) ;
}
/ * *
* Check database structure for missing values .
*
* @param update Type of data to check updates for
* /
public void checkDatabaseStructure ( DatabaseUpdate update ) {
String sql = null ;
2012-03-01 21:20:35 +01:00
ResultSet rs = null ;
HashMap < Integer , ArrayList < String > > Rows = new HashMap < Integer , ArrayList < String > > ( ) ;
2012-03-07 07:42:43 +01:00
switch ( update ) {
case BLAST_MINING :
sql = " SELECT * FROM ` " + LoadProperties . MySQLtablePrefix + " cooldowns` ORDER BY ` " + LoadProperties . MySQLtablePrefix + " cooldowns`.`blast_mining` ASC LIMIT 0 , 30 " ;
break ;
case FISHING :
sql = " SELECT * FROM ` " + LoadProperties . MySQLtablePrefix + " experience` ORDER BY ` " + LoadProperties . MySQLtablePrefix + " experience`.`fishing` ASC LIMIT 0 , 30 " ;
break ;
default :
break ;
}
2012-03-01 21:20:35 +01:00
try {
PreparedStatement stmt = conn . prepareStatement ( sql ) ;
if ( stmt . executeQuery ( ) ! = null ) {
stmt . executeQuery ( ) ;
rs = stmt . getResultSet ( ) ;
while ( rs . next ( ) ) {
ArrayList < String > Col = new ArrayList < String > ( ) ;
for ( int i = 1 ; i < = rs . getMetaData ( ) . getColumnCount ( ) ; i + + ) {
Col . add ( rs . getString ( i ) ) ;
}
Rows . put ( rs . getRow ( ) , Col ) ;
}
}
}
2012-03-07 07:42:43 +01:00
catch ( SQLException ex ) {
if ( update . equals ( DatabaseUpdate . BLAST_MINING ) ) {
System . out . println ( " Updating mcMMO MySQL tables for Blast Mining... " ) ;
write ( " ALTER TABLE ` " + LoadProperties . MySQLtablePrefix + " cooldowns` ADD `blast_mining` int(32) NOT NULL DEFAULT '0' ; " ) ;
}
else if ( update . equals ( DatabaseUpdate . FISHING ) ) {
System . out . println ( " Updating mcMMO MySQL tables for Fishing... " ) ;
write ( " ALTER TABLE ` " + LoadProperties . MySQLtablePrefix + " skills` ADD `fishing` int(10) NOT NULL DEFAULT '0' ; " ) ;
write ( " ALTER TABLE ` " + LoadProperties . MySQLtablePrefix + " experience` ADD `fishing` int(10) NOT NULL DEFAULT '0' ; " ) ;
}
}
}
2012-01-09 20:00:13 +01:00
2012-03-07 07:42:43 +01:00
/ * *
* Attempt to write the SQL query .
*
* @param sql Query to write .
* @return true if the query was successfully written , false otherwise .
* /
public boolean write ( String sql ) {
2012-03-22 20:59:26 +01:00
if ( isConnected ( ) ) {
2012-03-07 07:42:43 +01:00
try {
PreparedStatement stmt = conn . prepareStatement ( sql ) ;
stmt . executeUpdate ( ) ;
return true ;
}
catch ( SQLException ex ) {
printErrors ( ex ) ;
return false ;
}
}
else {
2012-03-22 20:59:26 +01:00
attemptReconnect ( ) ;
2012-03-07 07:42:43 +01:00
}
return false ;
}
/ * *
* Get the Integer . Only return first row / first field .
*
* @param sql SQL query to execute
* @return the value in the first row / first field
* /
public Integer getInt ( String sql ) {
ResultSet rs = null ;
Integer result = 0 ;
2012-01-09 20:00:13 +01:00
2012-03-22 20:59:26 +01:00
if ( isConnected ( ) ) {
2012-03-07 07:42:43 +01:00
try {
PreparedStatement stmt = conn . prepareStatement ( sql ) ;
stmt = conn . prepareStatement ( sql ) ;
if ( stmt . executeQuery ( ) ! = null ) {
stmt . executeQuery ( ) ;
rs = stmt . getResultSet ( ) ;
if ( rs . next ( ) ) {
result = rs . getInt ( 1 ) ;
}
else {
result = 0 ;
}
}
}
catch ( SQLException ex ) {
printErrors ( ex ) ;
}
}
else {
2012-03-22 20:59:26 +01:00
attemptReconnect ( ) ;
2012-03-07 07:42:43 +01:00
}
return result ;
}
2012-03-22 20:59:26 +01:00
/ * *
* Get connection status
*
* @return the boolean value for whether or not we are connected
* /
public boolean isConnected ( ) {
if ( conn = = null )
return false ;
try {
return conn . isValid ( 3 ) ;
} catch ( SQLException e ) {
return false ;
}
}
/ * *
* Schedules a Sync Delayed Task with the Bukkit Scheduler to attempt reconnection after a minute has elapsed
* This will check for a connection being present or not to prevent unneeded reconnection attempts
* /
public void attemptReconnect ( ) {
if ( reconnectTimestamp + 60000 < System . currentTimeMillis ( ) ) //Only reconnect if another attempt hasn't been made recently
{
System . out . println ( " [mcMMO] Connection to MySQL was lost! Attempting to reconnect in 60 seconds... " ) ;
reconnectTimestamp = System . currentTimeMillis ( ) ;
Bukkit . getScheduler ( ) . scheduleSyncDelayedTask ( plugin ,
new Runnable ( ) {
public void run ( ) {
if ( ! isConnected ( ) ) {
connect ( ) ;
2012-03-23 20:30:27 +01:00
if ( isConnected ( ) ) {
for ( PlayerProfile x : Users . players . values ( ) ) {
2012-03-23 20:34:23 +01:00
x . save ( ) ; //Save all profiles
2012-03-23 20:30:27 +01:00
}
Users . players . clear ( ) ; //Clear the profiles
for ( Player x : Bukkit . getOnlinePlayers ( ) ) {
Users . addUser ( x ) ; //Add in new profiles, forcing them to 'load' again from MySQL
}
}
2012-03-22 20:59:26 +01:00
}
}
} , 20 * 60 ) ;
}
}
2012-03-07 07:42:43 +01:00
/ * *
* Read SQL query .
*
* @param sql SQL query to read
* @return the rows in this SQL query
* /
public HashMap < Integer , ArrayList < String > > read ( String sql ) {
ResultSet rs = null ;
HashMap < Integer , ArrayList < String > > Rows = new HashMap < Integer , ArrayList < String > > ( ) ;
2012-03-22 20:59:26 +01:00
if ( isConnected ( ) ) {
2012-03-07 07:42:43 +01:00
try {
PreparedStatement stmt = conn . prepareStatement ( sql ) ;
if ( stmt . executeQuery ( ) ! = null ) {
stmt . executeQuery ( ) ;
rs = stmt . getResultSet ( ) ;
while ( rs . next ( ) ) {
ArrayList < String > Col = new ArrayList < String > ( ) ;
for ( int i = 1 ; i < = rs . getMetaData ( ) . getColumnCount ( ) ; i + + ) {
Col . add ( rs . getString ( i ) ) ;
}
Rows . put ( rs . getRow ( ) , Col ) ;
}
}
}
catch ( SQLException ex ) {
printErrors ( ex ) ;
}
}
else {
2012-03-22 20:59:26 +01:00
attemptReconnect ( ) ;
2012-03-07 07:42:43 +01:00
}
return Rows ;
}
private static void printErrors ( SQLException ex ) {
System . out . println ( " SQLException: " + ex . getMessage ( ) ) ;
System . out . println ( " SQLState: " + ex . getSQLState ( ) ) ;
System . out . println ( " VendorError: " + ex . getErrorCode ( ) ) ;
}
2012-03-22 20:59:26 +01:00
}