diff --git a/database/sql/1-db_database.sql b/database/sql/1-db_database.sql index 1d381f546c..c24fc76912 100644 --- a/database/sql/1-db_database.sql +++ b/database/sql/1-db_database.sql @@ -15978,9 +15978,11 @@ CREATE TABLE IF NOT EXISTS `medalmaps` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; CREATE TABLE IF NOT EXISTS `monsterbook` ( - `charid` int(11) unsigned NOT NULL, + `charid` int(11) NOT NULL, `cardid` int(11) NOT NULL, - `level` int(1) DEFAULT '1' + `level` int(1) NOT NULL DEFAULT '1', + PRIMARY KEY (`charid`, `cardid`), + CONSTRAINT `FK_monsterbook_characters` FOREIGN KEY (`charid`) REFERENCES `characters`(`id`) ON UPDATE CASCADE ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE IF NOT EXISTS `monstercarddata` ( diff --git a/database/sql/migration/monsterbook.sql b/database/sql/migration/monsterbook.sql new file mode 100644 index 0000000000..be886cb925 --- /dev/null +++ b/database/sql/migration/monsterbook.sql @@ -0,0 +1,4 @@ +ALTER TABLE cosmic.`monsterbook` +CHANGE COLUMN `charid` `charid` INT(11) NOT NULL, +ADD PRIMARY KEY (`charid`, `cardid`), +ADD CONSTRAINT `FK_monsterbook_1` FOREIGN KEY (`charid`) REFERENCES `characters` (`id`) ON UPDATE CASCADE ON DELETE CASCADE; \ No newline at end of file diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index 14437d463a..284e5abdc8 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -8464,7 +8464,7 @@ public class Character extends AbstractCharacterObject { ps.setInt(i + 31, getSlots(i)); } - monsterbook.saveCards(getId()); + monsterbook.saveCards(con, id); ps.setInt(36, bookCover); ps.setInt(37, vanquisherStage); diff --git a/src/main/java/client/MonsterBook.java b/src/main/java/client/MonsterBook.java index 1919fb344c..d354ab84e7 100644 --- a/src/main/java/client/MonsterBook.java +++ b/src/main/java/client/MonsterBook.java @@ -32,12 +32,9 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import java.util.Map.Entry; -import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; public final class MonsterBook { - private static final Semaphore semaphore = new Semaphore(10); - private int specialCard = 0; private int normalCard = 0; private int bookLevel = 1; @@ -180,61 +177,27 @@ public final class MonsterBook { calculateLevel(); } - private static int saveStringConcat(char[] data, int pos, Integer i) { - return saveStringConcat(data, pos, i.toString()); - } + public void saveCards(Connection con, int chrId) throws SQLException { + final String query = """ + INSERT INTO monsterbook (charid, cardid, level) + VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE level = ?; + """; + try (final PreparedStatement ps = con.prepareStatement(query)) { + for (Map.Entry cardAndLevel : cards.entrySet()) { + final int card = cardAndLevel.getKey(); + final int level = cardAndLevel.getValue(); + // insert + ps.setInt(1, chrId); + ps.setInt(2, card); + ps.setInt(3, level); - private static int saveStringConcat(char[] data, int pos, String s) { - int len = s.length(); - for (int j = 0; j < len; j++) { - data[pos + j] = s.charAt(j); - } + // update + ps.setInt(4, level); - return pos + len; - } - - private static String getSaveString(Integer charid, Set> cardSet) { - semaphore.acquireUninterruptibly(); - try { - char[] save = new char[400000]; // 500 * 10 * 10 * 8 - int i = 0; - - i = saveStringConcat(save, i, "INSERT INTO monsterbook VALUES "); - - for (Entry all : cardSet) { // assuming maxsize 500 unique cards - i = saveStringConcat(save, i, "("); - i = saveStringConcat(save, i, charid); //10 chars - i = saveStringConcat(save, i, ", "); - i = saveStringConcat(save, i, all.getKey()); //10 chars - i = saveStringConcat(save, i, ", "); - i = saveStringConcat(save, i, all.getValue()); //1 char due to being 0 ~ 5 - i = saveStringConcat(save, i, "),"); + ps.addBatch(); } - - return new String(save, 0, i - 1); - } finally { - semaphore.release(); - } - } - - public void saveCards(final int charid) { - Set> cardSet = getCardSet(); - - if (cardSet.isEmpty()) { - return; - } - - try (Connection con = DatabaseConnection.getConnection()) { - try (PreparedStatement ps = con.prepareStatement("DELETE FROM monsterbook WHERE charid = ?")) { - ps.setInt(1, charid); - ps.executeUpdate(); - } - - try (PreparedStatement ps = con.prepareStatement(getSaveString(charid, cardSet))) { - ps.executeUpdate(); - } - } catch (SQLException e) { - e.printStackTrace(); + ps.executeBatch(); } }