diff --git a/src/main/java/client/processor/action/MakerProcessor.java b/src/main/java/client/processor/action/MakerProcessor.java index e1461536cd..bd8417628e 100644 --- a/src/main/java/client/processor/action/MakerProcessor.java +++ b/src/main/java/client/processor/action/MakerProcessor.java @@ -29,6 +29,8 @@ import config.YamlConfig; import constants.game.GameConstants; import constants.id.ItemId; import constants.inventory.ItemConstants; +import database.maker.MakerInfoProvider; +import database.maker.MakerReagent; import net.packet.InPacket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,19 +40,22 @@ import server.MakerItemFactory.MakerItemCreateEntry; import tools.PacketCreator; import tools.Pair; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author Ronan */ public class MakerProcessor { private static final Logger log = LoggerFactory.getLogger(MakerProcessor.class); - private static final ItemInformationProvider ii = ItemInformationProvider.getInstance(); - public static void makerAction(InPacket p, Client c) { + private final ItemInformationProvider ii = ItemInformationProvider.getInstance(); + private final MakerInfoProvider infoProvider; + + public MakerProcessor(MakerInfoProvider infoProvider) { + this.infoProvider = infoProvider; + } + + public void makerAction(InPacket p, Client c) { if (c.tryacquireClient()) { try { int type = p.readInt(); @@ -242,7 +247,7 @@ public class MakerProcessor { } // checks and prevents hackers from PE'ing Maker operations with invalid operations - private static boolean removeOddMakerReagents(int toCreate, Map reagentids) { + private boolean removeOddMakerReagents(int toCreate, Map reagentids) { Map reagentType = new LinkedHashMap<>(); List toRemove = new LinkedList<>(); @@ -283,7 +288,7 @@ public class MakerProcessor { return true; } - private static int getMakerReagentSlots(int itemId) { + private int getMakerReagentSlots(int itemId) { try { int eqpLevel = ii.getEquipLevelReq(itemId); @@ -299,7 +304,7 @@ public class MakerProcessor { } } - private static Pair>> generateDisassemblyInfo(int itemId) { + private Pair>> generateDisassemblyInfo(int itemId) { int recvFee = ii.getMakerDisassembledFee(itemId); if (recvFee > -1) { List> gains = ii.getMakerDisassembledItems(itemId); @@ -311,11 +316,11 @@ public class MakerProcessor { return null; } - public static int getMakerSkillLevel(Character chr) { + private int getMakerSkillLevel(Character chr) { return chr.getSkillLevel((chr.getJob().getId() / 1000) * 10000000 + 1007); } - private static short getCreateStatus(Client c, MakerItemCreateEntry recipe) { + private short getCreateStatus(Client c, MakerItemCreateEntry recipe) { if (recipe.isInvalid()) { return -1; } @@ -358,7 +363,7 @@ public class MakerProcessor { return 0; } - private static boolean hasItems(Client c, MakerItemCreateEntry recipe) { + private boolean hasItems(Client c, MakerItemCreateEntry recipe) { for (Pair p : recipe.getReqItems()) { int itemId = p.getLeft(); if (c.getPlayer().getInventory(ItemConstants.getInventoryType(itemId)).countById(itemId) < p.getRight()) { @@ -368,7 +373,7 @@ public class MakerProcessor { return true; } - private static boolean addBoostedMakerItem(Client c, int itemid, int stimulantid, Map reagentids) { + private boolean addBoostedMakerItem(Client c, int itemid, int stimulantid, Map reagentids) { if (stimulantid != -1 && !ItemInformationProvider.rollSuccessChance(90.0)) { return false; } @@ -396,37 +401,32 @@ public class MakerProcessor { List randStat = new LinkedList<>(); for (Map.Entry r : reagentids.entrySet()) { - Pair reagentBuff = ii.getMakerReagentStatUpgrade(r.getKey()); - - if (reagentBuff != null) { - String s = reagentBuff.getLeft(); - - if (s.substring(0, 4).contains("rand")) { - if (s.substring(4).equals("Stat")) { - randStat.add((short) (reagentBuff.getRight() * r.getValue())); - } else { - randOption.add((short) (reagentBuff.getRight() * r.getValue())); - } + Optional reagentBuff = infoProvider.getMakerReagent(r.getKey()); + if (reagentBuff.isEmpty()) { + continue; + } + String buffStat = reagentBuff.get().stat(); + int buffValue = reagentBuff.get().value(); + if (buffStat.substring(0, 4).contains("rand")) { + if (buffStat.substring(4).equals("Stat")) { + randStat.add((short) (buffValue * r.getValue())); } else { - String stat = s.substring(3); + randOption.add((short) (buffValue * r.getValue())); + } + } else { + String stat = buffStat.substring(3); - if (!stat.equals("ReqLevel")) { // improve req level... really? - switch (stat) { - case "MaxHP": - stat = "MHP"; - break; + if (!stat.equals("ReqLevel")) { // improve req level... really? + switch (stat) { + case "MaxHP" -> stat = "MHP"; + case "MaxMP" -> stat = "MMP"; + } - case "MaxMP": - stat = "MMP"; - break; - } - - Integer d = stats.get(stat); - if (d == null) { - stats.put(stat, reagentBuff.getRight() * r.getValue()); - } else { - stats.put(stat, d + (reagentBuff.getRight() * r.getValue())); - } + Integer d = stats.get(stat); + if (d == null) { + stats.put(stat, buffValue * r.getValue()); + } else { + stats.put(stat, d + (buffValue * r.getValue())); } } } diff --git a/src/main/java/database/PgDatabaseConnection.java b/src/main/java/database/PgDatabaseConnection.java index c8d3a254cd..f52f29426e 100644 --- a/src/main/java/database/PgDatabaseConnection.java +++ b/src/main/java/database/PgDatabaseConnection.java @@ -1,5 +1,6 @@ package database; +import database.maker.MakerReagentRowMapper; import database.note.NoteRowMapper; import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.Jdbi; @@ -14,8 +15,14 @@ public class PgDatabaseConnection { public PgDatabaseConnection(DataSource dataSource) { this.dataSource = dataSource; - this.jdbi = Jdbi.create(dataSource) - .registerRowMapper(new NoteRowMapper()); // TODO: configure jdbi elsewhere + this.jdbi = Jdbi.create(dataSource); + registerRowMappers(); + // TODO: configure jdbi elsewhere + } + + private void registerRowMappers() { + jdbi.registerRowMapper(new NoteRowMapper()) + .registerRowMapper(new MakerReagentRowMapper()); } public Connection getConnection() throws SQLException { diff --git a/src/main/java/database/maker/MakerDao.java b/src/main/java/database/maker/MakerDao.java new file mode 100644 index 0000000000..0a08df913e --- /dev/null +++ b/src/main/java/database/maker/MakerDao.java @@ -0,0 +1,30 @@ +package database.maker; + +import database.DaoException; +import database.PgDatabaseConnection; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.JdbiException; + +import java.util.Optional; + +public class MakerDao { + private final PgDatabaseConnection connection; + + public MakerDao(PgDatabaseConnection connection) { + this.connection = connection; + } + + public Optional getReagent(int itemId) { + try (Handle handle = connection.getHandle()) { + return handle.createQuery(""" + SELECT * + FROM maker_reagent + WHERE item_id = ?;""") + .bind(0, itemId) + .mapTo(MakerReagent.class) + .findOne(); + } catch (JdbiException e) { + throw new DaoException("Failed to get maker reagent with item id: %d".formatted(itemId), e); + } + } +} diff --git a/src/main/java/database/maker/MakerInfoProvider.java b/src/main/java/database/maker/MakerInfoProvider.java new file mode 100644 index 0000000000..b733aa6315 --- /dev/null +++ b/src/main/java/database/maker/MakerInfoProvider.java @@ -0,0 +1,28 @@ +package database.maker; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class MakerInfoProvider { + private final MakerDao makerDao; + private final Map reagents = new ConcurrentHashMap<>(); + + public MakerInfoProvider(MakerDao makerDao) { + this.makerDao = makerDao; + } + + public Optional getMakerReagent(int itemId) { + final MakerReagent cachedReagent = reagents.get(itemId); + if (cachedReagent != null) { + return Optional.of(cachedReagent); + } + + final Optional reagentFromDb = makerDao.getReagent(itemId); + if (reagentFromDb.isEmpty()) { + return Optional.empty(); + } + reagents.put(itemId, reagentFromDb.get()); + return reagentFromDb; + } +} diff --git a/src/main/java/database/maker/MakerReagent.java b/src/main/java/database/maker/MakerReagent.java new file mode 100644 index 0000000000..f5ba1aa87d --- /dev/null +++ b/src/main/java/database/maker/MakerReagent.java @@ -0,0 +1,9 @@ +package database.maker; + +import java.util.Objects; + +public record MakerReagent(int itemId, String stat, int value) { + public MakerReagent { + Objects.requireNonNull(stat); + } +} diff --git a/src/main/java/database/maker/MakerReagentRowMapper.java b/src/main/java/database/maker/MakerReagentRowMapper.java new file mode 100644 index 0000000000..7b28e4c597 --- /dev/null +++ b/src/main/java/database/maker/MakerReagentRowMapper.java @@ -0,0 +1,18 @@ +package database.maker; + +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.statement.StatementContext; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class MakerReagentRowMapper implements RowMapper { + + @Override + public MakerReagent map(ResultSet rs, StatementContext ctx) throws SQLException { + int itemId = rs.getInt("item_id"); + String stat = rs.getString("stat"); + int value = rs.getInt("value"); + return new MakerReagent(itemId, stat, value); + } +} diff --git a/src/main/java/net/ChannelDependencies.java b/src/main/java/net/ChannelDependencies.java index a6660f494d..40f8bce69b 100644 --- a/src/main/java/net/ChannelDependencies.java +++ b/src/main/java/net/ChannelDependencies.java @@ -1,14 +1,18 @@ package net; +import client.processor.action.MakerProcessor; import client.processor.npc.FredrickProcessor; import service.NoteService; import java.util.Objects; -public record ChannelDependencies(NoteService noteService, FredrickProcessor fredrickProcessor) { +public record ChannelDependencies( + NoteService noteService, FredrickProcessor fredrickProcessor, MakerProcessor makerProcessor +) { public ChannelDependencies { Objects.requireNonNull(noteService); Objects.requireNonNull(fredrickProcessor); + Objects.requireNonNull(makerProcessor); } } diff --git a/src/main/java/net/PacketProcessor.java b/src/main/java/net/PacketProcessor.java index 391143cb1a..44de836339 100644 --- a/src/main/java/net/PacketProcessor.java +++ b/src/main/java/net/PacketProcessor.java @@ -233,7 +233,7 @@ public final class PacketProcessor { registerHandler(RecvOpcode.REPORT, new ReportHandler()); registerHandler(RecvOpcode.MONSTER_BOOK_COVER, new MonsterBookCoverHandler()); registerHandler(RecvOpcode.AUTO_DISTRIBUTE_AP, new AutoAssignHandler()); - registerHandler(RecvOpcode.MAKER_SKILL, new MakerSkillHandler()); + registerHandler(RecvOpcode.MAKER_SKILL, new MakerSkillHandler(channelDeps.makerProcessor())); registerHandler(RecvOpcode.OPEN_FAMILY_PEDIGREE, new OpenFamilyPedigreeHandler()); registerHandler(RecvOpcode.OPEN_FAMILY, new OpenFamilyHandler()); registerHandler(RecvOpcode.ADD_FAMILY, new FamilyAddHandler()); @@ -286,4 +286,4 @@ public final class PacketProcessor { registerHandler(RecvOpcode.USE_ITEMUI, new RaiseIncExpHandler()); registerHandler(RecvOpcode.CHANGE_QUICKSLOT, new QuickslotKeyMappedModifiedHandler()); } -} \ No newline at end of file +} diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index c2c985964c..d985bbc185 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -30,6 +30,7 @@ import client.inventory.Item; import client.inventory.ItemFactory; import client.inventory.manipulator.CashIdGenerator; import client.newyear.NewYearCardRecord; +import client.processor.action.MakerProcessor; import client.processor.npc.FredrickProcessor; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; @@ -41,6 +42,8 @@ import constants.net.OpcodeConstants; import constants.net.ServerConstants; import database.PgDatabaseConfig; import database.PgDatabaseConnection; +import database.maker.MakerDao; +import database.maker.MakerInfoProvider; import database.migration.FlywayRunner; import database.note.NoteDao; import net.ChannelDependencies; @@ -969,8 +972,10 @@ public class Server { private ChannelDependencies registerChannelDependencies(PgDatabaseConnection connection) { NoteService noteService = new NoteService(new NoteDao(connection)); + MakerProcessor makerProcessor = new MakerProcessor(new MakerInfoProvider(new MakerDao(connection))); FredrickProcessor fredrickProcessor = new FredrickProcessor(noteService); - ChannelDependencies channelDependencies = new ChannelDependencies(noteService, fredrickProcessor); + ChannelDependencies channelDependencies = new ChannelDependencies(noteService, fredrickProcessor, + makerProcessor); PacketProcessor.registerGameHandlerDependencies(channelDependencies); diff --git a/src/main/java/net/server/channel/handlers/MakerSkillHandler.java b/src/main/java/net/server/channel/handlers/MakerSkillHandler.java index daa72eb776..2e0be08d72 100644 --- a/src/main/java/net/server/channel/handlers/MakerSkillHandler.java +++ b/src/main/java/net/server/channel/handlers/MakerSkillHandler.java @@ -30,9 +30,14 @@ import net.packet.InPacket; * @author Jay Estrella, Ronan */ public final class MakerSkillHandler extends AbstractPacketHandler { + private final MakerProcessor makerProcessor; + + public MakerSkillHandler(MakerProcessor makerProcessor) { + this.makerProcessor = makerProcessor; + } @Override - public final void handlePacket(InPacket p, Client c) { - MakerProcessor.makerAction(p, c); + public void handlePacket(InPacket p, Client c) { + makerProcessor.makerAction(p, c); } } diff --git a/src/main/java/server/ItemInformationProvider.java b/src/main/java/server/ItemInformationProvider.java index c2a04457f5..82bed494d9 100644 --- a/src/main/java/server/ItemInformationProvider.java +++ b/src/main/java/server/ItemInformationProvider.java @@ -1985,37 +1985,6 @@ public class ItemInformationProvider { } } - public Pair getMakerReagentStatUpgrade(int itemId) { - try { - Pair statUpgd = statUpgradeMakerCache.get(itemId); - if (statUpgd != null) { - return statUpgd; - } else if (statUpgradeMakerCache.containsKey(itemId)) { - return null; - } - - try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT stat, value FROM makerreagentdata WHERE itemid = ?")) { - ps.setInt(1, itemId); - - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - String statType = rs.getString("stat"); - int statGain = rs.getInt("value"); - - statUpgd = new Pair<>(statType, statGain); - } - } - } - - statUpgradeMakerCache.put(itemId, statUpgd); - return statUpgd; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - public int getMakerCrystalFromLeftover(Integer leftoverId) { try { Integer itemid = mobCrystalMakerCache.get(leftoverId);