From d2d4b442d237cba59a783c4a7b30a34281b42606 Mon Sep 17 00:00:00 2001 From: P0nk Date: Sat, 4 Mar 2023 22:33:34 +0100 Subject: [PATCH] Maker disassembly info to MakerInfoProvider MakerProcessor is such a mess... --- .../processor/action/MakerProcessor.java | 22 +++-------- src/main/java/constants/id/ItemId.java | 4 ++ src/main/java/database/JdbiConfig.java | 4 +- src/main/java/database/maker/MakerDao.java | 15 +++++++ .../database/maker/MakerDisassemblyInfo.java | 6 +++ .../database/maker/MakerInfoProvider.java | 30 ++++++++++++++ .../java/database/maker/MakerIngredient.java | 4 ++ .../maker/MakerIngredientRowMapper.java | 17 ++++++++ .../java/server/ItemInformationProvider.java | 39 ------------------- src/main/java/server/MakerItemFactory.java | 9 ++--- 10 files changed, 89 insertions(+), 61 deletions(-) create mode 100644 src/main/java/database/maker/MakerDisassemblyInfo.java create mode 100644 src/main/java/database/maker/MakerIngredient.java create mode 100644 src/main/java/database/maker/MakerIngredientRowMapper.java diff --git a/src/main/java/client/processor/action/MakerProcessor.java b/src/main/java/client/processor/action/MakerProcessor.java index e6b6e46624..f749db754e 100644 --- a/src/main/java/client/processor/action/MakerProcessor.java +++ b/src/main/java/client/processor/action/MakerProcessor.java @@ -29,6 +29,7 @@ import config.YamlConfig; import constants.game.GameConstants; import constants.id.ItemId; import constants.inventory.ItemConstants; +import database.maker.MakerDisassemblyInfo; import database.maker.MakerInfoProvider; import database.maker.MakerReagent; import net.packet.InPacket; @@ -85,14 +86,14 @@ public class MakerProcessor { if (it != null && it.getItemId() == toCreate) { toDisassemble = toCreate; - Pair>> pair = generateDisassemblyInfo(toDisassemble); - if (pair != null) { - recipe = MakerItemFactory.generateDisassemblyCrystalEntry(toDisassemble, pair.getLeft(), pair.getRight()); - } else { + Optional disassemblyInfo = infoProvider.getDisassemblyInfo(toDisassemble); + if (disassemblyInfo.isEmpty()) { c.sendPacket(PacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly.")); c.sendPacket(PacketCreator.makerEnableActions()); return; } + + recipe = MakerItemFactory.generateDisassemblyCrystalEntry(toDisassemble, disassemblyInfo.get()); } else { c.sendPacket(PacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly.")); c.sendPacket(PacketCreator.makerEnableActions()); @@ -193,6 +194,7 @@ public class MakerProcessor { default: if (toDisassemble != -1) { InventoryManipulator.removeFromSlot(c, InventoryType.EQUIP, (short) pos, (short) 1, false); + // TODO: fix disassembly being free. The fee is never applied. } else { for (Pair pair : recipe.getReqItems()) { c.getAbstractPlayerInteraction().gainItem(pair.getLeft(), (short) -pair.getRight(), false); @@ -308,18 +310,6 @@ public class MakerProcessor { } } - private Pair>> generateDisassemblyInfo(int itemId) { - int recvFee = ii.getMakerDisassembledFee(itemId); - if (recvFee > -1) { - List> gains = ii.getMakerDisassembledItems(itemId); - if (!gains.isEmpty()) { - return new Pair<>(recvFee, gains); - } - } - - return null; - } - private int getMakerSkillLevel(Character chr) { return chr.getSkillLevel((chr.getJob().getId() / 1000) * 10000000 + 1007); } diff --git a/src/main/java/constants/id/ItemId.java b/src/main/java/constants/id/ItemId.java index 95ad8f2ec7..9c9541e61d 100644 --- a/src/main/java/constants/id/ItemId.java +++ b/src/main/java/constants/id/ItemId.java @@ -257,6 +257,10 @@ public class ItemId { public static final int ADVANCED_MONSTER_CRYSTAL_2 = 4260007; public static final int ADVANCED_MONSTER_CRYSTAL_3 = 4260008; + public static boolean isMonsterCrystal(int itemId) { + return itemId / 10000 == 426; + } + // NPC weather (PQ) public static final int NPC_WEATHER_GROWLIE = 5120016; // Henesys PQ diff --git a/src/main/java/database/JdbiConfig.java b/src/main/java/database/JdbiConfig.java index 02dc9f9088..19d5b0c772 100644 --- a/src/main/java/database/JdbiConfig.java +++ b/src/main/java/database/JdbiConfig.java @@ -1,5 +1,6 @@ package database; +import database.maker.MakerIngredientRowMapper; import database.maker.MakerReagentRowMapper; import database.maker.MakerRecipeRowMapper; import database.note.NoteRowMapper; @@ -14,6 +15,7 @@ public final class JdbiConfig { return Jdbi.create(dataSource) .registerRowMapper(new NoteRowMapper()) .registerRowMapper(new MakerReagentRowMapper()) - .registerRowMapper(new MakerRecipeRowMapper()); + .registerRowMapper(new MakerRecipeRowMapper()) + .registerRowMapper(new MakerIngredientRowMapper()); } } diff --git a/src/main/java/database/maker/MakerDao.java b/src/main/java/database/maker/MakerDao.java index 6b87109ae6..25e7dd6ab9 100644 --- a/src/main/java/database/maker/MakerDao.java +++ b/src/main/java/database/maker/MakerDao.java @@ -5,6 +5,7 @@ import database.PgDatabaseConnection; import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.JdbiException; +import java.util.List; import java.util.Optional; public class MakerDao { @@ -41,4 +42,18 @@ public class MakerDao { throw new DaoException("Failed to get maker recipe with item id: %d".formatted(itemId), e); } } + + public List getIngredients(int recipeItemId) { + try (Handle handle = connection.getHandle()) { + return handle.createQuery(""" + SELECT * + FROM maker_ingredient + WHERE maker_recipe = ?;""") + .bind(0, recipeItemId) + .mapTo(MakerIngredient.class) + .list(); + } catch (JdbiException e) { + throw new DaoException("Failed to get maker ingredients for recipe item id %d".formatted(recipeItemId), e); + } + } } diff --git a/src/main/java/database/maker/MakerDisassemblyInfo.java b/src/main/java/database/maker/MakerDisassemblyInfo.java new file mode 100644 index 0000000000..2be02f10fe --- /dev/null +++ b/src/main/java/database/maker/MakerDisassemblyInfo.java @@ -0,0 +1,6 @@ +package database.maker; + +import java.util.Collection; + +public record MakerDisassemblyInfo(int fee, Collection gainedItems) { +} diff --git a/src/main/java/database/maker/MakerInfoProvider.java b/src/main/java/database/maker/MakerInfoProvider.java index 5c1bffa836..0ed3d7f2f8 100644 --- a/src/main/java/database/maker/MakerInfoProvider.java +++ b/src/main/java/database/maker/MakerInfoProvider.java @@ -2,8 +2,10 @@ package database.maker; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; +import constants.id.ItemId; import net.jcip.annotations.ThreadSafe; +import java.util.List; import java.util.Optional; @ThreadSafe @@ -11,6 +13,7 @@ public class MakerInfoProvider { private final MakerDao makerDao; private final Cache> reagentCache = Caffeine.newBuilder().build(); private final Cache> recipeCache = Caffeine.newBuilder().build(); + private final Cache> ingredientsCache = Caffeine.newBuilder().build(); public MakerInfoProvider(MakerDao makerDao) { if (makerDao == null) { @@ -30,4 +33,31 @@ public class MakerInfoProvider { public Optional getStimulant(int itemId) { return getMakerRecipe(itemId).map(MakerRecipe::catalyst); } + + public List getIngredients(int recipeItemId) { + return ingredientsCache.get(recipeItemId, makerDao::getIngredients); + } + + public Optional getDisassemblyInfo(int itemId) { + Optional recipe = getMakerRecipe(itemId); + if (recipe.isEmpty()) { + return Optional.empty(); + } + int fee = calculateDisassemblyFee(recipe.get().mesoCost()); + + List gainedItems = getIngredients(itemId).stream() + .filter(i -> ItemId.isMonsterCrystal(i.itemId())) + .map(i -> new MakerIngredient(i.itemId(), (short) (i.count() / 2))) + .toList(); + + return Optional.of(new MakerDisassemblyInfo(fee, gainedItems)); + } + + private int calculateDisassemblyFee(int creationCost) { + // cost is 13.6363~ % of the original value, trim by 1000. + float val = (float) (creationCost * 0.13636363636364); + int fee = (int) (val / 1000); + fee *= 1000; + return fee; + } } diff --git a/src/main/java/database/maker/MakerIngredient.java b/src/main/java/database/maker/MakerIngredient.java new file mode 100644 index 0000000000..44db47d8d1 --- /dev/null +++ b/src/main/java/database/maker/MakerIngredient.java @@ -0,0 +1,4 @@ +package database.maker; + +public record MakerIngredient(int itemId, short count) { +} diff --git a/src/main/java/database/maker/MakerIngredientRowMapper.java b/src/main/java/database/maker/MakerIngredientRowMapper.java new file mode 100644 index 0000000000..a72ba1cd65 --- /dev/null +++ b/src/main/java/database/maker/MakerIngredientRowMapper.java @@ -0,0 +1,17 @@ +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 MakerIngredientRowMapper implements RowMapper { + + @Override + public MakerIngredient map(ResultSet rs, StatementContext ctx) throws SQLException { + int itemId = rs.getInt("item_id"); + short count = rs.getShort("count"); + return new MakerIngredient(itemId, count); + } +} diff --git a/src/main/java/server/ItemInformationProvider.java b/src/main/java/server/ItemInformationProvider.java index cfba281f5a..e8762e0548 100644 --- a/src/main/java/server/ItemInformationProvider.java +++ b/src/main/java/server/ItemInformationProvider.java @@ -2082,45 +2082,6 @@ public class ItemInformationProvider { return -1; } - public List> getMakerDisassembledItems(Integer itemId) { - List> items = new LinkedList<>(); - - try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT req_item, count FROM makerrecipedata WHERE itemid = ? AND req_item >= 4260000 AND req_item < 4270000")) { - ps.setInt(1, itemId); - - try (ResultSet rs = ps.executeQuery()) { - while (rs.next()) { - items.add(new Pair<>(rs.getInt("req_item"), rs.getInt("count") / 2)); // return to the player half of the crystals needed - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return items; - } - - public int getMakerDisassembledFee(Integer itemId) { - int fee = -1; - try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT req_meso FROM makercreatedata WHERE itemid = ?")) { - ps.setInt(1, itemId); - - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { // cost is 13.6363~ % of the original value, trim by 1000. - float val = (float) (rs.getInt("req_meso") * 0.13636363636364); - fee = (int) (val / 1000); - fee *= 1000; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return fee; - } - public Set getWhoDrops(Integer itemId) { Set list = new HashSet<>(); try (Connection con = DatabaseConnection.getConnection(); diff --git a/src/main/java/server/MakerItemFactory.java b/src/main/java/server/MakerItemFactory.java index b37430f2b3..dad6ab8086 100644 --- a/src/main/java/server/MakerItemFactory.java +++ b/src/main/java/server/MakerItemFactory.java @@ -23,6 +23,7 @@ package server; import config.YamlConfig; import constants.inventory.EquipType; +import database.maker.MakerDisassemblyInfo; import tools.Pair; import java.util.ArrayList; @@ -64,12 +65,10 @@ public class MakerItemFactory { return ret; } - public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int fromEquipid, int cost, List> gains) { // equipment at specific position already taken - MakerItemCreateEntry ret = new MakerItemCreateEntry(cost, 0, 1); + public static MakerItemCreateEntry generateDisassemblyCrystalEntry(int fromEquipid, MakerDisassemblyInfo disassemblyInfo) { // equipment at specific position already taken + MakerItemCreateEntry ret = new MakerItemCreateEntry(disassemblyInfo.fee(), 0, 1); ret.addReqItem(fromEquipid, 1); - for (Pair p : gains) { - ret.addGainItem(p.getLeft(), p.getRight()); - } + disassemblyInfo.gainedItems().forEach(i -> ret.addGainItem(i.itemId(), i.count())); return ret; }