SQLDatabaseManager.java 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548
  1. package com.gmail.nossr50.database;
  2. import com.gmail.nossr50.config.AdvancedConfig;
  3. import com.gmail.nossr50.config.Config;
  4. import com.gmail.nossr50.datatypes.MobHealthbarType;
  5. import com.gmail.nossr50.datatypes.database.DatabaseType;
  6. import com.gmail.nossr50.datatypes.database.PlayerStat;
  7. import com.gmail.nossr50.datatypes.database.UpgradeType;
  8. import com.gmail.nossr50.datatypes.player.PlayerProfile;
  9. import com.gmail.nossr50.datatypes.player.UniqueDataType;
  10. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  11. import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
  12. import com.gmail.nossr50.mcMMO;
  13. import com.gmail.nossr50.runnables.database.UUIDUpdateAsyncTask;
  14. import com.gmail.nossr50.util.Misc;
  15. import org.apache.tomcat.jdbc.pool.DataSource;
  16. import org.apache.tomcat.jdbc.pool.PoolProperties;
  17. import org.bukkit.scheduler.BukkitRunnable;
  18. import java.sql.*;
  19. import java.util.*;
  20. import java.util.concurrent.locks.ReentrantLock;
  21. public final class SQLDatabaseManager implements DatabaseManager {
  22. private static final String ALL_QUERY_VERSION = "total";
  23. private String tablePrefix = Config.getInstance().getMySQLTablePrefix();
  24. private final Map<UUID, Integer> cachedUserIDs = new HashMap<UUID, Integer>();
  25. private DataSource miscPool;
  26. private DataSource loadPool;
  27. private DataSource savePool;
  28. private boolean debug = false;
  29. private ReentrantLock massUpdateLock = new ReentrantLock();
  30. protected SQLDatabaseManager() {
  31. String connectionString = "jdbc:mysql://" + Config.getInstance().getMySQLServerName()
  32. + ":" + Config.getInstance().getMySQLServerPort() + "/" + Config.getInstance().getMySQLDatabaseName();
  33. if(Config.getInstance().getMySQLSSL())
  34. connectionString +=
  35. "?verifyServerCertificate=false"+
  36. "&useSSL=true"+
  37. "&requireSSL=true";
  38. else
  39. connectionString+=
  40. "?useSSL=false";
  41. try {
  42. // Force driver to load if not yet loaded
  43. Class.forName("com.mysql.jdbc.Driver");
  44. }
  45. catch (ClassNotFoundException e) {
  46. e.printStackTrace();
  47. return;
  48. //throw e; // aborts onEnable() Riking if you want to do this, fully implement it.
  49. }
  50. debug = Config.getInstance().getMySQLDebug();
  51. PoolProperties poolProperties = new PoolProperties();
  52. poolProperties.setDriverClassName("com.mysql.jdbc.Driver");
  53. poolProperties.setUrl(connectionString);
  54. poolProperties.setUsername(Config.getInstance().getMySQLUserName());
  55. poolProperties.setPassword(Config.getInstance().getMySQLUserPassword());
  56. poolProperties.setMaxIdle(Config.getInstance().getMySQLMaxPoolSize(PoolIdentifier.MISC));
  57. poolProperties.setMaxActive(Config.getInstance().getMySQLMaxConnections(PoolIdentifier.MISC));
  58. poolProperties.setInitialSize(0);
  59. poolProperties.setMaxWait(-1);
  60. poolProperties.setRemoveAbandoned(true);
  61. poolProperties.setRemoveAbandonedTimeout(60);
  62. poolProperties.setTestOnBorrow(true);
  63. poolProperties.setValidationQuery("SELECT 1");
  64. poolProperties.setValidationInterval(30000);
  65. miscPool = new DataSource(poolProperties);
  66. poolProperties = new PoolProperties();
  67. poolProperties.setDriverClassName("com.mysql.jdbc.Driver");
  68. poolProperties.setUrl(connectionString);
  69. poolProperties.setUsername(Config.getInstance().getMySQLUserName());
  70. poolProperties.setPassword(Config.getInstance().getMySQLUserPassword());
  71. poolProperties.setInitialSize(0);
  72. poolProperties.setMaxIdle(Config.getInstance().getMySQLMaxPoolSize(PoolIdentifier.SAVE));
  73. poolProperties.setMaxActive(Config.getInstance().getMySQLMaxConnections(PoolIdentifier.SAVE));
  74. poolProperties.setMaxWait(-1);
  75. poolProperties.setRemoveAbandoned(true);
  76. poolProperties.setRemoveAbandonedTimeout(60);
  77. poolProperties.setTestOnBorrow(true);
  78. poolProperties.setValidationQuery("SELECT 1");
  79. poolProperties.setValidationInterval(30000);
  80. savePool = new DataSource(poolProperties);
  81. poolProperties = new PoolProperties();
  82. poolProperties.setDriverClassName("com.mysql.jdbc.Driver");
  83. poolProperties.setUrl(connectionString);
  84. poolProperties.setUsername(Config.getInstance().getMySQLUserName());
  85. poolProperties.setPassword(Config.getInstance().getMySQLUserPassword());
  86. poolProperties.setInitialSize(0);
  87. poolProperties.setMaxIdle(Config.getInstance().getMySQLMaxPoolSize(PoolIdentifier.LOAD));
  88. poolProperties.setMaxActive(Config.getInstance().getMySQLMaxConnections(PoolIdentifier.LOAD));
  89. poolProperties.setMaxWait(-1);
  90. poolProperties.setRemoveAbandoned(true);
  91. poolProperties.setRemoveAbandonedTimeout(60);
  92. poolProperties.setTestOnBorrow(true);
  93. poolProperties.setValidationQuery("SELECT 1");
  94. poolProperties.setValidationInterval(30000);
  95. loadPool = new DataSource(poolProperties);
  96. checkStructure();
  97. }
  98. public void purgePowerlessUsers() {
  99. massUpdateLock.lock();
  100. mcMMO.p.getLogger().info("Purging powerless users...");
  101. Connection connection = null;
  102. Statement statement = null;
  103. int purged = 0;
  104. try {
  105. connection = getConnection(PoolIdentifier.MISC);
  106. statement = connection.createStatement();
  107. purged = statement.executeUpdate("DELETE FROM " + tablePrefix + "skills WHERE "
  108. + "taming = 0 AND mining = 0 AND woodcutting = 0 AND repair = 0 "
  109. + "AND unarmed = 0 AND herbalism = 0 AND excavation = 0 AND "
  110. + "archery = 0 AND swords = 0 AND axes = 0 AND acrobatics = 0 "
  111. + "AND fishing = 0 AND alchemy = 0;");
  112. statement.executeUpdate("DELETE FROM `" + tablePrefix + "experience` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "skills` `s` WHERE `" + tablePrefix + "experience`.`user_id` = `s`.`user_id`)");
  113. statement.executeUpdate("DELETE FROM `" + tablePrefix + "huds` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "skills` `s` WHERE `" + tablePrefix + "huds`.`user_id` = `s`.`user_id`)");
  114. statement.executeUpdate("DELETE FROM `" + tablePrefix + "cooldowns` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "skills` `s` WHERE `" + tablePrefix + "cooldowns`.`user_id` = `s`.`user_id`)");
  115. statement.executeUpdate("DELETE FROM `" + tablePrefix + "users` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "skills` `s` WHERE `" + tablePrefix + "users`.`id` = `s`.`user_id`)");
  116. }
  117. catch (SQLException ex) {
  118. printErrors(ex);
  119. }
  120. finally {
  121. tryClose(statement);
  122. tryClose(connection);
  123. massUpdateLock.unlock();
  124. }
  125. mcMMO.p.getLogger().info("Purged " + purged + " users from the database.");
  126. }
  127. public void purgeOldUsers() {
  128. massUpdateLock.lock();
  129. mcMMO.p.getLogger().info("Purging inactive users older than " + (PURGE_TIME / 2630000000L) + " months...");
  130. Connection connection = null;
  131. Statement statement = null;
  132. int purged = 0;
  133. try {
  134. connection = getConnection(PoolIdentifier.MISC);
  135. statement = connection.createStatement();
  136. purged = statement.executeUpdate("DELETE FROM u, e, h, s, c USING " + tablePrefix + "users u " +
  137. "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " +
  138. "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) " +
  139. "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) " +
  140. "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) " +
  141. "WHERE ((UNIX_TIMESTAMP() - lastlogin) > " + PURGE_TIME + ")");
  142. }
  143. catch (SQLException ex) {
  144. printErrors(ex);
  145. }
  146. finally {
  147. tryClose(statement);
  148. tryClose(connection);
  149. massUpdateLock.unlock();
  150. }
  151. mcMMO.p.getLogger().info("Purged " + purged + " users from the database.");
  152. }
  153. public boolean removeUser(String playerName, UUID uuid) {
  154. boolean success = false;
  155. Connection connection = null;
  156. PreparedStatement statement = null;
  157. try {
  158. connection = getConnection(PoolIdentifier.MISC);
  159. statement = connection.prepareStatement("DELETE FROM u, e, h, s, c " +
  160. "USING " + tablePrefix + "users u " +
  161. "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " +
  162. "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) " +
  163. "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) " +
  164. "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) " +
  165. "WHERE u.user = ?");
  166. statement.setString(1, playerName);
  167. success = statement.executeUpdate() != 0;
  168. }
  169. catch (SQLException ex) {
  170. printErrors(ex);
  171. }
  172. finally {
  173. tryClose(statement);
  174. tryClose(connection);
  175. }
  176. if (success) {
  177. if(uuid != null)
  178. cleanupUser(uuid);
  179. Misc.profileCleanup(playerName);
  180. }
  181. return success;
  182. }
  183. public void cleanupUser(UUID uuid) {
  184. if(cachedUserIDs.containsKey(uuid))
  185. cachedUserIDs.remove(uuid);
  186. }
  187. public boolean saveUser(PlayerProfile profile) {
  188. boolean success = true;
  189. PreparedStatement statement = null;
  190. Connection connection = null;
  191. try {
  192. connection = getConnection(PoolIdentifier.SAVE);
  193. int id = getUserID(connection, profile.getPlayerName(), profile.getUniqueId());
  194. if (id == -1) {
  195. id = newUser(connection, profile.getPlayerName(), profile.getUniqueId());
  196. if (id == -1) {
  197. mcMMO.p.getLogger().severe("Failed to create new account for " + profile.getPlayerName());
  198. return false;
  199. }
  200. }
  201. statement = connection.prepareStatement("UPDATE " + tablePrefix + "users SET lastlogin = UNIX_TIMESTAMP() WHERE id = ?");
  202. statement.setInt(1, id);
  203. success &= (statement.executeUpdate() != 0);
  204. statement.close();
  205. if (!success) {
  206. mcMMO.p.getLogger().severe("Failed to update last login for " + profile.getPlayerName());
  207. return false;
  208. }
  209. statement = connection.prepareStatement("UPDATE " + tablePrefix + "skills SET "
  210. + " taming = ?, mining = ?, repair = ?, woodcutting = ?"
  211. + ", unarmed = ?, herbalism = ?, excavation = ?"
  212. + ", archery = ?, swords = ?, axes = ?, acrobatics = ?"
  213. + ", fishing = ?, alchemy = ?, total = ? WHERE user_id = ?");
  214. statement.setInt(1, profile.getSkillLevel(PrimarySkillType.TAMING));
  215. statement.setInt(2, profile.getSkillLevel(PrimarySkillType.MINING));
  216. statement.setInt(3, profile.getSkillLevel(PrimarySkillType.REPAIR));
  217. statement.setInt(4, profile.getSkillLevel(PrimarySkillType.WOODCUTTING));
  218. statement.setInt(5, profile.getSkillLevel(PrimarySkillType.UNARMED));
  219. statement.setInt(6, profile.getSkillLevel(PrimarySkillType.HERBALISM));
  220. statement.setInt(7, profile.getSkillLevel(PrimarySkillType.EXCAVATION));
  221. statement.setInt(8, profile.getSkillLevel(PrimarySkillType.ARCHERY));
  222. statement.setInt(9, profile.getSkillLevel(PrimarySkillType.SWORDS));
  223. statement.setInt(10, profile.getSkillLevel(PrimarySkillType.AXES));
  224. statement.setInt(11, profile.getSkillLevel(PrimarySkillType.ACROBATICS));
  225. statement.setInt(12, profile.getSkillLevel(PrimarySkillType.FISHING));
  226. statement.setInt(13, profile.getSkillLevel(PrimarySkillType.ALCHEMY));
  227. int total = 0;
  228. for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS)
  229. total += profile.getSkillLevel(primarySkillType);
  230. statement.setInt(14, total);
  231. statement.setInt(15, id);
  232. success &= (statement.executeUpdate() != 0);
  233. statement.close();
  234. if (!success) {
  235. mcMMO.p.getLogger().severe("Failed to update skills for " + profile.getPlayerName());
  236. return false;
  237. }
  238. statement = connection.prepareStatement("UPDATE " + tablePrefix + "experience SET "
  239. + " taming = ?, mining = ?, repair = ?, woodcutting = ?"
  240. + ", unarmed = ?, herbalism = ?, excavation = ?"
  241. + ", archery = ?, swords = ?, axes = ?, acrobatics = ?"
  242. + ", fishing = ?, alchemy = ? WHERE user_id = ?");
  243. statement.setInt(1, profile.getSkillXpLevel(PrimarySkillType.TAMING));
  244. statement.setInt(2, profile.getSkillXpLevel(PrimarySkillType.MINING));
  245. statement.setInt(3, profile.getSkillXpLevel(PrimarySkillType.REPAIR));
  246. statement.setInt(4, profile.getSkillXpLevel(PrimarySkillType.WOODCUTTING));
  247. statement.setInt(5, profile.getSkillXpLevel(PrimarySkillType.UNARMED));
  248. statement.setInt(6, profile.getSkillXpLevel(PrimarySkillType.HERBALISM));
  249. statement.setInt(7, profile.getSkillXpLevel(PrimarySkillType.EXCAVATION));
  250. statement.setInt(8, profile.getSkillXpLevel(PrimarySkillType.ARCHERY));
  251. statement.setInt(9, profile.getSkillXpLevel(PrimarySkillType.SWORDS));
  252. statement.setInt(10, profile.getSkillXpLevel(PrimarySkillType.AXES));
  253. statement.setInt(11, profile.getSkillXpLevel(PrimarySkillType.ACROBATICS));
  254. statement.setInt(12, profile.getSkillXpLevel(PrimarySkillType.FISHING));
  255. statement.setInt(13, profile.getSkillXpLevel(PrimarySkillType.ALCHEMY));
  256. statement.setInt(14, id);
  257. success &= (statement.executeUpdate() != 0);
  258. statement.close();
  259. if (!success) {
  260. mcMMO.p.getLogger().severe("Failed to update experience for " + profile.getPlayerName());
  261. return false;
  262. }
  263. statement = connection.prepareStatement("UPDATE " + tablePrefix + "cooldowns SET "
  264. + " mining = ?, woodcutting = ?, unarmed = ?"
  265. + ", herbalism = ?, excavation = ?, swords = ?"
  266. + ", axes = ?, blast_mining = ?, chimaera_wing = ? WHERE user_id = ?");
  267. statement.setLong(1, profile.getAbilityDATS(SuperAbilityType.SUPER_BREAKER));
  268. statement.setLong(2, profile.getAbilityDATS(SuperAbilityType.TREE_FELLER));
  269. statement.setLong(3, profile.getAbilityDATS(SuperAbilityType.BERSERK));
  270. statement.setLong(4, profile.getAbilityDATS(SuperAbilityType.GREEN_TERRA));
  271. statement.setLong(5, profile.getAbilityDATS(SuperAbilityType.GIGA_DRILL_BREAKER));
  272. statement.setLong(6, profile.getAbilityDATS(SuperAbilityType.SERRATED_STRIKES));
  273. statement.setLong(7, profile.getAbilityDATS(SuperAbilityType.SKULL_SPLITTER));
  274. statement.setLong(8, profile.getAbilityDATS(SuperAbilityType.BLAST_MINING));
  275. statement.setLong(9, profile.getUniqueData(UniqueDataType.CHIMAERA_WING_DATS));
  276. statement.setInt(10, id);
  277. success = (statement.executeUpdate() != 0);
  278. statement.close();
  279. if (!success) {
  280. mcMMO.p.getLogger().severe("Failed to update cooldowns for " + profile.getPlayerName());
  281. return false;
  282. }
  283. statement = connection.prepareStatement("UPDATE " + tablePrefix + "huds SET mobhealthbar = ?, scoreboardtips = ? WHERE user_id = ?");
  284. statement.setString(1, profile.getMobHealthbarType() == null ? Config.getInstance().getMobHealthbarDefault().name() : profile.getMobHealthbarType().name());
  285. statement.setInt(2, profile.getScoreboardTipsShown());
  286. statement.setInt(3, id);
  287. success = (statement.executeUpdate() != 0);
  288. statement.close();
  289. if (!success) {
  290. mcMMO.p.getLogger().severe("Failed to update hud settings for " + profile.getPlayerName());
  291. return false;
  292. }
  293. }
  294. catch (SQLException ex) {
  295. printErrors(ex);
  296. }
  297. finally {
  298. tryClose(statement);
  299. tryClose(connection);
  300. }
  301. return success;
  302. }
  303. public List<PlayerStat> readLeaderboard(PrimarySkillType skill, int pageNumber, int statsPerPage) {
  304. List<PlayerStat> stats = new ArrayList<PlayerStat>();
  305. String query = skill == null ? ALL_QUERY_VERSION : skill.name().toLowerCase(Locale.ENGLISH);
  306. ResultSet resultSet = null;
  307. PreparedStatement statement = null;
  308. Connection connection = null;
  309. try {
  310. connection = getConnection(PoolIdentifier.MISC);
  311. statement = connection.prepareStatement("SELECT " + query + ", user FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 AND NOT user = '\\_INVALID\\_OLD\\_USERNAME\\_' ORDER BY " + query + " DESC, user LIMIT ?, ?");
  312. statement.setInt(1, (pageNumber * statsPerPage) - statsPerPage);
  313. statement.setInt(2, statsPerPage);
  314. resultSet = statement.executeQuery();
  315. while (resultSet.next()) {
  316. ArrayList<String> column = new ArrayList<String>();
  317. for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) {
  318. column.add(resultSet.getString(i));
  319. }
  320. stats.add(new PlayerStat(column.get(1), Integer.valueOf(column.get(0))));
  321. }
  322. }
  323. catch (SQLException ex) {
  324. printErrors(ex);
  325. }
  326. finally {
  327. tryClose(resultSet);
  328. tryClose(statement);
  329. tryClose(connection);
  330. }
  331. return stats;
  332. }
  333. public Map<PrimarySkillType, Integer> readRank(String playerName) {
  334. Map<PrimarySkillType, Integer> skills = new HashMap<PrimarySkillType, Integer>();
  335. ResultSet resultSet = null;
  336. PreparedStatement statement = null;
  337. Connection connection = null;
  338. try {
  339. connection = getConnection(PoolIdentifier.MISC);
  340. for (PrimarySkillType primarySkillType : PrimarySkillType.NON_CHILD_SKILLS) {
  341. String skillName = primarySkillType.name().toLowerCase(Locale.ENGLISH);
  342. // Get count of all users with higher skill level than player
  343. String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
  344. "AND " + skillName + " > (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
  345. "WHERE user = ?)";
  346. statement = connection.prepareStatement(sql);
  347. statement.setString(1, playerName);
  348. resultSet = statement.executeQuery();
  349. resultSet.next();
  350. int rank = resultSet.getInt("rank");
  351. // Ties are settled by alphabetical order
  352. sql = "SELECT user, " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
  353. "AND " + skillName + " = (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
  354. "WHERE user = '" + playerName + "') ORDER BY user";
  355. resultSet.close();
  356. statement.close();
  357. statement = connection.prepareStatement(sql);
  358. resultSet = statement.executeQuery();
  359. while (resultSet.next()) {
  360. if (resultSet.getString("user").equalsIgnoreCase(playerName)) {
  361. skills.put(primarySkillType, rank + resultSet.getRow());
  362. break;
  363. }
  364. }
  365. resultSet.close();
  366. statement.close();
  367. }
  368. String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
  369. "WHERE " + ALL_QUERY_VERSION + " > 0 " +
  370. "AND " + ALL_QUERY_VERSION + " > " +
  371. "(SELECT " + ALL_QUERY_VERSION + " " +
  372. "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?)";
  373. statement = connection.prepareStatement(sql);
  374. statement.setString(1, playerName);
  375. resultSet = statement.executeQuery();
  376. resultSet.next();
  377. int rank = resultSet.getInt("rank");
  378. resultSet.close();
  379. statement.close();
  380. sql = "SELECT user, " + ALL_QUERY_VERSION + " " +
  381. "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
  382. "WHERE " + ALL_QUERY_VERSION + " > 0 " +
  383. "AND " + ALL_QUERY_VERSION + " = " +
  384. "(SELECT " + ALL_QUERY_VERSION + " " +
  385. "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?) ORDER BY user";
  386. statement = connection.prepareStatement(sql);
  387. statement.setString(1, playerName);
  388. resultSet = statement.executeQuery();
  389. while (resultSet.next()) {
  390. if (resultSet.getString("user").equalsIgnoreCase(playerName)) {
  391. skills.put(null, rank + resultSet.getRow());
  392. break;
  393. }
  394. }
  395. resultSet.close();
  396. statement.close();
  397. }
  398. catch (SQLException ex) {
  399. printErrors(ex);
  400. }
  401. finally {
  402. tryClose(resultSet);
  403. tryClose(statement);
  404. tryClose(connection);
  405. }
  406. return skills;
  407. }
  408. public void newUser(String playerName, UUID uuid) {
  409. Connection connection = null;
  410. try {
  411. connection = getConnection(PoolIdentifier.MISC);
  412. newUser(connection, playerName, uuid);
  413. }
  414. catch (SQLException ex) {
  415. printErrors(ex);
  416. }
  417. finally {
  418. tryClose(connection);
  419. }
  420. }
  421. private int newUser(Connection connection, String playerName, UUID uuid) {
  422. ResultSet resultSet = null;
  423. PreparedStatement statement = null;
  424. try {
  425. statement = connection.prepareStatement(
  426. "UPDATE `" + tablePrefix + "users` "
  427. + "SET user = ? "
  428. + "WHERE user = ?");
  429. statement.setString(1, "_INVALID_OLD_USERNAME_");
  430. statement.setString(2, playerName);
  431. statement.executeUpdate();
  432. statement.close();
  433. statement = connection.prepareStatement("INSERT INTO " + tablePrefix + "users (user, uuid, lastlogin) VALUES (?, ?, UNIX_TIMESTAMP())", Statement.RETURN_GENERATED_KEYS);
  434. statement.setString(1, playerName);
  435. statement.setString(2, uuid != null ? uuid.toString() : null);
  436. statement.executeUpdate();
  437. resultSet = statement.getGeneratedKeys();
  438. if (!resultSet.next()) {
  439. mcMMO.p.getLogger().severe("Unable to create new user account in DB");
  440. return -1;
  441. }
  442. writeMissingRows(connection, resultSet.getInt(1));
  443. return resultSet.getInt(1);
  444. }
  445. catch (SQLException ex) {
  446. printErrors(ex);
  447. }
  448. finally {
  449. tryClose(resultSet);
  450. tryClose(statement);
  451. }
  452. return -1;
  453. }
  454. @Deprecated
  455. public PlayerProfile loadPlayerProfile(String playerName, boolean create) {
  456. return loadPlayerProfile(playerName, null, false, true);
  457. }
  458. public PlayerProfile loadPlayerProfile(UUID uuid) {
  459. return loadPlayerProfile("", uuid, false, true);
  460. }
  461. public PlayerProfile loadPlayerProfile(String playerName, UUID uuid, boolean create) {
  462. return loadPlayerProfile(playerName, uuid, create, true);
  463. }
  464. private PlayerProfile loadPlayerProfile(String playerName, UUID uuid, boolean create, boolean retry) {
  465. PreparedStatement statement = null;
  466. Connection connection = null;
  467. ResultSet resultSet = null;
  468. try {
  469. connection = getConnection(PoolIdentifier.LOAD);
  470. int id = getUserID(connection, playerName, uuid);
  471. if (id == -1) {
  472. // There is no such user
  473. if (create) {
  474. id = newUser(connection, playerName, uuid);
  475. create = false;
  476. if (id == -1) {
  477. return new PlayerProfile(playerName, false);
  478. }
  479. } else {
  480. return new PlayerProfile(playerName, false);
  481. }
  482. }
  483. // There is such a user
  484. writeMissingRows(connection, id);
  485. statement = connection.prepareStatement(
  486. "SELECT "
  487. + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, "
  488. + "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, "
  489. + "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, c.chimaera_wing, "
  490. + "h.mobhealthbar, h.scoreboardtips, u.uuid, u.user "
  491. + "FROM " + tablePrefix + "users u "
  492. + "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) "
  493. + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) "
  494. + "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) "
  495. + "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) "
  496. + "WHERE u.id = ?");
  497. statement.setInt(1, id);
  498. resultSet = statement.executeQuery();
  499. if (resultSet.next()) {
  500. try {
  501. PlayerProfile profile = loadFromResult(playerName, resultSet);
  502. String name = resultSet.getString(42); // TODO: Magic Number, make sure it stays updated
  503. resultSet.close();
  504. statement.close();
  505. if (!playerName.isEmpty() && !playerName.equalsIgnoreCase(name) && uuid != null) {
  506. statement = connection.prepareStatement(
  507. "UPDATE `" + tablePrefix + "users` "
  508. + "SET user = ? "
  509. + "WHERE user = ?");
  510. statement.setString(1, "_INVALID_OLD_USERNAME_");
  511. statement.setString(2, name);
  512. statement.executeUpdate();
  513. statement.close();
  514. statement = connection.prepareStatement(
  515. "UPDATE `" + tablePrefix + "users` "
  516. + "SET user = ?, uuid = ? "
  517. + "WHERE id = ?");
  518. statement.setString(1, playerName);
  519. statement.setString(2, uuid.toString());
  520. statement.setInt(3, id);
  521. statement.executeUpdate();
  522. statement.close();
  523. }
  524. return profile;
  525. }
  526. catch (SQLException e) {
  527. printErrors(e);
  528. }
  529. }
  530. resultSet.close();
  531. }
  532. catch (SQLException ex) {
  533. printErrors(ex);
  534. }
  535. finally {
  536. tryClose(resultSet);
  537. tryClose(statement);
  538. tryClose(connection);
  539. }
  540. // Problem, nothing was returned
  541. // return unloaded profile
  542. if (!retry) {
  543. return new PlayerProfile(playerName, false);
  544. }
  545. // Retry, and abort on re-failure
  546. return loadPlayerProfile(playerName, uuid, create, false);
  547. }
  548. public void convertUsers(DatabaseManager destination) {
  549. PreparedStatement statement = null;
  550. Connection connection = null;
  551. ResultSet resultSet = null;
  552. try {
  553. connection = getConnection(PoolIdentifier.MISC);
  554. statement = connection.prepareStatement(
  555. "SELECT "
  556. + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, "
  557. + "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, "
  558. + "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, c.chimaera_wing, "
  559. + "h.mobhealthbar, h.scoreboardtips, u.uuid "
  560. + "FROM " + tablePrefix + "users u "
  561. + "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) "
  562. + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) "
  563. + "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) "
  564. + "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) "
  565. + "WHERE u.user = ?");
  566. List<String> usernames = getStoredUsers();
  567. int convertedUsers = 0;
  568. long startMillis = System.currentTimeMillis();
  569. for (String playerName : usernames) {
  570. statement.setString(1, playerName);
  571. try {
  572. resultSet = statement.executeQuery();
  573. resultSet.next();
  574. destination.saveUser(loadFromResult(playerName, resultSet));
  575. resultSet.close();
  576. }
  577. catch (SQLException e) {
  578. printErrors(e);
  579. // Ignore
  580. }
  581. convertedUsers++;
  582. Misc.printProgress(convertedUsers, progressInterval, startMillis);
  583. }
  584. }
  585. catch (SQLException e) {
  586. printErrors(e);
  587. }
  588. finally {
  589. tryClose(resultSet);
  590. tryClose(statement);
  591. tryClose(connection);
  592. }
  593. }
  594. public boolean saveUserUUID(String userName, UUID uuid) {
  595. PreparedStatement statement = null;
  596. Connection connection = null;
  597. try {
  598. connection = getConnection(PoolIdentifier.MISC);
  599. statement = connection.prepareStatement(
  600. "UPDATE `" + tablePrefix + "users` SET "
  601. + " uuid = ? WHERE user = ?");
  602. statement.setString(1, uuid.toString());
  603. statement.setString(2, userName);
  604. statement.execute();
  605. return true;
  606. }
  607. catch (SQLException ex) {
  608. printErrors(ex);
  609. return false;
  610. }
  611. finally {
  612. tryClose(statement);
  613. tryClose(connection);
  614. }
  615. }
  616. public boolean saveUserUUIDs(Map<String, UUID> fetchedUUIDs) {
  617. PreparedStatement statement = null;
  618. int count = 0;
  619. Connection connection = null;
  620. try {
  621. connection = getConnection(PoolIdentifier.MISC);
  622. statement = connection.prepareStatement("UPDATE " + tablePrefix + "users SET uuid = ? WHERE user = ?");
  623. for (Map.Entry<String, UUID> entry : fetchedUUIDs.entrySet()) {
  624. statement.setString(1, entry.getValue().toString());
  625. statement.setString(2, entry.getKey());
  626. statement.addBatch();
  627. count++;
  628. if ((count % 500) == 0) {
  629. statement.executeBatch();
  630. count = 0;
  631. }
  632. }
  633. if (count != 0) {
  634. statement.executeBatch();
  635. }
  636. return true;
  637. }
  638. catch (SQLException ex) {
  639. printErrors(ex);
  640. return false;
  641. }
  642. finally {
  643. tryClose(statement);
  644. tryClose(connection);
  645. }
  646. }
  647. public List<String> getStoredUsers() {
  648. ArrayList<String> users = new ArrayList<String>();
  649. Statement statement = null;
  650. Connection connection = null;
  651. ResultSet resultSet = null;
  652. try {
  653. connection = getConnection(PoolIdentifier.MISC);
  654. statement = connection.createStatement();
  655. resultSet = statement.executeQuery("SELECT user FROM " + tablePrefix + "users");
  656. while (resultSet.next()) {
  657. users.add(resultSet.getString("user"));
  658. }
  659. }
  660. catch (SQLException e) {
  661. printErrors(e);
  662. }
  663. finally {
  664. tryClose(resultSet);
  665. tryClose(statement);
  666. tryClose(connection);
  667. }
  668. return users;
  669. }
  670. /**
  671. * Checks that the database structure is present and correct
  672. */
  673. private void checkStructure() {
  674. PreparedStatement statement = null;
  675. Statement createStatement = null;
  676. ResultSet resultSet = null;
  677. Connection connection = null;
  678. try {
  679. connection = getConnection(PoolIdentifier.MISC);
  680. statement = connection.prepareStatement("SELECT table_name FROM INFORMATION_SCHEMA.TABLES"
  681. + " WHERE table_schema = ?"
  682. + " AND table_name = ?");
  683. statement.setString(1, Config.getInstance().getMySQLDatabaseName());
  684. statement.setString(2, tablePrefix + "users");
  685. resultSet = statement.executeQuery();
  686. if (!resultSet.next()) {
  687. createStatement = connection.createStatement();
  688. createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "users` ("
  689. + "`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
  690. + "`user` varchar(40) NOT NULL,"
  691. + "`uuid` varchar(36) NULL DEFAULT NULL,"
  692. + "`lastlogin` int(32) unsigned NOT NULL,"
  693. + "PRIMARY KEY (`id`),"
  694. + "INDEX(`user`(20) ASC),"
  695. + "UNIQUE KEY `uuid` (`uuid`)) DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;");
  696. tryClose(createStatement);
  697. }
  698. tryClose(resultSet);
  699. statement.setString(1, Config.getInstance().getMySQLDatabaseName());
  700. statement.setString(2, tablePrefix + "huds");
  701. resultSet = statement.executeQuery();
  702. if (!resultSet.next()) {
  703. createStatement = connection.createStatement();
  704. createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "huds` ("
  705. + "`user_id` int(10) unsigned NOT NULL,"
  706. + "`mobhealthbar` varchar(50) NOT NULL DEFAULT '" + Config.getInstance().getMobHealthbarDefault() + "',"
  707. + "`scoreboardtips` int(10) NOT NULL DEFAULT '0',"
  708. + "PRIMARY KEY (`user_id`)) "
  709. + "DEFAULT CHARSET=latin1;");
  710. tryClose(createStatement);
  711. }
  712. tryClose(resultSet);
  713. statement.setString(1, Config.getInstance().getMySQLDatabaseName());
  714. statement.setString(2, tablePrefix + "cooldowns");
  715. resultSet = statement.executeQuery();
  716. if (!resultSet.next()) {
  717. createStatement = connection.createStatement();
  718. createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "cooldowns` ("
  719. + "`user_id` int(10) unsigned NOT NULL,"
  720. + "`taming` int(32) unsigned NOT NULL DEFAULT '0',"
  721. + "`mining` int(32) unsigned NOT NULL DEFAULT '0',"
  722. + "`woodcutting` int(32) unsigned NOT NULL DEFAULT '0',"
  723. + "`repair` int(32) unsigned NOT NULL DEFAULT '0',"
  724. + "`unarmed` int(32) unsigned NOT NULL DEFAULT '0',"
  725. + "`herbalism` int(32) unsigned NOT NULL DEFAULT '0',"
  726. + "`excavation` int(32) unsigned NOT NULL DEFAULT '0',"
  727. + "`archery` int(32) unsigned NOT NULL DEFAULT '0',"
  728. + "`swords` int(32) unsigned NOT NULL DEFAULT '0',"
  729. + "`axes` int(32) unsigned NOT NULL DEFAULT '0',"
  730. + "`acrobatics` int(32) unsigned NOT NULL DEFAULT '0',"
  731. + "`blast_mining` int(32) unsigned NOT NULL DEFAULT '0',"
  732. + "`chimaera_wing` int(32) unsigned NOT NULL DEFAULT '0',"
  733. + "PRIMARY KEY (`user_id`)) "
  734. + "DEFAULT CHARSET=latin1;");
  735. tryClose(createStatement);
  736. }
  737. tryClose(resultSet);
  738. statement.setString(1, Config.getInstance().getMySQLDatabaseName());
  739. statement.setString(2, tablePrefix + "skills");
  740. resultSet = statement.executeQuery();
  741. if (!resultSet.next()) {
  742. String startingLevel = "'" + AdvancedConfig.getInstance().getStartingLevel() + "'";
  743. String totalLevel = "'" + (AdvancedConfig.getInstance().getStartingLevel() * (PrimarySkillType.values().length - PrimarySkillType.CHILD_SKILLS.size())) + "'";
  744. createStatement = connection.createStatement();
  745. createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "skills` ("
  746. + "`user_id` int(10) unsigned NOT NULL,"
  747. + "`taming` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  748. + "`mining` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  749. + "`woodcutting` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  750. + "`repair` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  751. + "`unarmed` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  752. + "`herbalism` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  753. + "`excavation` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  754. + "`archery` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  755. + "`swords` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  756. + "`axes` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  757. + "`acrobatics` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  758. + "`fishing` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  759. + "`alchemy` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
  760. + "`total` int(10) unsigned NOT NULL DEFAULT "+totalLevel+","
  761. + "PRIMARY KEY (`user_id`)) "
  762. + "DEFAULT CHARSET=latin1;");
  763. tryClose(createStatement);
  764. }
  765. tryClose(resultSet);
  766. statement.setString(1, Config.getInstance().getMySQLDatabaseName());
  767. statement.setString(2, tablePrefix + "experience");
  768. resultSet = statement.executeQuery();
  769. if (!resultSet.next()) {
  770. createStatement = connection.createStatement();
  771. createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "experience` ("
  772. + "`user_id` int(10) unsigned NOT NULL,"
  773. + "`taming` int(10) unsigned NOT NULL DEFAULT '0',"
  774. + "`mining` int(10) unsigned NOT NULL DEFAULT '0',"
  775. + "`woodcutting` int(10) unsigned NOT NULL DEFAULT '0',"
  776. + "`repair` int(10) unsigned NOT NULL DEFAULT '0',"
  777. + "`unarmed` int(10) unsigned NOT NULL DEFAULT '0',"
  778. + "`herbalism` int(10) unsigned NOT NULL DEFAULT '0',"
  779. + "`excavation` int(10) unsigned NOT NULL DEFAULT '0',"
  780. + "`archery` int(10) unsigned NOT NULL DEFAULT '0',"
  781. + "`swords` int(10) unsigned NOT NULL DEFAULT '0',"
  782. + "`axes` int(10) unsigned NOT NULL DEFAULT '0',"
  783. + "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0',"
  784. + "`fishing` int(10) unsigned NOT NULL DEFAULT '0',"
  785. + "`alchemy` int(10) unsigned NOT NULL DEFAULT '0',"
  786. + "PRIMARY KEY (`user_id`)) "
  787. + "DEFAULT CHARSET=latin1;");
  788. tryClose(createStatement);
  789. }
  790. tryClose(resultSet);
  791. tryClose(statement);
  792. for (UpgradeType updateType : UpgradeType.values()) {
  793. checkDatabaseStructure(connection, updateType);
  794. }
  795. if (Config.getInstance().getTruncateSkills()) {
  796. for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
  797. int cap = Config.getInstance().getLevelCap(skill);
  798. if (cap != Integer.MAX_VALUE) {
  799. statement = connection.prepareStatement("UPDATE `" + tablePrefix + "skills` SET `" + skill.name().toLowerCase(Locale.ENGLISH) + "` = " + cap + " WHERE `" + skill.name().toLowerCase(Locale.ENGLISH) + "` > " + cap);
  800. statement.executeUpdate();
  801. tryClose(statement);
  802. }
  803. }
  804. }
  805. mcMMO.p.getLogger().info("Killing orphans");
  806. createStatement = connection.createStatement();
  807. createStatement.executeUpdate("DELETE FROM `" + tablePrefix + "experience` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "experience`.`user_id` = `u`.`id`)");
  808. createStatement.executeUpdate("DELETE FROM `" + tablePrefix + "huds` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "huds`.`user_id` = `u`.`id`)");
  809. createStatement.executeUpdate("DELETE FROM `" + tablePrefix + "cooldowns` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "cooldowns`.`user_id` = `u`.`id`)");
  810. createStatement.executeUpdate("DELETE FROM `" + tablePrefix + "skills` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "skills`.`user_id` = `u`.`id`)");
  811. }
  812. catch (SQLException ex) {
  813. printErrors(ex);
  814. }
  815. finally {
  816. tryClose(resultSet);
  817. tryClose(statement);
  818. tryClose(createStatement);
  819. tryClose(connection);
  820. }
  821. }
  822. private Connection getConnection(PoolIdentifier identifier) throws SQLException {
  823. Connection connection = null;
  824. switch (identifier) {
  825. case LOAD:
  826. connection = loadPool.getConnection();
  827. break;
  828. case MISC:
  829. connection = miscPool.getConnection();
  830. break;
  831. case SAVE:
  832. connection = savePool.getConnection();
  833. break;
  834. }
  835. if (connection == null) {
  836. throw new RuntimeException("getConnection() for " + identifier.name().toLowerCase(Locale.ENGLISH) + " pool timed out. Increase max connections settings.");
  837. }
  838. return connection;
  839. }
  840. /**
  841. * Check database structure for necessary upgrades.
  842. *
  843. * @param upgrade Upgrade to attempt to apply
  844. */
  845. private void checkDatabaseStructure(Connection connection, UpgradeType upgrade) {
  846. if (!mcMMO.getUpgradeManager().shouldUpgrade(upgrade)) {
  847. mcMMO.p.debug("Skipping " + upgrade.name() + " upgrade (unneeded)");
  848. return;
  849. }
  850. Statement statement = null;
  851. try {
  852. statement = connection.createStatement();
  853. switch (upgrade) {
  854. case ADD_FISHING:
  855. checkUpgradeAddFishing(statement);
  856. break;
  857. case ADD_BLAST_MINING_COOLDOWN:
  858. checkUpgradeAddBlastMiningCooldown(statement);
  859. break;
  860. case ADD_SQL_INDEXES:
  861. checkUpgradeAddSQLIndexes(statement);
  862. break;
  863. case ADD_MOB_HEALTHBARS:
  864. checkUpgradeAddMobHealthbars(statement);
  865. break;
  866. case DROP_SQL_PARTY_NAMES:
  867. checkUpgradeDropPartyNames(statement);
  868. break;
  869. case DROP_SPOUT:
  870. checkUpgradeDropSpout(statement);
  871. break;
  872. case ADD_ALCHEMY:
  873. checkUpgradeAddAlchemy(statement);
  874. break;
  875. case ADD_UUIDS:
  876. checkUpgradeAddUUIDs(statement);
  877. return;
  878. case ADD_SCOREBOARD_TIPS:
  879. checkUpgradeAddScoreboardTips(statement);
  880. return;
  881. case DROP_NAME_UNIQUENESS:
  882. checkNameUniqueness(statement);
  883. return;
  884. case ADD_SKILL_TOTAL:
  885. checkUpgradeSkillTotal(connection);
  886. break;
  887. case ADD_UNIQUE_PLAYER_DATA:
  888. checkUpgradeAddUniqueChimaeraWing(statement);
  889. break;
  890. default:
  891. break;
  892. }
  893. mcMMO.getUpgradeManager().setUpgradeCompleted(upgrade);
  894. }
  895. catch (SQLException ex) {
  896. printErrors(ex);
  897. }
  898. finally {
  899. tryClose(statement);
  900. }
  901. }
  902. private void writeMissingRows(Connection connection, int id) {
  903. PreparedStatement statement = null;
  904. try {
  905. statement = connection.prepareStatement("INSERT IGNORE INTO " + tablePrefix + "experience (user_id) VALUES (?)");
  906. statement.setInt(1, id);
  907. statement.execute();
  908. statement.close();
  909. statement = connection.prepareStatement("INSERT IGNORE INTO " + tablePrefix + "skills (user_id) VALUES (?)");
  910. statement.setInt(1, id);
  911. statement.execute();
  912. statement.close();
  913. statement = connection.prepareStatement("INSERT IGNORE INTO " + tablePrefix + "cooldowns (user_id) VALUES (?)");
  914. statement.setInt(1, id);
  915. statement.execute();
  916. statement.close();
  917. statement = connection.prepareStatement("INSERT IGNORE INTO " + tablePrefix + "huds (user_id, mobhealthbar, scoreboardtips) VALUES (?, ?, ?)");
  918. statement.setInt(1, id);
  919. statement.setString(2, Config.getInstance().getMobHealthbarDefault().name());
  920. statement.setInt(3, 0);
  921. statement.execute();
  922. statement.close();
  923. }
  924. catch (SQLException ex) {
  925. printErrors(ex);
  926. }
  927. finally {
  928. tryClose(statement);
  929. }
  930. }
  931. private PlayerProfile loadFromResult(String playerName, ResultSet result) throws SQLException {
  932. Map<PrimarySkillType, Integer> skills = new EnumMap<PrimarySkillType, Integer>(PrimarySkillType.class); // Skill & Level
  933. Map<PrimarySkillType, Float> skillsXp = new EnumMap<PrimarySkillType, Float>(PrimarySkillType.class); // Skill & XP
  934. Map<SuperAbilityType, Integer> skillsDATS = new EnumMap<SuperAbilityType, Integer>(SuperAbilityType.class); // Ability & Cooldown
  935. Map<UniqueDataType, Integer> uniqueData = new EnumMap<UniqueDataType, Integer>(UniqueDataType.class); //Chimaera wing cooldown and other misc info
  936. MobHealthbarType mobHealthbarType;
  937. UUID uuid;
  938. int scoreboardTipsShown;
  939. final int OFFSET_SKILLS = 0; // TODO update these numbers when the query
  940. // changes (a new skill is added)
  941. final int OFFSET_XP = 13;
  942. final int OFFSET_DATS = 26;
  943. final int OFFSET_OTHER = 39;
  944. skills.put(PrimarySkillType.TAMING, result.getInt(OFFSET_SKILLS + 1));
  945. skills.put(PrimarySkillType.MINING, result.getInt(OFFSET_SKILLS + 2));
  946. skills.put(PrimarySkillType.REPAIR, result.getInt(OFFSET_SKILLS + 3));
  947. skills.put(PrimarySkillType.WOODCUTTING, result.getInt(OFFSET_SKILLS + 4));
  948. skills.put(PrimarySkillType.UNARMED, result.getInt(OFFSET_SKILLS + 5));
  949. skills.put(PrimarySkillType.HERBALISM, result.getInt(OFFSET_SKILLS + 6));
  950. skills.put(PrimarySkillType.EXCAVATION, result.getInt(OFFSET_SKILLS + 7));
  951. skills.put(PrimarySkillType.ARCHERY, result.getInt(OFFSET_SKILLS + 8));
  952. skills.put(PrimarySkillType.SWORDS, result.getInt(OFFSET_SKILLS + 9));
  953. skills.put(PrimarySkillType.AXES, result.getInt(OFFSET_SKILLS + 10));
  954. skills.put(PrimarySkillType.ACROBATICS, result.getInt(OFFSET_SKILLS + 11));
  955. skills.put(PrimarySkillType.FISHING, result.getInt(OFFSET_SKILLS + 12));
  956. skills.put(PrimarySkillType.ALCHEMY, result.getInt(OFFSET_SKILLS + 13));
  957. skillsXp.put(PrimarySkillType.TAMING, result.getFloat(OFFSET_XP + 1));
  958. skillsXp.put(PrimarySkillType.MINING, result.getFloat(OFFSET_XP + 2));
  959. skillsXp.put(PrimarySkillType.REPAIR, result.getFloat(OFFSET_XP + 3));
  960. skillsXp.put(PrimarySkillType.WOODCUTTING, result.getFloat(OFFSET_XP + 4));
  961. skillsXp.put(PrimarySkillType.UNARMED, result.getFloat(OFFSET_XP + 5));
  962. skillsXp.put(PrimarySkillType.HERBALISM, result.getFloat(OFFSET_XP + 6));
  963. skillsXp.put(PrimarySkillType.EXCAVATION, result.getFloat(OFFSET_XP + 7));
  964. skillsXp.put(PrimarySkillType.ARCHERY, result.getFloat(OFFSET_XP + 8));
  965. skillsXp.put(PrimarySkillType.SWORDS, result.getFloat(OFFSET_XP + 9));
  966. skillsXp.put(PrimarySkillType.AXES, result.getFloat(OFFSET_XP + 10));
  967. skillsXp.put(PrimarySkillType.ACROBATICS, result.getFloat(OFFSET_XP + 11));
  968. skillsXp.put(PrimarySkillType.FISHING, result.getFloat(OFFSET_XP + 12));
  969. skillsXp.put(PrimarySkillType.ALCHEMY, result.getFloat(OFFSET_XP + 13));
  970. // Taming - Unused - result.getInt(OFFSET_DATS + 1)
  971. skillsDATS.put(SuperAbilityType.SUPER_BREAKER, result.getInt(OFFSET_DATS + 2));
  972. // Repair - Unused - result.getInt(OFFSET_DATS + 3)
  973. skillsDATS.put(SuperAbilityType.TREE_FELLER, result.getInt(OFFSET_DATS + 4));
  974. skillsDATS.put(SuperAbilityType.BERSERK, result.getInt(OFFSET_DATS + 5));
  975. skillsDATS.put(SuperAbilityType.GREEN_TERRA, result.getInt(OFFSET_DATS + 6));
  976. skillsDATS.put(SuperAbilityType.GIGA_DRILL_BREAKER, result.getInt(OFFSET_DATS + 7));
  977. // Archery - Unused - result.getInt(OFFSET_DATS + 8)
  978. skillsDATS.put(SuperAbilityType.SERRATED_STRIKES, result.getInt(OFFSET_DATS + 9));
  979. skillsDATS.put(SuperAbilityType.SKULL_SPLITTER, result.getInt(OFFSET_DATS + 10));
  980. // Acrobatics - Unused - result.getInt(OFFSET_DATS + 11)
  981. skillsDATS.put(SuperAbilityType.BLAST_MINING, result.getInt(OFFSET_DATS + 12));
  982. uniqueData.put(UniqueDataType.CHIMAERA_WING_DATS, result.getInt(OFFSET_DATS + 13));
  983. try {
  984. mobHealthbarType = MobHealthbarType.valueOf(result.getString(OFFSET_OTHER + 1));
  985. }
  986. catch (Exception e) {
  987. mobHealthbarType = Config.getInstance().getMobHealthbarDefault();
  988. }
  989. try {
  990. scoreboardTipsShown = result.getInt(OFFSET_OTHER + 2);
  991. }
  992. catch (Exception e) {
  993. scoreboardTipsShown = 0;
  994. }
  995. try {
  996. uuid = UUID.fromString(result.getString(OFFSET_OTHER + 3));
  997. }
  998. catch (Exception e) {
  999. uuid = null;
  1000. }
  1001. return new PlayerProfile(playerName, uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown, uniqueData);
  1002. }
  1003. private void printErrors(SQLException ex) {
  1004. if (debug) {
  1005. ex.printStackTrace();
  1006. }
  1007. StackTraceElement element = ex.getStackTrace()[0];
  1008. mcMMO.p.getLogger().severe("Location: " + element.getClassName() + " " + element.getMethodName() + " " + element.getLineNumber());
  1009. mcMMO.p.getLogger().severe("SQLException: " + ex.getMessage());
  1010. mcMMO.p.getLogger().severe("SQLState: " + ex.getSQLState());
  1011. mcMMO.p.getLogger().severe("VendorError: " + ex.getErrorCode());
  1012. }
  1013. public DatabaseType getDatabaseType() {
  1014. return DatabaseType.SQL;
  1015. }
  1016. private void checkNameUniqueness(final Statement statement) {
  1017. ResultSet resultSet = null;
  1018. try {
  1019. resultSet = statement.executeQuery("SHOW INDEXES "
  1020. + "FROM `" + tablePrefix + "users` "
  1021. + "WHERE Column_name='user' "
  1022. + " AND NOT Non_unique");
  1023. if (!resultSet.next()) {
  1024. return;
  1025. }
  1026. resultSet.close();
  1027. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables to drop name uniqueness...");
  1028. statement.execute("ALTER TABLE `" + tablePrefix + "users` "
  1029. + "DROP INDEX `user`,"
  1030. + "ADD INDEX `user` (`user`(20) ASC)");
  1031. } catch (SQLException ex) {
  1032. ex.printStackTrace();
  1033. } finally {
  1034. tryClose(resultSet);
  1035. }
  1036. }
  1037. private void checkUpgradeAddAlchemy(final Statement statement) throws SQLException {
  1038. try {
  1039. statement.executeQuery("SELECT `alchemy` FROM `" + tablePrefix + "skills` LIMIT 1");
  1040. }
  1041. catch (SQLException ex) {
  1042. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Alchemy...");
  1043. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD `alchemy` int(10) NOT NULL DEFAULT '0'");
  1044. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "experience` ADD `alchemy` int(10) NOT NULL DEFAULT '0'");
  1045. }
  1046. }
  1047. private void checkUpgradeAddBlastMiningCooldown(final Statement statement) throws SQLException {
  1048. try {
  1049. statement.executeQuery("SELECT `blast_mining` FROM `" + tablePrefix + "cooldowns` LIMIT 1");
  1050. }
  1051. catch (SQLException ex) {
  1052. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Blast Mining...");
  1053. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "cooldowns` ADD `blast_mining` int(32) NOT NULL DEFAULT '0'");
  1054. }
  1055. }
  1056. private void checkUpgradeAddUniqueChimaeraWing(final Statement statement) throws SQLException {
  1057. try {
  1058. statement.executeQuery("SELECT `chimaera_wing` FROM `" + tablePrefix + "cooldowns` LIMIT 1");
  1059. }
  1060. catch (SQLException ex) {
  1061. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Chimaera Wing...");
  1062. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "cooldowns` ADD `chimaera_wing` int(32) NOT NULL DEFAULT '0'");
  1063. }
  1064. }
  1065. private void checkUpgradeAddFishing(final Statement statement) throws SQLException {
  1066. try {
  1067. statement.executeQuery("SELECT `fishing` FROM `" + tablePrefix + "skills` LIMIT 1");
  1068. }
  1069. catch (SQLException ex) {
  1070. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Fishing...");
  1071. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD `fishing` int(10) NOT NULL DEFAULT '0'");
  1072. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "experience` ADD `fishing` int(10) NOT NULL DEFAULT '0'");
  1073. }
  1074. }
  1075. private void checkUpgradeAddMobHealthbars(final Statement statement) throws SQLException {
  1076. try {
  1077. statement.executeQuery("SELECT `mobhealthbar` FROM `" + tablePrefix + "huds` LIMIT 1");
  1078. }
  1079. catch (SQLException ex) {
  1080. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for mob healthbars...");
  1081. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "huds` ADD `mobhealthbar` varchar(50) NOT NULL DEFAULT '" + Config.getInstance().getMobHealthbarDefault() + "'");
  1082. }
  1083. }
  1084. private void checkUpgradeAddScoreboardTips(final Statement statement) throws SQLException {
  1085. try {
  1086. statement.executeQuery("SELECT `scoreboardtips` FROM `" + tablePrefix + "huds` LIMIT 1");
  1087. }
  1088. catch (SQLException ex) {
  1089. mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for scoreboard tips...");
  1090. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "huds` ADD `scoreboardtips` int(10) NOT NULL DEFAULT '0' ;");
  1091. }
  1092. }
  1093. private void checkUpgradeAddSQLIndexes(final Statement statement) {
  1094. ResultSet resultSet = null;
  1095. try {
  1096. resultSet = statement.executeQuery("SHOW INDEX FROM `" + tablePrefix + "skills` WHERE `Key_name` LIKE 'idx\\_%'");
  1097. resultSet.last();
  1098. if (resultSet.getRow() != PrimarySkillType.NON_CHILD_SKILLS.size()) {
  1099. mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases");
  1100. for (PrimarySkillType skill : PrimarySkillType.NON_CHILD_SKILLS) {
  1101. String skill_name = skill.name().toLowerCase(Locale.ENGLISH);
  1102. try {
  1103. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD INDEX `idx_" + skill_name + "` (`" + skill_name + "`) USING BTREE");
  1104. }
  1105. catch (SQLException ex) {
  1106. // Ignore
  1107. }
  1108. }
  1109. }
  1110. }
  1111. catch (SQLException ex) {
  1112. printErrors(ex);
  1113. }
  1114. finally {
  1115. tryClose(resultSet);
  1116. }
  1117. }
  1118. private void checkUpgradeAddUUIDs(final Statement statement) {
  1119. ResultSet resultSet = null;
  1120. try {
  1121. resultSet = statement.executeQuery("SELECT * FROM `" + tablePrefix + "users` LIMIT 1");
  1122. ResultSetMetaData rsmeta = resultSet.getMetaData();
  1123. boolean column_exists = false;
  1124. for (int i = 1; i <= rsmeta.getColumnCount(); i++) {
  1125. if (rsmeta.getColumnName(i).equalsIgnoreCase("uuid")) {
  1126. column_exists = true;
  1127. break;
  1128. }
  1129. }
  1130. if (!column_exists) {
  1131. mcMMO.p.getLogger().info("Adding UUIDs to mcMMO MySQL user table...");
  1132. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "users` ADD `uuid` varchar(36) NULL DEFAULT NULL");
  1133. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "users` ADD UNIQUE INDEX `uuid` (`uuid`) USING BTREE");
  1134. }
  1135. }
  1136. catch (SQLException ex) {
  1137. printErrors(ex);
  1138. }
  1139. finally {
  1140. tryClose(resultSet);
  1141. }
  1142. new GetUUIDUpdatesRequired().runTaskLaterAsynchronously(mcMMO.p, 100); // wait until after first purge
  1143. }
  1144. private class GetUUIDUpdatesRequired extends BukkitRunnable {
  1145. public void run() {
  1146. massUpdateLock.lock();
  1147. List<String> names = new ArrayList<String>();
  1148. Connection connection = null;
  1149. Statement statement = null;
  1150. ResultSet resultSet = null;
  1151. try {
  1152. try {
  1153. connection = miscPool.getConnection();
  1154. statement = connection.createStatement();
  1155. resultSet = statement.executeQuery("SELECT `user` FROM `" + tablePrefix + "users` WHERE `uuid` IS NULL");
  1156. while (resultSet.next()) {
  1157. names.add(resultSet.getString("user"));
  1158. }
  1159. } catch (SQLException ex) {
  1160. printErrors(ex);
  1161. } finally {
  1162. tryClose(resultSet);
  1163. tryClose(statement);
  1164. tryClose(connection);
  1165. }
  1166. if (!names.isEmpty()) {
  1167. new UUIDUpdateAsyncTask(mcMMO.p, names).run();
  1168. }
  1169. } finally {
  1170. massUpdateLock.unlock();
  1171. }
  1172. }
  1173. }
  1174. private void checkUpgradeDropPartyNames(final Statement statement) {
  1175. ResultSet resultSet = null;
  1176. try {
  1177. resultSet = statement.executeQuery("SELECT * FROM `" + tablePrefix + "users` LIMIT 1");
  1178. ResultSetMetaData rsmeta = resultSet.getMetaData();
  1179. boolean column_exists = false;
  1180. for (int i = 1; i <= rsmeta.getColumnCount(); i++) {
  1181. if (rsmeta.getColumnName(i).equalsIgnoreCase("party")) {
  1182. column_exists = true;
  1183. break;
  1184. }
  1185. }
  1186. if (column_exists) {
  1187. mcMMO.p.getLogger().info("Removing party name from users table...");
  1188. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "users` DROP COLUMN `party`");
  1189. }
  1190. }
  1191. catch (SQLException ex) {
  1192. printErrors(ex);
  1193. }
  1194. finally {
  1195. tryClose(resultSet);
  1196. }
  1197. }
  1198. private void checkUpgradeSkillTotal(final Connection connection) throws SQLException {
  1199. ResultSet resultSet = null;
  1200. Statement statement = null;
  1201. try {
  1202. connection.setAutoCommit(false);
  1203. statement = connection.createStatement();
  1204. resultSet = statement.executeQuery("SELECT * FROM `" + tablePrefix + "skills` LIMIT 1");
  1205. ResultSetMetaData rsmeta = resultSet.getMetaData();
  1206. boolean column_exists = false;
  1207. for (int i = 1; i <= rsmeta.getColumnCount(); i++) {
  1208. if (rsmeta.getColumnName(i).equalsIgnoreCase("total")) {
  1209. column_exists = true;
  1210. break;
  1211. }
  1212. }
  1213. if (!column_exists) {
  1214. mcMMO.p.getLogger().info("Adding skill total column to skills table...");
  1215. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD COLUMN `total` int NOT NULL DEFAULT '0'");
  1216. statement.executeUpdate("UPDATE `" + tablePrefix + "skills` SET `total` = (taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy)");
  1217. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD INDEX `idx_total` (`total`) USING BTREE");
  1218. connection.commit();
  1219. }
  1220. }
  1221. catch (SQLException ex) {
  1222. printErrors(ex);
  1223. }
  1224. finally {
  1225. connection.setAutoCommit(true);
  1226. tryClose(resultSet);
  1227. tryClose(statement);
  1228. }
  1229. }
  1230. private void checkUpgradeDropSpout(final Statement statement) {
  1231. ResultSet resultSet = null;
  1232. try {
  1233. resultSet = statement.executeQuery("SELECT * FROM `" + tablePrefix + "huds` LIMIT 1");
  1234. ResultSetMetaData rsmeta = resultSet.getMetaData();
  1235. boolean column_exists = false;
  1236. for (int i = 1; i <= rsmeta.getColumnCount(); i++) {
  1237. if (rsmeta.getColumnName(i).equalsIgnoreCase("hudtype")) {
  1238. column_exists = true;
  1239. break;
  1240. }
  1241. }
  1242. if (column_exists) {
  1243. mcMMO.p.getLogger().info("Removing Spout HUD type from huds table...");
  1244. statement.executeUpdate("ALTER TABLE `" + tablePrefix + "huds` DROP COLUMN `hudtype`");
  1245. }
  1246. }
  1247. catch (SQLException ex) {
  1248. printErrors(ex);
  1249. }
  1250. finally {
  1251. tryClose(resultSet);
  1252. }
  1253. }
  1254. private int getUserID(final Connection connection, final String playerName, final UUID uuid) {
  1255. if (uuid == null)
  1256. return getUserIDByName(connection, playerName);
  1257. if (cachedUserIDs.containsKey(uuid))
  1258. return cachedUserIDs.get(uuid);
  1259. ResultSet resultSet = null;
  1260. PreparedStatement statement = null;
  1261. try {
  1262. statement = connection.prepareStatement("SELECT id, user FROM " + tablePrefix + "users WHERE uuid = ? OR (uuid IS NULL AND user = ?)");
  1263. statement.setString(1, uuid.toString());
  1264. statement.setString(2, playerName);
  1265. resultSet = statement.executeQuery();
  1266. if (resultSet.next()) {
  1267. int id = resultSet.getInt("id");
  1268. cachedUserIDs.put(uuid, id);
  1269. return id;
  1270. }
  1271. }
  1272. catch (SQLException ex) {
  1273. printErrors(ex);
  1274. }
  1275. finally {
  1276. tryClose(resultSet);
  1277. tryClose(statement);
  1278. }
  1279. return -1;
  1280. }
  1281. private int getUserIDByName(final Connection connection, final String playerName) {
  1282. ResultSet resultSet = null;
  1283. PreparedStatement statement = null;
  1284. try {
  1285. statement = connection.prepareStatement("SELECT id, user FROM " + tablePrefix + "users WHERE user = ?");
  1286. statement.setString(1, playerName);
  1287. resultSet = statement.executeQuery();
  1288. if (resultSet.next()) {
  1289. int id = resultSet.getInt("id");
  1290. return id;
  1291. }
  1292. }
  1293. catch (SQLException ex) {
  1294. printErrors(ex);
  1295. }
  1296. finally {
  1297. tryClose(resultSet);
  1298. tryClose(statement);
  1299. }
  1300. return -1;
  1301. }
  1302. private void tryClose(AutoCloseable closeable) {
  1303. if (closeable != null) {
  1304. try {
  1305. closeable.close();
  1306. }
  1307. catch (Exception e) {
  1308. // Ignore
  1309. }
  1310. }
  1311. }
  1312. @Override
  1313. public void onDisable() {
  1314. mcMMO.p.debug("Releasing connection pool resource...");
  1315. miscPool.close();
  1316. loadPool.close();
  1317. savePool.close();
  1318. }
  1319. public enum PoolIdentifier {
  1320. MISC,
  1321. LOAD,
  1322. SAVE
  1323. }
  1324. public void resetMobHealthSettings() {
  1325. PreparedStatement statement = null;
  1326. Connection connection = null;
  1327. try {
  1328. connection = getConnection(PoolIdentifier.MISC);
  1329. statement = connection.prepareStatement("UPDATE " + tablePrefix + "huds SET mobhealthbar = ?");
  1330. statement.setString(1, Config.getInstance().getMobHealthbarDefault().toString());
  1331. statement.executeUpdate();
  1332. }
  1333. catch (SQLException ex) {
  1334. printErrors(ex);
  1335. }
  1336. finally {
  1337. tryClose(statement);
  1338. tryClose(connection);
  1339. }
  1340. }
  1341. }