diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000..3fbb8c079e
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,3 @@
+/docs
+/handbook
+/tools
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 99c411b1fa..d13e4644ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.idea/
*.iml
/target
+/docker-db-data
# build files
diff --git a/Dockerfile b/Dockerfile
index d37cf08b8e..b24fea224d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,13 +1,20 @@
-# Docker support, thanks to xinyifly
+# Initial Docker support thanks to xinyifly
-FROM openjdk:8u171-jdk-alpine
-RUN apk -U add tini
-WORKDIR /mnt
+#
+# Build stage
+#
+FROM maven:3.6.3-jdk-8 AS build
+COPY src /home/app/src
+COPY pom.xml /home/app
+RUN mvn -f /home/app/pom.xml clean package
+
+#
+# Package stage
+#
+FROM openjdk:8
+COPY --from=build /home/app/target/Cosmic.jar /usr/local/lib/Cosmic.jar
COPY ./ ./
-RUN sh ./posix-compile.sh
-ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.6.0/wait /wait
-RUN chmod +x /wait
-
EXPOSE 8484 7575 7576 7577
-ENTRYPOINT ["tini", "--"]
-CMD /wait && sh ./posix-launch.sh
+ENTRYPOINT ["java", "-jar", "/usr/local/lib/Cosmic.jar"]
+
+
diff --git a/config.yaml b/config.yaml
index 2fa1000331..4caedb49ea 100644
--- a/config.yaml
+++ b/config.yaml
@@ -162,10 +162,11 @@ server:
USE_THREAD_TRACKER: false #[SEVERE] This deadlock auditing thing will bloat the memory as fast as the time frame one takes to lose track of a raindrop on a tempesting day. Only for debugging purposes.
#Database Configuration
- DB_URL: "jdbc:mysql://localhost:3306/cosmic"
- DB_USER: "snail"
- DB_PASS: "shell"
- DB_CONNECTION_POOL: true #Installs a connection pool to hub DB connections. Set false to default.
+ DB_URL_FORMAT: "jdbc:mysql://%s:3306/cosmic"
+ DB_HOST: "localhost"
+ DB_USER: "cosmic_server"
+ DB_PASS: "snailshell"
+ INIT_CONNECTION_POOL_TIMEOUT: 60 # Seconds
#Login Configuration
WORLDS: 1 #Initial number of worlds on the server.
diff --git a/docker-compose.yml b/docker-compose.yml
index eb87edac6b..fc7334dedd 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,20 +1,22 @@
version: '3'
services:
maplestory:
- network_mode: "host"
build: .
depends_on:
- db
+ ports:
+ - "8484:8484"
+ - "7575-7577:7575-7577"
environment:
- WAIT_HOSTS: localhost:3306
+ DB_HOST: "db"
db:
- network_mode: "host"
- image: mysql:5.6
+ image: mysql:8.0.23
environment:
- MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
+ MYSQL_RANDOM_ROOT_PASSWORD: "true"
MYSQL_DATABASE: "cosmic"
- MYSQL_USER: "root"
- MYSQL_PASSWORD: ""
+ MYSQL_USER: "cosmic_server"
+ MYSQL_PASSWORD: "snailshell"
volumes:
+ - ./docker-db-data:/var/lib/mysql
- ./sql:/docker-entrypoint-initdb.d
diff --git a/launchtest.bat b/launchtest.bat
deleted file mode 100644
index b6a02eb5a9..0000000000
--- a/launchtest.bat
+++ /dev/null
@@ -1,61 +0,0 @@
-REM // 'launchtest.bat' Author: Tochi
-@echo off
-set a=0
-title HeavenMS: Offline
-color 1b
-:clear
-cls
-echo HeavenMS Server Launcher
-echo.
-echo Commands:
-echo -------------------------------------------------------------
-echo start - Start HeavenMS server
-echo shutdown - Shut down HeavenMS server and close Launcher File
-echo reset - Resets HeavenMS Launcher File
-echo clear - Clear this window
-echo -------------------------------------------------------------
-echo.
-
-:command
-set /p s="Enter command: "
-if "%s%"=="start" goto :start
-if "%s%"=="shutdown" goto :shutdown
-if "%s%"=="reset" goto :reset
-if "%s%"=="clear" goto :clear
-echo Wrong Command.
-echo.
-goto :command
-
-:start
-if "%a%"=="1" (
-echo HeavenMS is already active!
-echo.
-goto :command
-)
-color 4c
-echo This might take a while....
-echo.
-title HeavenMS: activating
-echo Server Launching...
-start /b launch.bat
-color 2a
-title HeavenMS: Online
-set a=1
-ping localhost -w 10000 >nul
-echo.
-goto :command
-
-:shutdown
-color 4c
-title HeavenMS: Shutting Down...
-echo The Server Launcher will be close in a few seconds.
-ping localhost -w 100000 >nul
-taskkill /im cmd.exe
-
-:reset
-color 4c
-title HeavenMS: Resetting...
-echo Please type 'start' in command box after bat file have been resetted.
-ping localhost -w 100000 >nul
-start launchtest.bat REM // thanks Paxum for noting that 'launchtest.bat' is to be used here
-taskkill /im cmd.exe
\ No newline at end of file
diff --git a/linux-compile.sh b/linux-compile.sh
deleted file mode 100755
index 9cfec04218..0000000000
--- a/linux-compile.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-# thanks to lkxyyjx
-sudo ant -Dplatforms.JDK_1.7.home=/opt/jdk1.7.0_80 compile
-sudo ant -Dplatforms.JDK_1.7.home=/opt/jdk1.7.0_80 jar
\ No newline at end of file
diff --git a/linux-launch.sh b/linux-launch.sh
deleted file mode 100644
index 40557cec8e..0000000000
--- a/linux-launch.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-# cores in classpath, thanks to lkxyyjx
-export CLASSPATH=".:dist/*:cores/*"
-java -Xmx2048m -Dwzpath=wz/ net.server.Server
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 81c5f754bc..7341ff2b53 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
mysql
mysql-connector-java
- 5.1.6
+ 8.0.23
org.slf4j
diff --git a/posix-compile.sh b/posix-compile.sh
deleted file mode 100644
index 1880dd8b58..0000000000
--- a/posix-compile.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-# compilation script for posix-compliant systems
-
-src=src
-dist=dist
-
-cores=$(echo cores/*)
-cores=${cores// /:}
-
-mkdir -p $dist
-javac -d $dist -cp $cores $(find $src -name "*.java")
diff --git a/posix-launch.sh b/posix-launch.sh
deleted file mode 100644
index 9222538da7..0000000000
--- a/posix-launch.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-# launch script
-cores=$(echo cores/*)
-cores=${cores// /:}
-cp=.:dist:$cores
-
-java -Xmx2048m -Dwzpath=wz -cp $cp net.server.Server
diff --git a/sql/db_database.sql b/sql/1-db_database.sql
similarity index 99%
rename from sql/db_database.sql
rename to sql/1-db_database.sql
index 1431167768..1d381f546c 100644
--- a/sql/db_database.sql
+++ b/sql/1-db_database.sql
@@ -21,7 +21,7 @@ CREATE TABLE IF NOT EXISTS `accounts` (
`loggedin` tinyint(4) NOT NULL DEFAULT '0',
`lastlogin` timestamp NULL DEFAULT NULL,
`createdat` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
- `birthday` date NOT NULL DEFAULT '0000-00-00',
+ `birthday` date NOT NULL DEFAULT '2005-05-11',
`banned` tinyint(1) NOT NULL DEFAULT '0',
`banreason` text,
`macs` tinytext,
@@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS `accounts` (
`nxPrepaid` int(11) DEFAULT NULL,
`characterslots` tinyint(2) NOT NULL DEFAULT '3',
`gender` tinyint(2) NOT NULL DEFAULT '10',
- `tempban` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `tempban` timestamp NOT NULL DEFAULT '2005-05-11 00:00:00',
`greason` tinyint(4) NOT NULL DEFAULT '0',
`tos` tinyint(1) NOT NULL DEFAULT '0',
`sitelogged` text,
diff --git a/sql/db_drops.sql b/sql/2-db_drops.sql
similarity index 100%
rename from sql/db_drops.sql
rename to sql/2-db_drops.sql
diff --git a/sql/db_shopupdate.sql b/sql/3-db_shopupdate.sql
similarity index 100%
rename from sql/db_shopupdate.sql
rename to sql/3-db_shopupdate.sql
diff --git a/src/main/java/client/DefaultDates.java b/src/main/java/client/DefaultDates.java
new file mode 100644
index 0000000000..68cbb3690d
--- /dev/null
+++ b/src/main/java/client/DefaultDates.java
@@ -0,0 +1,19 @@
+package client;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+final public class DefaultDates {
+ // May 11 2005 is the date MapleGlobal released, so it's a symbolic default value
+
+ private DefaultDates() {
+ }
+
+ public static LocalDate getBirthday() {
+ return LocalDate.parse("2005-05-11");
+ }
+
+ public static LocalDateTime getTempban() {
+ return LocalDateTime.parse("2005-05-11T00:00:00");
+ }
+}
diff --git a/src/main/java/client/MapleCharacter.java b/src/main/java/client/MapleCharacter.java
index e26a8ac49a..479450066d 100644
--- a/src/main/java/client/MapleCharacter.java
+++ b/src/main/java/client/MapleCharacter.java
@@ -30,6 +30,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -9777,7 +9778,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void showNote() {
try {
Connection con = DatabaseConnection.getConnection();
- try (PreparedStatement ps = con.prepareStatement("SELECT * FROM notes WHERE `to` = ? AND `deleted` = 0", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) {
+ try (PreparedStatement ps = con.prepareStatement("SELECT * FROM notes WHERE `to` = ? AND `deleted` = 0",
+ ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) {
ps.setString(1, this.getName());
try (ResultSet rs = ps.executeQuery()) {
rs.last();
@@ -11036,8 +11038,13 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
try (PreparedStatement ps = con.prepareStatement("SELECT tempban FROM accounts WHERE id = ?")) {
ps.setInt(1, accountId);
ResultSet rs = ps.executeQuery();
- if(!rs.next()) return "Account does not exist.";
- if(rs.getLong("tempban") != 0 && !rs.getString("tempban").equals("2018-06-20 00:00:00.0")) return "Account has been banned.";
+ if (!rs.next()) {
+ return "Account does not exist.";
+ }
+ LocalDateTime tempban = rs.getTimestamp("tempban").toLocalDateTime();
+ if(!tempban.equals(DefaultDates.getTempban())) {
+ return "Account has been banned.";
+ }
} catch(SQLException e) {
e.printStackTrace();
FilePrinter.printError(FilePrinter.CHANGE_CHARACTER_NAME, e);
diff --git a/src/main/java/client/MapleClient.java b/src/main/java/client/MapleClient.java
index bd8b34e773..8f131fa660 100644
--- a/src/main/java/client/MapleClient.java
+++ b/src/main/java/client/MapleClient.java
@@ -25,10 +25,8 @@ import java.io.*;
import java.net.InetAddress;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
+import java.sql.*;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -647,23 +645,24 @@ public class MapleClient {
ResultSet rs = null;
final Calendar lTempban = Calendar.getInstance();
try {
- con = DatabaseConnection.getConnection();
+ con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT `tempban` FROM accounts WHERE id = ?");
ps.setInt(1, getAccID());
rs = ps.executeQuery();
if (!rs.next()) {
return null;
}
- long blubb = rs.getLong("tempban");
-
- if (blubb == 0 || rs.getString("tempban").equals("2018-06-20 00:00:00.0")) { // 0000-00-00 or 2018-06-20 (default set in LoginPasswordHandler)
+
+ final Timestamp tempban = rs.getTimestamp("tempban");
+ if (tempban.toLocalDateTime().equals(DefaultDates.getTempban())) {
return null;
}
- lTempban.setTimeInMillis(rs.getTimestamp("tempban").getTime());
+
+ lTempban.setTimeInMillis(tempban.getTime());
tempBanCalendar = lTempban;
return lTempban;
} catch (SQLException e) {
- e.printStackTrace();
+ e.printStackTrace();
} finally {
try {
if (ps != null) {
@@ -672,11 +671,11 @@ public class MapleClient {
if (rs != null) {
rs.close();
}
- if (con != null && !con.isClosed()) {
+ if (con != null && !con.isClosed()) {
con.close();
}
} catch (SQLException e) {
- e.printStackTrace();
+ e.printStackTrace();
}
}
return null;//why oh why!?!
diff --git a/src/main/java/client/MonsterBook.java b/src/main/java/client/MonsterBook.java
index 235362d78f..95f320b298 100644
--- a/src/main/java/client/MonsterBook.java
+++ b/src/main/java/client/MonsterBook.java
@@ -247,9 +247,10 @@ public final class MonsterBook {
public static int[] getCardTierSize() {
try {
Connection con = DatabaseConnection.getConnection();
- PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM monstercarddata GROUP BY floor(cardid / 1000);");
+ PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM monstercarddata GROUP BY floor(cardid / 1000);",
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = ps.executeQuery();
-
+
rs.last();
int[] tierSizes = new int[rs.getRow()];
rs.beforeFirst();
diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java
index fbef750367..721c577e16 100644
--- a/src/main/java/config/ServerConfig.java
+++ b/src/main/java/config/ServerConfig.java
@@ -5,10 +5,11 @@ public class ServerConfig {
public boolean USE_THREAD_TRACKER;
//Database Configuration
- public String DB_URL;
+ public String DB_URL_FORMAT;
+ public String DB_HOST;
public String DB_USER;
public String DB_PASS;
- public boolean DB_CONNECTION_POOL;
+ public int INIT_CONNECTION_POOL_TIMEOUT;
//Login Configuration
public int WORLDS;
diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java
index f85be22624..27b8025f26 100644
--- a/src/main/java/net/server/Server.java
+++ b/src/main/java/net/server/Server.java
@@ -866,8 +866,13 @@ public class Server {
public void init() {
System.out.println("Cosmic v" + ServerConstants.VERSION + " starting up.\r\n");
- if(YamlConfig.config.server.SHUTDOWNHOOK)
+ if(YamlConfig.config.server.SHUTDOWNHOOK) {
Runtime.getRuntime().addShutdownHook(new Thread(shutdown(false)));
+ }
+
+ if (!DatabaseConnection.initializeConnectionPool()) {
+ throw new IllegalStateException("Failed to initiate a connection to the database");
+ }
TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE));
@@ -1620,7 +1625,8 @@ public class Server {
private static void applyAllWorldTransfers() {
try (Connection con = DatabaseConnection.getConnection();
- PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL")) {
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL",
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
ResultSet rs = ps.executeQuery();
List removedTransfers = new LinkedList();
while(rs.next()) {
diff --git a/src/main/java/net/server/channel/handlers/BBSOperationHandler.java b/src/main/java/net/server/channel/handlers/BBSOperationHandler.java
index 6f97a56e92..be4e545506 100644
--- a/src/main/java/net/server/channel/handlers/BBSOperationHandler.java
+++ b/src/main/java/net/server/channel/handlers/BBSOperationHandler.java
@@ -98,7 +98,8 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
private static void listBBSThreads(MapleClient c, int start) {
try {
Connection con = DatabaseConnection.getConnection();
- try (PreparedStatement ps = con.prepareStatement("SELECT * FROM bbs_threads WHERE guildid = ? ORDER BY localthreadid DESC")) {
+ try (PreparedStatement ps = con.prepareStatement("SELECT * FROM bbs_threads WHERE guildid = ? ORDER BY localthreadid DESC",
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
ps.setInt(1, c.getPlayer().getGuildId());
try (ResultSet rs = ps.executeQuery()) {
c.announce(MaplePacketCreator.BBSThreadList(rs, start));
diff --git a/src/main/java/net/server/guild/MapleGuild.java b/src/main/java/net/server/guild/MapleGuild.java
index a682cda6d7..73d7edc7e8 100644
--- a/src/main/java/net/server/guild/MapleGuild.java
+++ b/src/main/java/net/server/guild/MapleGuild.java
@@ -76,7 +76,7 @@ public class MapleGuild {
con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM guilds WHERE guildid = " + guildid);
ResultSet rs = ps.executeQuery();
- if (!rs.first()) {
+ if (!rs.next()) {
id = -1;
ps.close();
rs.close();
@@ -102,7 +102,7 @@ public class MapleGuild {
ps = con.prepareStatement("SELECT id, name, level, job, guildrank, allianceRank FROM characters WHERE guildid = ? ORDER BY guildrank ASC, name ASC");
ps.setInt(1, guildid);
rs = ps.executeQuery();
- if (!rs.first()) {
+ if (!rs.next()) {
rs.close();
ps.close();
return;
@@ -436,7 +436,7 @@ public class MapleGuild {
PreparedStatement ps = con.prepareStatement("SELECT guildid FROM guilds WHERE name = ?");
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
- if (rs.first()) {
+ if (rs.next()) {
ps.close();
rs.close();
return 0;
@@ -454,7 +454,7 @@ public class MapleGuild {
ps = con.prepareStatement("SELECT guildid FROM guilds WHERE leader = ?");
ps.setInt(1, leaderId);
rs = ps.executeQuery();
- rs.first();
+ rs.next();
int guildId = rs.getInt("guildid");
rs.close();
ps.close();
@@ -779,7 +779,8 @@ public class MapleGuild {
try {
ResultSet rs;
Connection con = DatabaseConnection.getConnection();
- try (PreparedStatement ps = con.prepareStatement("SELECT `name`, `GP`, `logoBG`, `logoBGColor`, `logo`, `logoColor` FROM guilds ORDER BY `GP` DESC LIMIT 50")) {
+ try (PreparedStatement ps = con.prepareStatement("SELECT `name`, `GP`, `logoBG`, `logoBGColor`, `logo`, `logoColor` FROM guilds ORDER BY `GP` DESC LIMIT 50",
+ ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) {
rs = ps.executeQuery();
c.announce(MaplePacketCreator.showGuildRanks(npcid, rs));
}
diff --git a/src/main/java/net/server/handlers/login/LoginPasswordHandler.java b/src/main/java/net/server/handlers/login/LoginPasswordHandler.java
index c5ddfed5c4..3039be8627 100644
--- a/src/main/java/net/server/handlers/login/LoginPasswordHandler.java
+++ b/src/main/java/net/server/handlers/login/LoginPasswordHandler.java
@@ -21,11 +21,11 @@
*/
package net.server.handlers.login;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
+import java.sql.*;
+import java.time.LocalDateTime;
import java.util.Calendar;
+import client.DefaultDates;
import config.YamlConfig;
import net.MaplePacketHandler;
import net.server.Server;
@@ -35,8 +35,7 @@ import tools.HexTool;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleClient;
-import java.sql.ResultSet;
-import java.sql.Statement;
+
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -100,8 +99,8 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
ps = con.prepareStatement("INSERT INTO accounts (name, password, birthday, tempban) VALUES (?, ?, ?, ?);", Statement.RETURN_GENERATED_KEYS); //Jayd: Added birthday, tempban
ps.setString(1, login);
ps.setString(2, YamlConfig.config.server.BCRYPT_MIGRATION ? BCrypt.hashpw(pwd, BCrypt.gensalt(12)) : hashpwSHA512(pwd));
- ps.setString(3, "2018-06-20"); //Jayd's idea: was added to solve the MySQL 5.7 strict checking (birthday)
- ps.setString(4, "2018-06-20"); //Jayd's idea: was added to solve the MySQL 5.7 strict checking (tempban)
+ ps.setDate(3, Date.valueOf(DefaultDates.getBirthday()));
+ ps.setTimestamp(4, Timestamp.valueOf(DefaultDates.getTempban()));
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
diff --git a/src/main/java/server/maps/MapleHiredMerchant.java b/src/main/java/server/maps/MapleHiredMerchant.java
index 261238e411..c87619d310 100644
--- a/src/main/java/server/maps/MapleHiredMerchant.java
+++ b/src/main/java/server/maps/MapleHiredMerchant.java
@@ -30,7 +30,6 @@ import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleInventoryManipulator;
import client.inventory.manipulator.MapleKarmaManipulator;
import client.processor.npc.FredrickProcessor;
-import com.mysql.jdbc.Statement;
import config.YamlConfig;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -309,7 +308,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
}
merchantMesos += price;
- try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET MerchantMesos = ? WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
+ try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET MerchantMesos = ? WHERE id = ?", PreparedStatement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, (int) Math.min(merchantMesos, Integer.MAX_VALUE));
ps.setInt(2, ownerId);
ps.executeUpdate();
@@ -383,7 +382,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
} else {
try {
Connection con = DatabaseConnection.getConnection();
- PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", Statement.RETURN_GENERATED_KEYS);
+ PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", PreparedStatement.RETURN_GENERATED_KEYS);
ps.setInt(1, ownerId);
ps.executeUpdate();
@@ -442,7 +441,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
player.setHasMerchant(false);
} else {
Connection con = DatabaseConnection.getConnection();
- try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", Statement.RETURN_GENERATED_KEYS)) {
+ try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0 WHERE id = ?", PreparedStatement.RETURN_GENERATED_KEYS)) {
ps.setInt(1, ownerId);
ps.executeUpdate();
}
diff --git a/src/main/java/tools/DatabaseConnection.java b/src/main/java/tools/DatabaseConnection.java
index e408be455f..875bf7ef44 100644
--- a/src/main/java/tools/DatabaseConnection.java
+++ b/src/main/java/tools/DatabaseConnection.java
@@ -1,10 +1,11 @@
package tools;
import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.DriverManager;
import java.sql.SQLException;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.concurrent.TimeUnit;
+
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@@ -16,82 +17,64 @@ import config.YamlConfig;
* @author Ronan - some connection pool to this beautiful code
*/
public class DatabaseConnection {
- private static HikariDataSource ds;
-
- public static Connection getConnection() throws SQLException {
- if(ds != null) {
- try {
- return ds.getConnection();
- } catch (SQLException sqle) {
- sqle.printStackTrace();
- }
- }
-
- int denies = 0;
- while(true) { // There is no way it can pass with a null out of here?
- try {
- return DriverManager.getConnection(YamlConfig.config.server.DB_URL, YamlConfig.config.server.DB_USER, YamlConfig.config.server.DB_PASS);
- } catch (SQLException sqle) {
- denies++;
-
- if(denies == 3) {
- // Give up, throw exception. Nothing good will come from this.
- FilePrinter.printError(FilePrinter.SQL_EXCEPTION, "SQL Driver refused to give a connection after " + denies + " tries. Problem: " + sqle.getMessage());
- throw sqle;
- }
- }
- }
- }
-
- private static int getNumberOfAccounts() {
- try {
- Connection con = DriverManager.getConnection(YamlConfig.config.server.DB_URL, YamlConfig.config.server.DB_USER, YamlConfig.config.server.DB_PASS);
- try (PreparedStatement ps = con.prepareStatement("SELECT count(*) FROM accounts")) {
- try (ResultSet rs = ps.executeQuery()) {
- rs.next();
- return rs.getInt(1);
- }
- } finally {
- con.close();
- }
- } catch(SQLException sqle) {
- return 20;
- }
- }
-
- public DatabaseConnection() {
- try {
- Class.forName("com.mysql.jdbc.Driver"); // touch the mysql driver
- } catch (ClassNotFoundException e) {
- System.out.println("[SEVERE] SQL Driver Not Found. Consider death by clams.");
- e.printStackTrace();
- }
-
- ds = null;
-
- if(YamlConfig.config.server.DB_CONNECTION_POOL) {
- // Connection Pool on database ftw!
-
- HikariConfig config = new HikariConfig();
- config.setJdbcUrl(YamlConfig.config.server.DB_URL);
-
- config.setUsername(YamlConfig.config.server.DB_USER);
- config.setPassword(YamlConfig.config.server.DB_PASS);
-
- // Make sure pool size is comfortable for the worst case scenario.
- // Under 100 accounts? Make it 10. Over 10000 accounts? Make it 30.
- int poolSize = (int)Math.ceil(0.00202020202 * getNumberOfAccounts() + 9.797979798);
- if(poolSize < 10) poolSize = 10;
- else if(poolSize > 30) poolSize = 30;
-
- config.setConnectionTimeout(30 * 1000);
- config.setMaximumPoolSize(poolSize);
-
- config.addDataSourceProperty("cachePrepStmts", true);
- config.addDataSourceProperty("prepStmtCacheSize", 25);
- config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
+ private static HikariDataSource dataSource;
- ds = new HikariDataSource(config);
+ public static Connection getConnection() throws SQLException {
+ if (dataSource == null) {
+ throw new IllegalStateException("Unable to get connection from uninitialized connection pool");
}
+
+ return dataSource.getConnection();
+ }
+
+ private static String getDbUrl() {
+ // Environment variables override what's defined in the config file
+ // This feature is used for the Docker support
+ String hostOverride = System.getenv("DB_HOST");
+ String host = hostOverride != null ? hostOverride : YamlConfig.config.server.DB_HOST;
+ String dbUrl = String.format(YamlConfig.config.server.DB_URL_FORMAT, host);
+ return dbUrl;
+ }
+
+ private static HikariConfig getConfig() {
+ HikariConfig config = new HikariConfig();
+
+ config.setJdbcUrl(getDbUrl());
+ config.setUsername(YamlConfig.config.server.DB_USER);
+ config.setPassword(YamlConfig.config.server.DB_PASS);
+
+ final int initFailTimeoutSeconds = YamlConfig.config.server.INIT_CONNECTION_POOL_TIMEOUT;
+ config.setInitializationFailTimeout(TimeUnit.SECONDS.toMillis(initFailTimeoutSeconds));
+ config.setConnectionTimeout(30 * 1000); // Hikari default
+ config.setMaximumPoolSize(10); // Hikari default
+
+ config.addDataSourceProperty("cachePrepStmts", true);
+ config.addDataSourceProperty("prepStmtCacheSize", 25);
+ config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
+
+ return config;
+ }
+
+ /**
+ * Initiate connection to the database
+ *
+ * @return true if connection to the database initiated successfully, false if not successful
+ */
+ public static boolean initializeConnectionPool() {
+ System.out.println("Initializing connection pool...");
+ final HikariConfig config = getConfig();
+ Instant initStart = Instant.now();
+ try {
+ dataSource = new HikariDataSource(config);
+ long initDuration = Duration.between(initStart, Instant.now()).toMillis();
+ System.out.printf("Connection pool initialized in %d ms%n", initDuration);
+ return true;
+ } catch (Exception e) {
+ long timeout = Duration.between(initStart, Instant.now()).getSeconds();
+ System.err.printf("Failed to initialize database connection pool. Gave up after %d seconds.%n", timeout);
+ }
+
+ // Timed out - failed to initialize
+ return false;
}
}
diff --git a/tools/MapleArrowFetcher/src/tools/DatabaseConnection.java b/tools/MapleArrowFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleArrowFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleArrowFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;
diff --git a/tools/MapleCashCosmeticsFetcher/src/tools/DatabaseConnection.java b/tools/MapleCashCosmeticsFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleCashCosmeticsFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleCashCosmeticsFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;
diff --git a/tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java b/tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java
index dadddcdc29..cc610c9fcd 100644
--- a/tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java
+++ b/tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java
@@ -50,8 +50,8 @@ import tools.Pair;
public class MapleCashDropFetcher {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String wzPath = "../../wz";
diff --git a/tools/MapleCashDropFetcher/src/tools/DatabaseConnection.java b/tools/MapleCashDropFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleCashDropFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleCashDropFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;
diff --git a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java b/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java
index ac3a25d7cb..45e2abab35 100644
--- a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java
+++ b/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java
@@ -47,8 +47,8 @@ import java.sql.Statement;
public class MapleCodeCouponGenerator {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static Connection con = null;
static InputStreamReader fileReader = null;
diff --git a/tools/MapleCouponInstaller/src/maplecouponinstaller/MapleCouponInstaller.java b/tools/MapleCouponInstaller/src/maplecouponinstaller/MapleCouponInstaller.java
index 81c466170f..659a48550b 100644
--- a/tools/MapleCouponInstaller/src/maplecouponinstaller/MapleCouponInstaller.java
+++ b/tools/MapleCouponInstaller/src/maplecouponinstaller/MapleCouponInstaller.java
@@ -37,8 +37,8 @@ import java.sql.SQLException;
public class MapleCouponInstaller {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static Connection con = null;
static InputStreamReader fileReader = null;
diff --git a/tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java b/tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java
index 76438d274a..b490a31156 100644
--- a/tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java
+++ b/tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java
@@ -57,8 +57,8 @@ public class MapleGachaponItemidRetriever {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static Connection con = null;
static InputStreamReader fileReader = null;
diff --git a/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java b/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java
index d9a7b66837..7ac88eb733 100644
--- a/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java
+++ b/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java
@@ -50,8 +50,8 @@ public class MapleIdRetriever {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static Connection con = null;
static InputStreamReader fileReader = null;
diff --git a/tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java b/tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java
index 985d9d7d79..1647758035 100644
--- a/tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java
+++ b/tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java
@@ -50,8 +50,8 @@ import java.util.Set;
public class MapleNoItemIdFetcher {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String wzPath = "../../wz";
static String newFile = "lib/result.txt";
diff --git a/tools/MapleInvalidItemWithNoNameFetcher/src/tools/DatabaseConnection.java b/tools/MapleInvalidItemWithNoNameFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleInvalidItemWithNoNameFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleInvalidItemWithNoNameFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;
diff --git a/tools/MapleMesoFetcher/src/tools/DatabaseConnection.java b/tools/MapleMesoFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleMesoFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleMesoFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;
diff --git a/tools/MapleMobBookIndexer/src/maplemobbookindexer/MapleMobBookIndexer.java b/tools/MapleMobBookIndexer/src/maplemobbookindexer/MapleMobBookIndexer.java
index 87a5a28288..ded162c95c 100644
--- a/tools/MapleMobBookIndexer/src/maplemobbookindexer/MapleMobBookIndexer.java
+++ b/tools/MapleMobBookIndexer/src/maplemobbookindexer/MapleMobBookIndexer.java
@@ -38,8 +38,8 @@ import java.io.*;
public class MapleMobBookIndexer {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String fileName = "lib/MonsterBook.img.xml";
diff --git a/tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java b/tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java
index 83db149e45..158ce16788 100644
--- a/tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java
+++ b/tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java
@@ -48,8 +48,8 @@ import java.io.*;
public class MapleMobBookUpdate {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String fileName = "lib/MonsterBook.img.xml";
static String newFile = "lib/MonsterBook_updated.img.xml";
diff --git a/tools/MapleQuestItemFetcher/src/maplequestitemfetcher/MapleQuestItemFetcher.java b/tools/MapleQuestItemFetcher/src/maplequestitemfetcher/MapleQuestItemFetcher.java
index 5cb97996f0..53c6fd5120 100644
--- a/tools/MapleQuestItemFetcher/src/maplequestitemfetcher/MapleQuestItemFetcher.java
+++ b/tools/MapleQuestItemFetcher/src/maplequestitemfetcher/MapleQuestItemFetcher.java
@@ -67,8 +67,8 @@ public class MapleQuestItemFetcher {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String wzPath = "../../wz";
static String directoryName = "../..";
diff --git a/tools/MapleQuestItemFetcher/src/tools/DatabaseConnection.java b/tools/MapleQuestItemFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleQuestItemFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleQuestItemFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;
diff --git a/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java b/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java
index 880c83c037..c0ab9703f4 100644
--- a/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java
+++ b/tools/MapleReactorDropFetcher/src/maplereactordropfetcher/MapleReactorDropFetcher.java
@@ -46,8 +46,8 @@ import java.io.File;
public class MapleReactorDropFetcher {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String reactorScriptPath = "../../scripts/reactor";
diff --git a/tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleSkillMakerFetcher.java b/tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleSkillMakerFetcher.java
index 75b3f70e36..a2dc506673 100644
--- a/tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleSkillMakerFetcher.java
+++ b/tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleSkillMakerFetcher.java
@@ -38,8 +38,8 @@ import java.io.*;
public class MapleSkillMakerFetcher {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String fileName = "../../wz/Etc.wz/ItemMake.img.xml";
static String newFile = "lib/MakerData.sql";
diff --git a/tools/MapleSkillMakerReagentIndexer/src/mapleskillmakerreagentindexer/MapleSkillMakerReagentIndexer.java b/tools/MapleSkillMakerReagentIndexer/src/mapleskillmakerreagentindexer/MapleSkillMakerReagentIndexer.java
index 8cbffaff2a..c4f012fcab 100644
--- a/tools/MapleSkillMakerReagentIndexer/src/mapleskillmakerreagentindexer/MapleSkillMakerReagentIndexer.java
+++ b/tools/MapleSkillMakerReagentIndexer/src/mapleskillmakerreagentindexer/MapleSkillMakerReagentIndexer.java
@@ -42,8 +42,8 @@ import java.util.List;
public class MapleSkillMakerReagentIndexer {
static String host = "jdbc:mysql://localhost:3306/cosmic";
static String driver = "com.mysql.jdbc.Driver";
- static String username = "snail";
- static String password = "shell";
+ static String username = "cosmic_server";
+ static String password = "snailshell";
static String fileName = "../../wz/Item.wz/Etc/0425.img.xml";
static String newFile = "lib/MakerReagentData.sql";
diff --git a/tools/MapleSkillbookChanceFetcher/src/tools/DatabaseConnection.java b/tools/MapleSkillbookChanceFetcher/src/tools/DatabaseConnection.java
index 0b882cb279..b887280343 100644
--- a/tools/MapleSkillbookChanceFetcher/src/tools/DatabaseConnection.java
+++ b/tools/MapleSkillbookChanceFetcher/src/tools/DatabaseConnection.java
@@ -10,8 +10,8 @@ import java.sql.SQLException;
*/
public class DatabaseConnection {
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
- private static String DB_USER = "snail";
- private static String DB_PASS = "shell";
+ private static String DB_USER = "cosmic_server";
+ private static String DB_PASS = "snailshell";
public static final int RETURN_GENERATED_KEYS = 1;