// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.db.handlers; import engine.gameManager.DbManager; import engine.mbEnums; import engine.mbEnums.ItemContainerType; import engine.mbEnums.ItemType; import engine.objects.AbstractCharacter; import engine.objects.CharacterItemManager; import engine.objects.Item; import engine.objects.ItemTemplate; import org.json.JSONObject; import org.pmw.tinylog.Logger; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; public class dbItemHandler extends dbHandlerBase { public dbItemHandler() { this.localClass = Item.class; this.localObjectType = mbEnums.GameObjectType.valueOf(this.localClass.getSimpleName()); } private static String formatTradeString(HashSet list) { int size = list.size(); String ret = ""; if (size == 0) return ret; boolean start = true; for (int i : list) { if (start) { ret += i; start = false; } else ret += "," + i; } return ret; } public Item PERSIST(Item toAdd) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("CALL `item_CREATE`(?, ?, ?, ?, ?, ?, ?, ?,?);")) { preparedStatement.setInt(1, toAdd.ownerID); preparedStatement.setInt(2, toAdd.templateID); preparedStatement.setInt(3, (byte) toAdd.chargesRemaining); preparedStatement.setInt(4, (short) toAdd.combat_health_current); if (toAdd.getNumOfItems() < 1) preparedStatement.setInt(5, 1); else preparedStatement.setInt(5, toAdd.getNumOfItems()); switch (toAdd.containerType) { case INVENTORY: preparedStatement.setString(6, "inventory"); break; case EQUIPPED: preparedStatement.setString(6, "equip"); break; case BANK: preparedStatement.setString(6, "bank"); break; case VAULT: preparedStatement.setString(6, "vault"); break; case FORGE: preparedStatement.setString(6, "forge"); break; default: preparedStatement.setString(6, "none"); //Shouldn't be here break; } if (toAdd.equipSlot.equals(mbEnums.EquipSlotType.NONE)) preparedStatement.setString(7, ""); else preparedStatement.setString(7, toAdd.equipSlot.name()); String flagString = ""; for (mbEnums.ItemFlags itemflag : toAdd.flags) flagString += itemflag.toString() + ";"; flagString = flagString.replaceAll(";$", ""); preparedStatement.setString(8, flagString); preparedStatement.setString(9, toAdd.name); ResultSet rs = preparedStatement.executeQuery(); if (rs.next()) { int objectUUID = (int) rs.getLong("UID"); if (objectUUID > 0) return GET_ITEM(objectUUID); } } catch (SQLException e) { Logger.error(e); } return null; } public boolean DO_TRADE(HashSet from1, HashSet from2, CharacterItemManager man1, CharacterItemManager man2, Item inventoryGold1, Item inventoryGold2, int goldFrom1, int goldFrom2) { AbstractCharacter ac1 = man1.getOwner(); AbstractCharacter ac2 = man2.getOwner(); boolean worked = false; if (ac1 == null || ac2 == null || inventoryGold1 == null || inventoryGold2 == null) return false; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("CALL `item_TRADE`(?, ?, ?, ?, ?, ?, ?, ?)")) { preparedStatement.setString(1, formatTradeString(from1)); preparedStatement.setLong(2, ac1.getObjectUUID()); preparedStatement.setString(3, formatTradeString(from2)); preparedStatement.setLong(4, ac2.getObjectUUID()); preparedStatement.setInt(5, goldFrom1); preparedStatement.setLong(6, inventoryGold1.getObjectUUID()); preparedStatement.setInt(7, goldFrom2); preparedStatement.setLong(8, inventoryGold2.getObjectUUID()); ResultSet rs = preparedStatement.executeQuery(); if (rs.next()) worked = rs.getBoolean("result"); } catch (SQLException e) { Logger.error(e); } return worked; } public ArrayList GET_EQUIPPED_ITEMS(final int targetId) { ArrayList itemList; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_item`.*, `object`.`parent`, `object`.`type` FROM `object` INNER JOIN `obj_item` ON `object`.`UID` = `obj_item`.`UID` WHERE `object`.`parent`=? && `obj_item`.`container`='equip';")) { preparedStatement.setLong(1, targetId); ResultSet rs = preparedStatement.executeQuery(); itemList = getObjectsFromRs(rs, 10); } catch (SQLException e) { Logger.error(e); return null; } return itemList; } public void LOAD_ITEM_TEMPLATES() { HashMap templateTCountMap = new HashMap<>(); try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_item_templates`;"); ResultSet rs = preparedStatement.executeQuery()) { while (rs.next()) { int templateID = rs.getInt("id"); JSONObject jsonObject = new JSONObject(rs.getString("template")); ItemTemplate itemTemplate = new ItemTemplate(jsonObject); itemTemplate.template_id = templateID; ItemTemplate.templates.put(templateID, itemTemplate); templateTCountMap.merge(itemTemplate.item_type, 1, Integer::sum); } Logger.info(templateTCountMap.toString()); } catch (Exception e) { Logger.error(e); } } public void LOAD_TEMPLATE_MODTABLES() { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_vendor_items`;"); ResultSet rs = preparedStatement.executeQuery()) { while (rs.next()) { int templateID = rs.getInt("templateID"); int modTable = rs.getInt("modTable"); ItemTemplate template = ItemTemplate.templates.get(templateID); template.modTable = modTable; } } catch (Exception e) { Logger.error(e); } } public Item GET_ITEM(final int itemUUID) { Item item; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_item`.*, `object`.`parent`, `object`.`type` FROM `object` INNER JOIN `obj_item` ON `object`.`UID` = `obj_item`.`UID` WHERE `object`.`UID`=?;")) { preparedStatement.setLong(1, itemUUID); ResultSet rs = preparedStatement.executeQuery(); item = (Item) getObjectFromRs(rs); } catch (SQLException e) { Logger.error(e); return null; } return item; } public ArrayList GET_ITEMS_FOR_ACCOUNT(final int accountId) { ArrayList itemList; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_item`.*, `object`.`parent`, `object`.`type` FROM `object` INNER JOIN `obj_item` ON `object`.`UID` = `obj_item`.`UID` WHERE `object`.`parent`=?;")) { preparedStatement.setLong(1, accountId); ResultSet rs = preparedStatement.executeQuery(); itemList = getObjectsFromRs(rs, 100); } catch (SQLException e) { Logger.error(e); return null; } return itemList; } public ArrayList GET_ITEMS_FOR_NPC(final int npcId) { ArrayList itemList; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_item`.*, `object`.`parent`, `object`.`type` FROM `object` INNER JOIN `obj_item` ON `object`.`UID` = `obj_item`.`UID` WHERE `object`.`parent`=?;")) { preparedStatement.setLong(1, npcId); ResultSet rs = preparedStatement.executeQuery(); itemList = getObjectsFromRs(rs, 20); } catch (SQLException e) { Logger.error(e); return null; } return itemList; } public ArrayList GET_ITEMS_FOR_PC(final int id) { ArrayList itemList; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_item`.*, `object`.`parent`, `object`.`type` FROM `object` INNER JOIN `obj_item` ON `object`.`UID` = `obj_item`.`UID` WHERE `object`.`parent`=?")) { preparedStatement.setLong(1, id); ResultSet rs = preparedStatement.executeQuery(); itemList = getObjectsFromRs(rs, 100); } catch (SQLException e) { Logger.error(e); return null; } return itemList; } public boolean MOVE_GOLD(final Item from, final Item to, final int amt) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `numberOfItems` = CASE WHEN `UID`=? THEN ? WHEN `UID`=? THEN ? END WHERE `UID` IN (?, ?);")) { int newFromAmt = from.getNumOfItems() - amt; int newToAmt = to.getNumOfItems() + amt; preparedStatement.setLong(1, from.getObjectUUID()); preparedStatement.setInt(2, newFromAmt); preparedStatement.setLong(3, to.getObjectUUID()); preparedStatement.setInt(4, newToAmt); preparedStatement.setLong(5, from.getObjectUUID()); preparedStatement.setLong(6, to.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); } return false; } public boolean ORPHAN_INVENTORY(final HashSet inventory) { boolean worked = true; for (Item item : inventory) { if (item.template.item_type.equals(ItemType.GOLD)) continue; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` LEFT JOIN `object` ON `object`.`UID` = `obj_item`.`UID` SET `object`.`parent`=NULL, `obj_item`.`container`='none' WHERE `object`.`UID`=?;")) { preparedStatement.setLong(1, item.getObjectUUID()); worked = (preparedStatement.executeUpdate() > 0); if (worked) item.zeroItem(); } catch (SQLException e) { Logger.error(e); return false; } } return worked; } public HashSet GET_VENDOR_CAN_ROLL_LIST(final int vendorID) { HashSet itemSet = new HashSet<>(); try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("SELECT templateID FROM static_vendor_items WHERE vendorType = ?")) { preparedStatement.setInt(1, vendorID); ResultSet rs = preparedStatement.executeQuery(); while (rs.next()) itemSet.add(rs.getInt(1)); } catch (SQLException e) { Logger.error(e); return itemSet; } return itemSet; } //Used to transfer a single item between owners or equip or vault or bank or inventory public boolean UPDATE_OWNER(final Item item, int newOwnerID, ItemContainerType containerType, mbEnums.EquipSlotType slot) { boolean worked = false; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("CALL `item_TRANSFER_OWNER`(?, ?, ?, ? )")) { preparedStatement.setLong(1, item.getObjectUUID()); if (newOwnerID != 0) preparedStatement.setLong(2, newOwnerID); else preparedStatement.setNull(2, java.sql.Types.BIGINT); switch (containerType) { case INVENTORY: preparedStatement.setString(3, "inventory"); break; case EQUIPPED: preparedStatement.setString(3, "equip"); break; case BANK: preparedStatement.setString(3, "bank"); break; case VAULT: preparedStatement.setString(3, "vault"); break; case FORGE: preparedStatement.setString(3, "forge"); break; default: preparedStatement.setString(3, "none"); //Shouldn't be here break; } if (slot.equals(mbEnums.EquipSlotType.NONE)) preparedStatement.setString(4, ""); else preparedStatement.setString(4, slot.name()); ResultSet rs = preparedStatement.executeQuery(); if (rs.next()) worked = rs.getBoolean("result"); } catch (SQLException e) { Logger.error(e); return false; } return worked; } public boolean SET_DURABILITY(final Item item, int value) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `combat_health_current`=? WHERE `UID`=? AND `combat_health_current`=?")) { preparedStatement.setInt(1, value); preparedStatement.setLong(2, item.getObjectUUID()); preparedStatement.setInt(3, (short) item.combat_health_current); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } public boolean UPDATE_FORGE_TO_INVENTORY(final Item item) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `container` = ? WHERE `UID` = ? AND `container` = 'forge';")) { preparedStatement.setString(1, "inventory"); preparedStatement.setLong(2, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } /** * Attempts to update the quantity of this gold item * * @param value New quantity of gold * @return True on success */ public boolean UPDATE_GOLD(final Item item, int value) { if (item == null) return false; return UPDATE_GOLD(item, value, item.getNumOfItems()); } /** * Attempts to update the quantity of this gold item using CAS * * @return True on success */ public boolean UPDATE_GOLD(final Item item, int newValue, int oldValue) { if (!item.template.item_type.equals(ItemType.GOLD)) return false; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `numberOfItems`=? WHERE `UID`=?")) { preparedStatement.setInt(1, newValue); preparedStatement.setLong(2, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } public boolean UPDATE_REMAINING_CHARGES(final Item item) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `chargesRemaining` = ? WHERE `UID` = ?")) { preparedStatement.setInt(1, (byte) item.chargesRemaining); preparedStatement.setLong(2, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } // This is necessary because default number of items is 1. // When we create gold, we want it to start at 0 quantity. public boolean ZERO_ITEM_STACK(Item item) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `numberOfItems`=0 WHERE `UID` = ?")) { preparedStatement.setLong(1, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } public boolean UPDATE_FLAGS(Item item) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `flags`=? WHERE `UID` = ?")) { String flagString = ""; for (mbEnums.ItemFlags itemflag : item.flags) flagString += itemflag.toString() + ";"; flagString = flagString.replaceAll(";$", ""); preparedStatement.setString(1, flagString); preparedStatement.setLong(2, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } public boolean UPDATE_VALUE(Item item, int value) { // Write 0 if we will not modify the value from template if (item.value == item.template.item_value) value = 0; try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `value`=? WHERE `UID` = ?")) { preparedStatement.setInt(1, value); preparedStatement.setLong(2, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } public boolean UPDATE_EQUIP_SLOT(Item item) { try (Connection connection = DbManager.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `obj_item` SET `equipSlot`=? WHERE `UID` = ?")) { if (item.equipSlot.equals(mbEnums.EquipSlotType.NONE)) preparedStatement.setString(1, ""); else preparedStatement.setString(1, item.equipSlot.name()); preparedStatement.setLong(2, item.getObjectUUID()); return (preparedStatement.executeUpdate() > 0); } catch (SQLException e) { Logger.error(e); return false; } } }