2012-07-17 03:17:12 +00:00
/ *
2017-08-23 15:37:25 +00:00
GriefPrevention Server Plugin for Minecraft
Copyright ( C ) 2012 Ryan Hamshire
2012-07-17 03:17:12 +00:00
2017-08-23 15:37:25 +00: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 .
2012-07-17 03:17:12 +00:00
2017-08-23 15:37:25 +00:00
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 .
2012-07-17 03:17:12 +00:00
2017-08-23 15:37:25 +00:00
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2012-07-17 03:17:12 +00:00
* /
package me.ryanhamshire.GriefPrevention ;
2015-05-17 02:17:11 +00:00
import java.io.PrintWriter ;
import java.io.StringWriter ;
2017-08-23 15:37:25 +00:00
import java.sql.* ;
2012-07-17 03:17:12 +00:00
import java.text.SimpleDateFormat ;
import java.util.* ;
2017-08-23 15:37:25 +00:00
import java.util.Date ;
2012-07-17 03:17:12 +00:00
import org.bukkit.* ;
//manages data stored in the file system
public class DatabaseDataStore extends DataStore
{
private Connection databaseConnection = null ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
private String databaseUrl ;
private String userName ;
private String password ;
2017-08-23 15:37:25 +00:00
private String updateNameSQL ;
private String insertClaimSQL ;
private String deleteClaimSQL ;
private String getPlayerDataSQL ;
private String deletePlayerDataSQL ;
private String insertPlayerDataSQL ;
private String insertNextClaimIdSQL ;
private String deleteGroupBonusSQL ;
private String insertSchemaVerSQL ;
private String deleteNextClaimIdSQL ;
private String deleteSchemaVersionSQL ;
private String selectSchemaVersionSQL ;
2012-07-17 03:17:12 +00:00
DatabaseDataStore ( String url , String userName , String password ) throws Exception
{
this . databaseUrl = url ;
this . userName = userName ;
this . password = password ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
this . initialize ( ) ;
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
@Override
void initialize ( ) throws Exception
{
try
{
//load the java driver for mySQL
Class . forName ( " com.mysql.jdbc.Driver " ) ;
}
catch ( Exception e )
{
GriefPrevention . AddLogEntry ( " ERROR: Unable to load Java's mySQL database driver. Check to make sure you've installed it properly. " ) ;
throw e ;
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
try
{
2013-01-25 03:45:39 +00:00
this . refreshDataConnection ( ) ;
2012-07-17 03:17:12 +00:00
}
catch ( Exception e2 )
{
GriefPrevention . AddLogEntry ( " ERROR: Unable to connect to database. Check your config file settings. " ) ;
throw e2 ;
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
try
{
//ensure the data tables exist
Statement statement = databaseConnection . createStatement ( ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
statement . execute ( " CREATE TABLE IF NOT EXISTS griefprevention_nextclaimid (nextid INT(15)); " ) ;
2017-07-22 01:54:24 +00:00
statement . execute ( " CREATE TABLE IF NOT EXISTS griefprevention_claimdata (id INT(15), owner VARCHAR(50), lessercorner VARCHAR(100), greatercorner VARCHAR(100), builders TEXT, containers TEXT, accessors TEXT, managers TEXT, inheritnothing BOOLEAN, parentid INT(15)); " ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
statement . execute ( " CREATE TABLE IF NOT EXISTS griefprevention_playerdata (name VARCHAR(50), lastlogin DATETIME, accruedblocks INT(15), bonusblocks INT(15)); " ) ;
2017-08-23 15:37:25 +00:00
2014-09-22 20:46:13 +00:00
statement . execute ( " CREATE TABLE IF NOT EXISTS griefprevention_schemaversion (version INT(15)); " ) ;
2017-08-23 15:37:25 +00:00
2015-10-04 03:19:24 +00:00
statement . execute ( " ALTER TABLE griefprevention_claimdata MODIFY builders TEXT; " ) ;
statement . execute ( " ALTER TABLE griefprevention_claimdata MODIFY containers TEXT; " ) ;
statement . execute ( " ALTER TABLE griefprevention_claimdata MODIFY accessors TEXT; " ) ;
statement . execute ( " ALTER TABLE griefprevention_claimdata MODIFY managers TEXT; " ) ;
2017-08-23 15:37:25 +00:00
2014-09-22 20:46:13 +00:00
//if the next claim id table is empty, this is a brand new database which will write using the latest schema
//otherwise, schema version is determined by schemaversion table (or =0 if table is empty, see getSchemaVersion())
ResultSet results = statement . executeQuery ( " SELECT * FROM griefprevention_nextclaimid; " ) ;
2017-08-23 15:37:25 +00:00
if ( ! results . next ( ) )
2014-09-22 20:46:13 +00:00
{
2017-08-23 15:37:25 +00:00
this . setSchemaVersion ( latestSchemaVersion ) ;
}
2012-07-17 03:17:12 +00:00
}
catch ( Exception e3 )
{
GriefPrevention . AddLogEntry ( " ERROR: Unable to create the necessary database table. Details: " ) ;
GriefPrevention . AddLogEntry ( e3 . getMessage ( ) ) ;
2014-10-09 02:32:43 +00:00
e3 . printStackTrace ( ) ;
2012-07-17 03:17:12 +00:00
throw e3 ;
}
2017-08-23 15:37:25 +00:00
this . updateNameSQL = " UPDATE griefprevention_playerdata SET name = ? WHERE name = ?; " ;
this . insertClaimSQL = " INSERT INTO griefprevention_claimdata (id, owner, lessercorner, greatercorner, builders, containers, accessors, managers, inheritnothing, parentid) VALUES(?,?,?,?,?,?,?,?,?,?); " ;
this . deleteClaimSQL = " DELETE FROM griefprevention_claimdata WHERE id=?; " ;
this . getPlayerDataSQL = " SELECT * FROM griefprevention_playerdata WHERE name=?; " ;
this . deletePlayerDataSQL = " DELETE FROM griefprevention_playerdata WHERE name=?; " ;
this . insertPlayerDataSQL = " INSERT INTO griefprevention_playerdata (name, lastlogin, accruedblocks, bonusblocks) VALUES (?,?,?,?); " ;
this . insertNextClaimIdSQL = " INSERT INTO griefprevention_nextclaimid VALUES (?); " ;
this . deleteGroupBonusSQL = " DELETE FROM griefprevention_playerdata WHERE name=?; " ;
this . insertSchemaVerSQL = " INSERT INTO griefprevention_schemaversion VALUES (?) " ;
this . deleteNextClaimIdSQL = " DELETE FROM griefprevention_nextclaimid; " ;
this . deleteSchemaVersionSQL = " DELETE FROM griefprevention_schemaversion; " ;
this . selectSchemaVersionSQL = " SELECT * FROM griefprevention_schemaversion; " ;
2012-07-17 03:17:12 +00:00
//load group data into memory
Statement statement = databaseConnection . createStatement ( ) ;
ResultSet results = statement . executeQuery ( " SELECT * FROM griefprevention_playerdata; " ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
while ( results . next ( ) )
{
String name = results . getString ( " name " ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//ignore non-groups. all group names start with a dollar sign.
if ( ! name . startsWith ( " $ " ) ) continue ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
String groupName = name . substring ( 1 ) ;
if ( groupName = = null | | groupName . isEmpty ( ) ) continue ; //defensive coding, avoid unlikely cases
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
int groupBonusBlocks = results . getInt ( " bonusblocks " ) ;
2017-08-23 15:37:25 +00:00
this . permissionToBonusBlocksMap . put ( groupName , groupBonusBlocks ) ;
2012-07-17 03:17:12 +00:00
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//load next claim number into memory
results = statement . executeQuery ( " SELECT * FROM griefprevention_nextclaimid; " ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//if there's nothing yet, add it
if ( ! results . next ( ) )
{
statement . execute ( " INSERT INTO griefprevention_nextclaimid VALUES(0); " ) ;
this . nextClaimID = ( long ) 0 ;
}
//otherwise load it
else
{
this . nextClaimID = results . getLong ( " nextid " ) ;
}
2017-08-23 15:37:25 +00:00
2014-10-09 02:32:43 +00:00
if ( this . getSchemaVersion ( ) = = 0 )
2017-08-23 15:37:25 +00:00
{
try
{
this . refreshDataConnection ( ) ;
//pull ALL player data from the database
statement = this . databaseConnection . createStatement ( ) ;
results = statement . executeQuery ( " SELECT * FROM griefprevention_playerdata; " ) ;
//make a list of changes to be made
HashMap < String , UUID > changes = new HashMap < String , UUID > ( ) ;
ArrayList < String > namesToConvert = new ArrayList < String > ( ) ;
while ( results . next ( ) )
{
//get the id
String playerName = results . getString ( " name " ) ;
//add to list of names to convert to UUID
namesToConvert . add ( playerName ) ;
}
//resolve and cache as many as possible through various means
try
{
UUIDFetcher fetcher = new UUIDFetcher ( namesToConvert ) ;
fetcher . call ( ) ;
}
catch ( Exception e )
{
GriefPrevention . AddLogEntry ( " Failed to resolve a batch of names to UUIDs. Details: " + e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
}
//reset results cursor
results . beforeFirst ( ) ;
//for each result
while ( results . next ( ) )
{
//get the id
String playerName = results . getString ( " name " ) ;
//try to convert player name to UUID
try
{
UUID playerID = UUIDFetcher . getUUIDOf ( playerName ) ;
//if successful, update the playerdata row by replacing the player's name with the player's UUID
if ( playerID ! = null )
{
changes . put ( playerName , playerID ) ;
}
}
//otherwise leave it as-is. no harm done - it won't be requested by name, and this update only happens once.
catch ( Exception ex ) { }
}
//refresh data connection in case data migration took a long time
this . refreshDataConnection ( ) ;
for ( String name : changes . keySet ( ) )
{
try ( PreparedStatement updateStmnt = this . databaseConnection . prepareStatement ( this . getUpdateNameSQL ( ) ) ) {
updateStmnt . setString ( 1 , changes . get ( name ) . toString ( ) ) ;
updateStmnt . setString ( 2 , name ) ;
updateStmnt . executeUpdate ( ) ;
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to convert player data for " + name + " . Skipping. " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
}
}
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to convert player data. Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
}
}
2017-07-22 01:54:24 +00:00
if ( this . getSchemaVersion ( ) < = 2 )
{
statement = this . databaseConnection . createStatement ( ) ;
statement . execute ( " ALTER TABLE griefprevention_claimdata ADD inheritNothing BOOLEAN DEFAULT 0 AFTER managers; " ) ;
}
2017-08-23 15:37:25 +00:00
//load claims data into memory
2012-07-17 03:17:12 +00:00
results = statement . executeQuery ( " SELECT * FROM griefprevention_claimdata; " ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
ArrayList < Claim > claimsToRemove = new ArrayList < Claim > ( ) ;
2014-10-13 20:22:55 +00:00
ArrayList < Claim > subdivisionsToLoad = new ArrayList < Claim > ( ) ;
2015-09-12 21:17:00 +00:00
List < World > validWorlds = Bukkit . getServer ( ) . getWorlds ( ) ;
2017-08-23 15:37:25 +00:00
2015-12-15 21:43:38 +00:00
Long claimID = null ;
2012-07-17 03:17:12 +00:00
while ( results . next ( ) )
{
try
2014-11-08 05:08:19 +00:00
{
2017-07-22 01:54:24 +00:00
//problematic claims will be removed from secondary storage, and never added to in-memory data store
boolean removeClaim = false ;
2017-08-23 15:37:25 +00:00
2017-07-22 01:54:24 +00:00
long parentId = results . getLong ( " parentid " ) ;
2015-12-15 21:43:38 +00:00
claimID = results . getLong ( " id " ) ;
2017-07-22 01:54:24 +00:00
boolean inheritNothing = results . getBoolean ( " inheritNothing " ) ;
2014-10-09 02:32:43 +00:00
Location lesserBoundaryCorner = null ;
Location greaterBoundaryCorner = null ;
2014-11-08 05:08:19 +00:00
String lesserCornerString = " (location not available) " ;
2014-10-09 02:32:43 +00:00
try
{
2017-07-22 01:54:24 +00:00
lesserCornerString = results . getString ( " lessercorner " ) ;
lesserBoundaryCorner = this . locationFromString ( lesserCornerString , validWorlds ) ;
String greaterCornerString = results . getString ( " greatercorner " ) ;
greaterBoundaryCorner = this . locationFromString ( greaterCornerString , validWorlds ) ;
2014-10-09 02:32:43 +00:00
}
catch ( Exception e )
{
2017-08-23 15:37:25 +00:00
if ( e . getMessage ( ) ! = null & & e . getMessage ( ) . contains ( " World not found " ) )
{
GriefPrevention . AddLogEntry ( " Failed to load a claim (ID: " + claimID . toString ( ) + " ) because its world isn't loaded (yet?). Please delete the claim or contact the GriefPrevention developer with information about which plugin(s) you're using to load or create worlds. " + lesserCornerString ) ;
continue ;
}
else
{
throw e ;
}
2014-10-09 02:32:43 +00:00
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
String ownerName = results . getString ( " owner " ) ;
2014-09-22 20:46:13 +00:00
UUID ownerID = null ;
2017-08-23 15:37:25 +00:00
if ( ownerName . isEmpty ( ) | | ownerName . startsWith ( " -- " ) )
{
ownerID = null ; //administrative land claim or subdivision
}
else if ( this . getSchemaVersion ( ) < 1 )
{
try
{
ownerID = UUIDFetcher . getUUIDOf ( ownerName ) ;
}
catch ( Exception ex )
{
GriefPrevention . AddLogEntry ( " This owner name did not convert to a UUID: " + ownerName + " . " ) ;
GriefPrevention . AddLogEntry ( " Converted land claim to administrative @ " + lesserBoundaryCorner . toString ( ) ) ;
}
}
else
{
try
{
ownerID = UUID . fromString ( ownerName ) ;
}
catch ( Exception ex )
{
GriefPrevention . AddLogEntry ( " This owner entry is not a UUID: " + ownerName + " . " ) ;
GriefPrevention . AddLogEntry ( " Converted land claim to administrative @ " + lesserBoundaryCorner . toString ( ) ) ;
}
}
2012-07-17 03:17:12 +00:00
String buildersString = results . getString ( " builders " ) ;
2015-09-12 21:17:00 +00:00
List < String > builderNames = Arrays . asList ( buildersString . split ( " ; " ) ) ;
2014-09-22 20:46:13 +00:00
builderNames = this . convertNameListToUUIDList ( builderNames ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
String containersString = results . getString ( " containers " ) ;
2015-09-12 21:17:00 +00:00
List < String > containerNames = Arrays . asList ( containersString . split ( " ; " ) ) ;
2014-09-22 20:46:13 +00:00
containerNames = this . convertNameListToUUIDList ( containerNames ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
String accessorsString = results . getString ( " accessors " ) ;
2015-09-12 21:17:00 +00:00
List < String > accessorNames = Arrays . asList ( accessorsString . split ( " ; " ) ) ;
2014-09-22 20:46:13 +00:00
accessorNames = this . convertNameListToUUIDList ( accessorNames ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
String managersString = results . getString ( " managers " ) ;
2015-09-12 21:17:00 +00:00
List < String > managerNames = Arrays . asList ( managersString . split ( " ; " ) ) ;
2014-09-22 20:46:13 +00:00
managerNames = this . convertNameListToUUIDList ( managerNames ) ;
2017-07-22 01:54:24 +00:00
Claim claim = new Claim ( lesserBoundaryCorner , greaterBoundaryCorner , ownerID , builderNames , containerNames , accessorNames , managerNames , inheritNothing , claimID ) ;
2017-08-23 15:37:25 +00:00
2014-11-08 05:08:19 +00:00
if ( removeClaim )
{
2017-08-23 15:37:25 +00:00
claimsToRemove . add ( claim ) ;
2014-11-08 05:08:19 +00:00
}
else if ( parentId = = - 1 )
2014-10-13 20:22:55 +00:00
{
2017-08-23 15:37:25 +00:00
//top level claim
this . addClaim ( claim , false ) ;
2014-10-13 20:22:55 +00:00
}
else
{
2017-08-23 15:37:25 +00:00
//subdivision
subdivisionsToLoad . add ( claim ) ;
2012-07-17 03:17:12 +00:00
}
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to load a claim. Details: " + e . getMessage ( ) + " ... " + results . toString ( ) ) ;
e . printStackTrace ( ) ;
}
}
2017-08-23 15:37:25 +00:00
2014-10-14 02:08:43 +00:00
//add subdivisions to their parent claims
2017-08-23 15:37:25 +00:00
for ( Claim childClaim : subdivisionsToLoad )
{
//find top level claim parent
Claim topLevelClaim = this . getClaimAt ( childClaim . getLesserBoundaryCorner ( ) , true , null ) ;
if ( topLevelClaim = = null )
{
claimsToRemove . add ( childClaim ) ;
GriefPrevention . AddLogEntry ( " Removing orphaned claim subdivision: " + childClaim . getLesserBoundaryCorner ( ) . toString ( ) ) ;
continue ;
}
//add this claim to the list of children of the current top level claim
childClaim . parent = topLevelClaim ;
topLevelClaim . children . add ( childClaim ) ;
childClaim . inDataStore = true ;
}
for ( Claim claim : claimsToRemove )
2012-07-17 03:17:12 +00:00
{
2017-08-23 15:37:25 +00:00
this . deleteClaimFromSecondaryStorage ( claim ) ;
2012-07-17 03:17:12 +00:00
}
2017-08-23 15:37:25 +00:00
2015-09-12 21:17:00 +00:00
if ( this . getSchemaVersion ( ) < = 2 )
{
2017-08-23 15:37:25 +00:00
this . refreshDataConnection ( ) ;
statement = this . databaseConnection . createStatement ( ) ;
statement . execute ( " DELETE FROM griefprevention_claimdata WHERE id='-1'; " ) ;
2015-09-12 21:17:00 +00:00
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
super . initialize ( ) ;
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
@Override
2012-08-08 04:46:31 +00:00
synchronized void writeClaimToStorage ( Claim claim ) //see datastore.cs. this will ALWAYS be a top level claim
2012-07-17 03:17:12 +00:00
{
try
{
2013-01-25 03:45:39 +00:00
this . refreshDataConnection ( ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//wipe out any existing data about this claim
this . deleteClaimFromSecondaryStorage ( claim ) ;
2017-08-23 15:37:25 +00:00
2015-09-12 21:17:00 +00:00
//write claim data to the database
2012-07-17 03:17:12 +00:00
this . writeClaimData ( claim ) ;
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to save data for claim at " + this . locationToString ( claim . lesserBoundaryCorner ) + " . Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
}
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//actually writes claim data to the database
2012-08-08 04:46:31 +00:00
synchronized private void writeClaimData ( Claim claim ) throws SQLException
2012-07-17 03:17:12 +00:00
{
String lesserCornerString = this . locationToString ( claim . getLesserBoundaryCorner ( ) ) ;
String greaterCornerString = this . locationToString ( claim . getGreaterBoundaryCorner ( ) ) ;
2014-09-22 20:46:13 +00:00
String owner = " " ;
if ( claim . ownerID ! = null ) owner = claim . ownerID . toString ( ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
ArrayList < String > builders = new ArrayList < String > ( ) ;
ArrayList < String > containers = new ArrayList < String > ( ) ;
ArrayList < String > accessors = new ArrayList < String > ( ) ;
ArrayList < String > managers = new ArrayList < String > ( ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
claim . getPermissions ( builders , containers , accessors , managers ) ;
2017-08-23 15:37:25 +00:00
String buildersString = this . storageStringBuilder ( builders ) ;
String containersString = this . storageStringBuilder ( containers ) ;
String accessorsString = this . storageStringBuilder ( accessors ) ;
String managersString = this . storageStringBuilder ( managers ) ;
2017-07-22 01:54:24 +00:00
boolean inheritNothing = claim . getSubclaimRestrictions ( ) ;
2017-08-23 15:37:25 +00:00
long parentId = claim . parent = = null ? - 1 : claim . parent . id ;
2017-07-22 01:54:24 +00:00
2017-08-23 15:37:25 +00:00
try ( PreparedStatement insertStmt = this . databaseConnection . prepareStatement ( this . getInsertClaimSQL ( ) ) ) {
insertStmt . setLong ( 1 , claim . id ) ;
insertStmt . setString ( 2 , owner ) ;
insertStmt . setString ( 3 , lesserCornerString ) ;
insertStmt . setString ( 4 , greaterCornerString ) ;
insertStmt . setString ( 5 , buildersString ) ;
insertStmt . setString ( 6 , containersString ) ;
insertStmt . setString ( 7 , accessorsString ) ;
insertStmt . setString ( 8 , managersString ) ;
insertStmt . setBoolean ( 9 , inheritNothing ) ;
insertStmt . setLong ( 10 , parentId ) ;
insertStmt . executeUpdate ( ) ;
2012-07-17 03:17:12 +00:00
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to save data for claim at " + this . locationToString ( claim . lesserBoundaryCorner ) + " . Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
}
}
2017-08-23 15:37:25 +00:00
2014-11-08 05:08:19 +00:00
//deletes a claim from the database
2012-07-17 03:17:12 +00:00
@Override
2012-08-08 04:46:31 +00:00
synchronized void deleteClaimFromSecondaryStorage ( Claim claim )
2012-07-17 03:17:12 +00:00
{
2017-08-23 15:37:25 +00:00
try ( PreparedStatement deleteStmnt = this . databaseConnection . prepareStatement ( this . getDeleteClaimSQL ( ) ) ) {
deleteStmnt . setLong ( 1 , claim . id ) ;
deleteStmnt . executeUpdate ( ) ;
2012-07-17 03:17:12 +00:00
}
catch ( SQLException e )
{
2014-10-09 02:32:43 +00:00
GriefPrevention . AddLogEntry ( " Unable to delete data for claim " + claim . id + " . Details: " ) ;
2012-07-17 03:17:12 +00:00
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
2014-10-09 02:32:43 +00:00
e . printStackTrace ( ) ;
2012-07-17 03:17:12 +00:00
}
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
@Override
2014-09-22 20:46:13 +00:00
synchronized PlayerData getPlayerDataFromStorage ( UUID playerID )
2012-07-17 03:17:12 +00:00
{
PlayerData playerData = new PlayerData ( ) ;
2014-09-22 20:46:13 +00:00
playerData . playerID = playerID ;
2017-08-23 15:37:25 +00:00
try ( PreparedStatement selectStmnt = this . databaseConnection . prepareStatement ( this . getGetPlayerDataSQL ( ) ) )
2012-07-17 03:17:12 +00:00
{
2017-08-23 15:37:25 +00:00
selectStmnt . setString ( 1 , playerID . toString ( ) ) ;
ResultSet results = selectStmnt . executeQuery ( ) ;
2014-10-11 04:27:12 +00:00
//if data for this player exists, use it
if ( results . next ( ) )
2016-10-08 02:29:36 +00:00
{
2014-10-31 02:24:07 +00:00
playerData . setAccruedClaimBlocks ( results . getInt ( " accruedblocks " ) ) ;
2017-08-23 15:37:25 +00:00
playerData . setBonusClaimBlocks ( results . getInt ( " bonusblocks " ) ) ;
2012-07-17 03:17:12 +00:00
}
}
catch ( SQLException e )
{
2017-08-23 15:37:25 +00:00
StringWriter errors = new StringWriter ( ) ;
e . printStackTrace ( new PrintWriter ( errors ) ) ;
GriefPrevention . AddLogEntry ( playerID + " " + errors . toString ( ) , CustomLogEntryTypes . Exception ) ;
2012-07-17 03:17:12 +00:00
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
return playerData ;
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//saves changes to player data. MUST be called after you're done making changes, otherwise a reload will lose them
@Override
2015-05-16 20:00:55 +00:00
public void overrideSavePlayerData ( UUID playerID , PlayerData playerData )
2012-07-17 03:17:12 +00:00
{
//never save data for the "administrative" account. an empty string for player name indicates administrative account
2014-09-22 20:46:13 +00:00
if ( playerID = = null ) return ;
2017-08-23 15:37:25 +00:00
2014-09-22 20:46:13 +00:00
this . savePlayerData ( playerID . toString ( ) , playerData ) ;
}
2017-08-23 15:37:25 +00:00
2014-09-22 20:46:13 +00:00
private void savePlayerData ( String playerID , PlayerData playerData )
{
2017-08-23 15:37:25 +00:00
try ( PreparedStatement deleteStmnt = this . databaseConnection . prepareStatement ( this . getDeletePlayerDataSQL ( ) ) ;
PreparedStatement insertStmnt = this . databaseConnection . prepareStatement ( this . getInsertPlayerDataSQL ( ) ) ) {
2016-10-08 02:29:36 +00:00
OfflinePlayer player = Bukkit . getOfflinePlayer ( UUID . fromString ( playerID ) ) ;
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
SimpleDateFormat sqlFormat = new SimpleDateFormat ( " yyyy-MM-dd HH:mm:ss " ) ;
2016-10-08 02:29:36 +00:00
String dateString = sqlFormat . format ( new Date ( player . getLastPlayed ( ) ) ) ;
2017-08-23 15:37:25 +00:00
deleteStmnt . setString ( 1 , playerID ) ;
deleteStmnt . executeUpdate ( ) ;
insertStmnt . setString ( 1 , playerID ) ;
insertStmnt . setString ( 2 , dateString ) ;
insertStmnt . setInt ( 3 , playerData . getAccruedClaimBlocks ( ) ) ;
insertStmnt . setInt ( 4 , playerData . getBonusClaimBlocks ( ) ) ;
insertStmnt . executeUpdate ( ) ;
2012-07-17 03:17:12 +00:00
}
catch ( SQLException e )
{
2017-08-23 15:37:25 +00:00
StringWriter errors = new StringWriter ( ) ;
e . printStackTrace ( new PrintWriter ( errors ) ) ;
GriefPrevention . AddLogEntry ( playerID + " " + errors . toString ( ) , CustomLogEntryTypes . Exception ) ;
2012-07-17 03:17:12 +00:00
}
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
@Override
2012-08-08 04:46:31 +00:00
synchronized void incrementNextClaimID ( )
2012-07-17 03:17:12 +00:00
{
this . setNextClaimID ( this . nextClaimID + 1 ) ;
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//sets the next claim ID. used by incrementNextClaimID() above, and also while migrating data from a flat file data store
2012-08-08 04:46:31 +00:00
synchronized void setNextClaimID ( long nextID )
2012-07-17 03:17:12 +00:00
{
this . nextClaimID = nextID ;
2017-08-23 15:37:25 +00:00
try ( PreparedStatement deleteStmnt = this . databaseConnection . prepareStatement ( this . getDeleteNextClaimIdSQL ( ) ) ;
PreparedStatement insertStmnt = this . databaseConnection . prepareStatement ( this . getInsertNextClaimIdSQL ( ) ) ) {
deleteStmnt . execute ( ) ;
insertStmnt . setLong ( 1 , nextID ) ;
insertStmnt . executeUpdate ( ) ;
2012-07-17 03:17:12 +00:00
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to set next claim ID to " + nextID + " . Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
}
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
//updates the database with a group's bonus blocks
@Override
2012-08-08 04:46:31 +00:00
synchronized void saveGroupBonusBlocks ( String groupName , int currentValue )
2012-07-17 03:17:12 +00:00
{
//group bonus blocks are stored in the player data table, with player name = $groupName
2017-08-23 15:37:25 +00:00
try ( PreparedStatement deleteStmnt = this . databaseConnection . prepareStatement ( this . getDeleteGroupBonusSQL ( ) ) ;
PreparedStatement insertStmnt = this . databaseConnection . prepareStatement ( this . getInsertPlayerDataSQL ( ) ) ) {
SimpleDateFormat sqlFormat = new SimpleDateFormat ( " yyyy-MM-dd HH:mm:ss " ) ;
String dateString = sqlFormat . format ( new Date ( ) ) ;
deleteStmnt . setString ( 1 , '$' + groupName ) ;
deleteStmnt . executeUpdate ( ) ;
insertStmnt . setString ( 1 , '$' + groupName ) ;
insertStmnt . setString ( 2 , dateString ) ;
insertStmnt . setInt ( 3 , 0 ) ;
insertStmnt . setInt ( 4 , currentValue ) ;
insertStmnt . executeUpdate ( ) ;
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to save data for group " + groupName + " . Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
}
2012-07-17 03:17:12 +00:00
}
2017-08-23 15:37:25 +00:00
2012-07-17 03:17:12 +00:00
@Override
2012-08-08 04:46:31 +00:00
synchronized void close ( )
2012-07-17 03:17:12 +00:00
{
if ( this . databaseConnection ! = null )
{
try
{
2013-01-25 03:45:39 +00:00
if ( ! this . databaseConnection . isClosed ( ) )
{
this . databaseConnection . close ( ) ;
}
2012-07-17 03:17:12 +00:00
}
catch ( SQLException e ) { } ;
2013-01-25 03:45:39 +00:00
}
2017-08-23 15:37:25 +00:00
2013-01-25 03:45:39 +00:00
this . databaseConnection = null ;
}
2017-08-23 15:37:25 +00:00
2014-10-03 02:27:15 +00:00
private synchronized void refreshDataConnection ( ) throws SQLException
2013-01-25 03:45:39 +00:00
{
2015-09-20 20:36:32 +00:00
if ( this . databaseConnection = = null | | ! this . databaseConnection . isValid ( 3 ) )
2013-01-25 03:45:39 +00:00
{
2015-10-04 02:58:30 +00:00
if ( this . databaseConnection ! = null & & ! this . databaseConnection . isClosed ( ) )
2017-08-23 15:37:25 +00:00
{
this . databaseConnection . close ( ) ;
}
//set username/pass properties
2013-01-25 03:45:39 +00:00
Properties connectionProps = new Properties ( ) ;
connectionProps . put ( " user " , this . userName ) ;
connectionProps . put ( " password " , this . password ) ;
2015-01-28 21:55:46 +00:00
connectionProps . put ( " autoReconnect " , " true " ) ;
2015-09-22 03:04:14 +00:00
connectionProps . put ( " maxReconnects " , String . valueOf ( Integer . MAX_VALUE ) ) ;
2017-08-23 15:37:25 +00:00
2013-01-25 03:45:39 +00:00
//establish connection
2017-08-23 15:37:25 +00:00
this . databaseConnection = DriverManager . getConnection ( this . databaseUrl , connectionProps ) ;
}
}
@Override
protected int getSchemaVersionFromStorage ( )
{
try ( PreparedStatement selectStmnt = this . databaseConnection . prepareStatement ( this . getSelectSchemaVersionSQL ( ) ) ) {
ResultSet results = selectStmnt . executeQuery ( ) ;
//if there's nothing yet, assume 0 and add it
if ( ! results . next ( ) )
{
this . setSchemaVersion ( 0 ) ;
return 0 ;
}
//otherwise return the value that's in the table
else
{
return results . getInt ( " version " ) ;
}
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to retrieve schema version from database. Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
return 0 ;
}
}
@Override
protected void updateSchemaVersionInStorage ( int versionToSet )
{
try ( PreparedStatement deleteStmnt = this . databaseConnection . prepareStatement ( this . getDeleteSchemaVersionSQL ( ) ) ;
PreparedStatement insertStmnt = this . databaseConnection . prepareStatement ( this . getInsertSchemaVerSQL ( ) ) ) {
deleteStmnt . execute ( ) ;
insertStmnt . setInt ( 1 , versionToSet ) ;
insertStmnt . executeUpdate ( ) ;
}
catch ( SQLException e )
{
GriefPrevention . AddLogEntry ( " Unable to set next schema version to " + versionToSet + " . Details: " ) ;
GriefPrevention . AddLogEntry ( e . getMessage ( ) ) ;
2012-07-17 03:17:12 +00:00
}
}
2014-09-22 20:46:13 +00:00
2017-08-23 15:37:25 +00:00
/ * *
* Concats an array to a string divided with the ; sign
* @param input Arraylist with strings to concat
* @return String with all values from input array
* /
private String storageStringBuilder ( ArrayList < String > input ) {
String output = " " ;
for ( String string : input ) {
output + = string + " ; " ;
}
return output ;
}
public String getUpdateNameSQL ( ) {
return updateNameSQL ;
}
public String getInsertClaimSQL ( ) {
return insertClaimSQL ;
}
public String getDeleteClaimSQL ( ) {
return deleteClaimSQL ;
}
public String getGetPlayerDataSQL ( ) {
return getPlayerDataSQL ;
}
public String getDeletePlayerDataSQL ( ) {
return deletePlayerDataSQL ;
}
public String getInsertPlayerDataSQL ( ) {
return insertPlayerDataSQL ;
}
public String getInsertNextClaimIdSQL ( ) {
return insertNextClaimIdSQL ;
}
public String getDeleteGroupBonusSQL ( ) {
return deleteGroupBonusSQL ;
}
public String getInsertSchemaVerSQL ( ) {
return insertSchemaVerSQL ;
}
public String getDeleteNextClaimIdSQL ( ) {
return deleteNextClaimIdSQL ;
}
public String getDeleteSchemaVersionSQL ( ) {
return deleteSchemaVersionSQL ;
}
public String getSelectSchemaVersionSQL ( ) {
return selectSchemaVersionSQL ;
}
2012-07-17 03:17:12 +00:00
}