Conditional Buffs & M. Magnet & Loot Patch + Exp Split + Duey Rework

Fixed Monster Magnet skill when used on bosses disconnecting the caster.
Improved conditional buff system, no longer updating buffs that are not supposed to toggle.
Added party hunting in the conditional buffs system.
Refactored usage of DB by Duey. Registered Duey items now make use of the same table as the other inventory items.
Fixed non-encapsulated unlocking in reactor class.
Fixed stylish NPCs disconnecting players when trying to display empty styles list.
Fixed a deadlock case within recently implemented update buff effects (conditional buffs mechanic).
Fixed AOE mobskills not behaving well for fixed mobs (those shouldn't take into account attribute "facingLeft").
Fixed non-flipping mobs having attribute "facingLeft" updated according to controller position.
Revised aggro system no longer having bosses expire player chase.
Fixed chalkboard being depleted upon use.
Refactored MapleMapFactory, looking for normalization of the Factory design pattern the class was intended to make use at its conception.
Added MP replenishing system for mobs, gains based on its level.
Fixed indisponibility of one-of-a-kind loots due to the killer's team already having one sample each.
Reworked the EXP split system within the source. New behavior is expected to be GMS-like.
Adjusted interaction within the NPC Nein Spirit's Baby Dragon area. Only players who interacts with quests within can access the area now. One player at a time, with a timeout timer.
Fixed check of level requisites for expeditions.
This commit is contained in:
ronancpl
2019-06-15 15:10:56 -03:00
parent 04b11e2518
commit a39a210c1f
54 changed files with 1217 additions and 866 deletions

View File

@@ -84,13 +84,12 @@ import server.events.gm.MapleFitness;
import server.events.gm.MapleOla;
import server.life.MapleMonster;
import server.life.MobSkill;
import server.loot.MapleLootManager;
import server.maps.MapleHiredMerchant;
import server.maps.MapleDoor;
import server.maps.MapleDragon;
import server.maps.MapleMap;
import server.maps.MapleMapEffect;
import server.maps.MapleMapFactory;
import server.maps.MapleMapManager;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
import server.maps.MapleMiniGame;
@@ -3489,7 +3488,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
for(Entry<Integer, Map<MapleBuffStat, MapleBuffStatValueHolder>> bpl: buffEffects.entrySet()) {
MapleBuffStatValueHolder mbsvhi = bpl.getValue().get(mbs);
if(mbsvhi != null) {
if(!mbsvhi.effect.isActive(mapid)) {
if(!mbsvhi.effect.isActive(this)) {
continue;
}
@@ -3714,17 +3713,57 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
}
public void updateActiveEffects() {
chrLock.lock();
private static MapleStatEffect getEffectFromBuffSource(Map<MapleBuffStat, MapleBuffStatValueHolder> buffSource) {
try {
effects.clear();
updateEffects(buffEffectsCount.keySet());
return buffSource.entrySet().iterator().next().getValue().effect;
} catch (Exception e) {
return null;
}
}
private boolean isUpdatingEffect(Set<MapleStatEffect> activeEffects, MapleStatEffect mse) {
if (mse == null) return false;
// thanks xinyifly for noticing "Speed Infusion" crashing game when updating buffs during map transition
boolean active = mse.isActive(this);
if (active) {
return !activeEffects.contains(mse);
} else {
return activeEffects.contains(mse);
}
}
public void updateActiveEffects() {
effLock.lock(); // thanks davidlafriniere, maple006, RedHat for pointing a deadlock occurring here
try {
Set<MapleBuffStat> updatedBuffs = new LinkedHashSet<>();
Set<MapleStatEffect> activeEffects = new LinkedHashSet<>();
for (MapleBuffStatValueHolder mse : effects.values()) {
activeEffects.add(mse.effect);
}
for (Map<MapleBuffStat, MapleBuffStatValueHolder> buff : buffEffects.values()) {
MapleStatEffect mse = getEffectFromBuffSource(buff);
if (isUpdatingEffect(activeEffects, mse)) {
for (Pair<MapleBuffStat, Integer> p : mse.getStatups()) {
updatedBuffs.add(p.getLeft());
}
}
}
for (MapleBuffStat mbs : updatedBuffs) {
effects.remove(mbs);
}
updateEffects(updatedBuffs);
} finally {
chrLock.unlock();
effLock.unlock();
}
}
private void updateEffects(Set<MapleBuffStat> removedStats) {
effLock.lock();
chrLock.lock();
try {
Set<MapleBuffStat> retrievedStats = new LinkedHashSet<>();
@@ -3743,6 +3782,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
propagateBuffEffectUpdates(new LinkedHashMap<Integer, Pair<MapleStatEffect, Long>>(), retrievedStats, removedStats);
} finally {
chrLock.unlock();
effLock.unlock();
}
}
@@ -4169,6 +4209,12 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
case COUPON_DRP1:
case COUPON_DRP2:
case COUPON_DRP3:
case MESO_UP_BY_ITEM:
case ITEM_UP_BY_ITEM:
case RESPECT_PIMMUNE:
case RESPECT_MIMMUNE:
case DEFENSE_ATT:
case DEFENSE_STATE:
case WATK:
case WDEF:
case MATK:
@@ -4314,7 +4360,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
appliedStatups.put(ps.getLeft(), new MapleBuffStatValueHolder(effect, starttime, ps.getRight()));
}
boolean active = effect.isActive(mapid);
boolean active = effect.isActive(this);
if(ServerConstants.USE_BUFF_MOST_SIGNIFICANT) {
toDeploy = new LinkedHashMap<>();
Map<Integer, Pair<MapleStatEffect, Long>> retrievedEffects = new LinkedHashMap<>();
@@ -5289,20 +5335,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
return false;
}
public List<MonsterDropEntry> retrieveRelevantDrops(int monsterId) {
List<MapleCharacter> pchars = new LinkedList<>();
for (MapleCharacter chr : getPartyMembers()) {
if (chr.isLoggedinWorld()) {
pchars.add(chr);
}
}
if (pchars.isEmpty()) {
pchars.add(this);
}
return MapleLootManager.retrieveRelevantDrops(monsterId, pchars);
}
public MaplePlayerShop getPlayerShop() {
return playerShop;
}
@@ -6507,9 +6539,10 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
public void updateCouponRates() {
MapleInventory cashInv = this.getInventory(MapleInventoryType.CASH);
if (cashInv == null) return;
if (cpnLock.tryLock()) {
MapleInventory cashInv = this.getInventory(MapleInventoryType.CASH);
effLock.lock();
chrLock.lock();
cashInv.lockInventory();
@@ -6944,11 +6977,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
ret.commitExcludedItems();
if (channelserver) {
MapleMapFactory mapFactory = client.getChannelServer().getMapFactory();
ret.map = mapFactory.getMap(ret.mapid);
MapleMapManager mapManager = client.getChannelServer().getMapFactory();
ret.map = mapManager.getMap(ret.mapid);
if (ret.map == null) {
ret.map = mapFactory.getMap(100000000);
ret.map = mapManager.getMap(100000000);
}
MaplePortal portal = ret.map.getPortal(ret.initialSpawnPoint);
if (portal == null) {

View File

@@ -33,7 +33,7 @@ import net.server.Server;
import server.MaplePortal;
import server.maps.FieldLimit;
import server.maps.MapleMap;
import server.maps.MapleMapFactory;
import server.maps.MapleMapManager;
import server.maps.MapleMiniDungeonInfo;
import java.util.Comparator;
@@ -47,18 +47,18 @@ public class GotoCommand extends Command {
{
setDescription("");
MapleMapFactory mapFactory = Server.getInstance().getWorlds().get(0).getChannels().get(0).getMapFactory();
MapleMapManager mapManager = Server.getInstance().getWorlds().get(0).getChannels().get(0).getMapFactory();
List<Entry<String, Integer>> towns = new ArrayList<>(GameConstants.GOTO_TOWNS.entrySet());
sortGotoEntries(towns);
for (Map.Entry<String, Integer> e : towns) {
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (mapFactory.getMap(e.getValue()).getMapName()) + "#k\r\n");
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (mapManager.getMap(e.getValue()).getMapName()) + "#k\r\n");
}
List<Entry<String, Integer>> areas = new ArrayList<>(GameConstants.GOTO_AREAS.entrySet());
sortGotoEntries(areas);
for (Map.Entry<String, Integer> e : areas) {
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (mapFactory.getMap(e.getValue()).getMapName()) + "#k\r\n");
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (mapManager.getMap(e.getValue()).getMapName()) + "#k\r\n");
}
}
@@ -103,6 +103,7 @@ public class GotoCommand extends Command {
HashMap<String, Integer> gotomaps;
if (player.isGM()) {
gotomaps = new HashMap<>(GameConstants.GOTO_AREAS); // distinct map registry for GM/users suggested thanks to Vcoc
gotomaps.putAll(GameConstants.GOTO_TOWNS); // thanks Halcyon for pointing out duplicates on listed entries functionality
} else {
gotomaps = new HashMap<>(GameConstants.GOTO_TOWNS);
}

View File

@@ -46,13 +46,16 @@ public enum ItemFactory {
CASH_ARAN(5, true),
MERCHANT(6, false),
CASH_OVERALL(7, true),
MARRIAGE_GIFTS(8, false);
MARRIAGE_GIFTS(8, false),
DUEY(9, false);
private final int value;
private final boolean account;
private static final Lock locks[] = new Lock[200]; // thanks Masterrulax for pointing out a bottleneck issue here
private static final int lockCount = 400;
private static final Lock locks[] = new Lock[lockCount]; // thanks Masterrulax for pointing out a bottleneck issue here
static {
for (int i = 0; i < 200; i++) {
for (int i = 0; i < lockCount; i++) {
locks[i] = MonitoredReentrantLockFactory.createLock(MonitoredLockType.ITEM, true);
}
}
@@ -75,7 +78,9 @@ public enum ItemFactory {
saveItems(items, null, id, con);
}
public synchronized void saveItems(List<Pair<Item, MapleInventoryType>> items, List<Short> bundlesList, int id, Connection con) throws SQLException {
public void saveItems(List<Pair<Item, MapleInventoryType>> items, List<Short> bundlesList, int id, Connection con) throws SQLException {
// thanks Arufonsu, MedicOP, BHB for pointing a "synchronized" bottleneck here
if(value != 6) saveItemsCommon(items, id, con);
else saveItemsMerchant(items, bundlesList, id, con);
}
@@ -199,7 +204,7 @@ public enum ItemFactory {
PreparedStatement pse = null;
ResultSet rs = null;
Lock lock = locks[id % 200];
Lock lock = locks[id % lockCount];
lock.lock();
try {
StringBuilder query = new StringBuilder();
@@ -365,7 +370,7 @@ public enum ItemFactory {
PreparedStatement pse = null;
ResultSet rs = null;
Lock lock = locks[id % 200];
Lock lock = locks[id % lockCount];
lock.lock();
try {
ps = con.prepareStatement("DELETE FROM `inventorymerchant` WHERE `characterid` = ?");

View File

@@ -713,7 +713,7 @@ public class MapleInventoryManipulator {
source.setQuantity((short) (source.getQuantity() - quantity));
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(1, source))));
if(ItemConstants.isNewYearCardEtc(itemId)) {
if (ItemConstants.isNewYearCardEtc(itemId)) {
if(itemId == 4300000) {
NewYearCardRecord.removeAllNewYearCard(true, chr);
c.getAbstractPlayerInteraction().removeAll(4300000);
@@ -723,13 +723,9 @@ public class MapleInventoryManipulator {
}
} else if (ItemConstants.isWeddingRing(source.getItemId())) {
map.disappearingItemDrop(chr, chr, target, dropPos);
} else if (map.getEverlast()) {
if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
map.disappearingItemDrop(chr, chr, target, dropPos);
} else {
map.spawnItemDrop(chr, chr, target, dropPos, true, true);
}
} else if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
}
if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
map.disappearingItemDrop(chr, chr, target, dropPos);
} else {
map.spawnItemDrop(chr, chr, target, dropPos, true, true);
@@ -750,24 +746,20 @@ public class MapleInventoryManipulator {
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(3, source))));
if (src < 0) {
chr.equipChanged();
} else if(ItemConstants.isNewYearCardEtc(itemId)) {
if(itemId == 4300000) {
} else if (ItemConstants.isNewYearCardEtc(itemId)) {
if (itemId == 4300000) {
NewYearCardRecord.removeAllNewYearCard(true, chr);
c.getAbstractPlayerInteraction().removeAll(4300000);
} else {
NewYearCardRecord.removeAllNewYearCard(false, chr);
c.getAbstractPlayerInteraction().removeAll(4301000);
}
} else if (ItemConstants.isWeddingRing(source.getItemId())) {
map.disappearingItemDrop(chr, chr, source, dropPos);
}
if (map.getEverlast()) {
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
map.disappearingItemDrop(chr, chr, source, dropPos);
} else {
map.spawnItemDrop(chr, chr, source, dropPos, true, true);
}
} else if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
map.disappearingItemDrop(chr, chr, source, dropPos);
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
map.disappearingItemDrop(chr, chr, source, dropPos);
} else {
map.spawnItemDrop(chr, chr, source, dropPos, true, true);
}

View File

@@ -26,26 +26,31 @@ package client.processor;
import client.MapleCharacter;
import client.MapleClient;
import client.autoban.AutobanFactory;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleInventoryManipulator;
import client.inventory.manipulator.MapleKarmaManipulator;
import constants.ItemConstants;
import constants.ServerConstants;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import net.server.channel.Channel;
import server.DueyPackages;
import server.DueyPackage;
import server.MapleItemInformationProvider;
import server.MapleTrade;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
@@ -86,21 +91,17 @@ public class DueyProcessor {
}
}
private static int getAccIdFromCNAME(String name, boolean accountid) {
private static Pair<Integer, Integer> getAccountCharacterIdFromCNAME(String name) {
try {
PreparedStatement ps;
String text = "SELECT id,accountid FROM characters WHERE name = ?";
Connection con = DatabaseConnection.getConnection();
ps = con.prepareStatement(text);
PreparedStatement ps = con.prepareStatement("SELECT id,accountid FROM characters WHERE name = ?");
ps.setString(1, name);
int id_;
Pair<Integer, Integer> id_ = null;
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) {
rs.close();
ps.close();
return -1;
if (rs.next()) {
id_ = new Pair<>(rs.getInt("accountid"), rs.getInt("id"));
}
id_ = accountid ? rs.getInt("accountid") : rs.getInt("id");
}
ps.close();
con.close();
@@ -108,7 +109,7 @@ public class DueyProcessor {
} catch (SQLException e) {
e.printStackTrace();
}
return -1;
return null;
}
private static String getCurrentDate() {
@@ -123,67 +124,6 @@ public class DueyProcessor {
return date;
}
private static void removeItemFromDB(int packageid) {
Connection con = null;
try {
con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM dueypackages WHERE PackageId = ?");
ps.setInt(1, packageid);
ps.executeUpdate();
ps.close();
ps = con.prepareStatement("DELETE FROM dueyitems WHERE PackageId = ?");
ps.setInt(1, packageid);
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private static DueyPackages getItemByPID(ResultSet rs) {
try {
DueyPackages dueypack;
if (rs.getInt("type") == 1) {
Equip eq = new Equip(rs.getInt("itemid"), (byte) 0, -1);
eq.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
eq.setLevel((byte) rs.getInt("level"));
eq.setItemLevel((byte) rs.getInt("itemlevel"));
eq.setItemExp(rs.getInt("itemexp"));
eq.setStr((short) rs.getInt("str"));
eq.setDex((short) rs.getInt("dex"));
eq.setInt((short) rs.getInt("int"));
eq.setLuk((short) rs.getInt("luk"));
eq.setHp((short) rs.getInt("hp"));
eq.setMp((short) rs.getInt("mp"));
eq.setWatk((short) rs.getInt("watk"));
eq.setMatk((short) rs.getInt("matk"));
eq.setWdef((short) rs.getInt("wdef"));
eq.setMdef((short) rs.getInt("mdef"));
eq.setAcc((short) rs.getInt("acc"));
eq.setAvoid((short) rs.getInt("avoid"));
eq.setHands((short) rs.getInt("hands"));
eq.setSpeed((short) rs.getInt("speed"));
eq.setJump((short) rs.getInt("jump"));
eq.setFlag((byte) rs.getInt("flag"));
eq.setOwner(rs.getString("owner"));
dueypack = new DueyPackages(rs.getInt("PackageId"), eq);
} else if (rs.getInt("type") == 2) {
Item newItem = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
newItem.setFlag((byte) rs.getInt("flag"));
newItem.setOwner(rs.getString("owner"));
dueypack = new DueyPackages(rs.getInt("PackageId"), newItem);
} else {
dueypack = new DueyPackages(rs.getInt("PackageId"));
}
return dueypack;
} catch (SQLException se) {
se.printStackTrace();
return null;
}
}
private static void showDueyNotification(MapleClient c, MapleCharacter player) {
Connection con = null;
@@ -230,70 +170,21 @@ public class DueyProcessor {
}
}
}
private static void addMesoToDB(int mesos, String sName, int recipientID) {
addItemToDB(null, 1, mesos, sName, recipientID);
}
public static void addItemToDB(Item item, int quantity, int mesos, String sName, int recipientID) {
Connection con = null;
private static void deletePackageFromInventoryDB(Connection con, int packageId) throws SQLException {
ItemFactory.DUEY.saveItems(new LinkedList<Pair<Item, MapleInventoryType>>(), packageId, con);
}
private static void removePackageFromDB(int packageId) {
try {
con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("INSERT INTO dueypackages (ReceiverId, SenderName, Mesos, TimeStamp, Checked, Type) VALUES (?, ?, ?, ?, ?, ?)")) {
ps.setInt(1, recipientID);
ps.setString(2, sName);
ps.setInt(3, mesos);
ps.setString(4, getCurrentDate());
ps.setInt(5, 1);
if (item == null) {
ps.setInt(6, 3);
ps.executeUpdate();
} else {
ps.setInt(6, item.getItemType());
ps.executeUpdate();
try (ResultSet rs = ps.getGeneratedKeys()) {
rs.next();
PreparedStatement ps2;
if (item.getInventoryType().equals(MapleInventoryType.EQUIP)) {
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, upgradeslots, level, itemlevel, itemexp, str, dex, `int`, luk, hp, mp, watk, matk, wdef, mdef, acc, avoid, hands, speed, jump, flag, owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
Equip eq = (Equip) item;
ps2.setInt(2, eq.getItemId());
ps2.setInt(3, 1);
ps2.setInt(4, eq.getUpgradeSlots());
ps2.setInt(5, eq.getLevel());
ps2.setInt(6, eq.getItemLevel());
ps2.setInt(7, eq.getItemExp());
ps2.setInt(8, eq.getStr());
ps2.setInt(9, eq.getDex());
ps2.setInt(10, eq.getInt());
ps2.setInt(11, eq.getLuk());
ps2.setInt(12, eq.getHp());
ps2.setInt(13, eq.getMp());
ps2.setInt(14, eq.getWatk());
ps2.setInt(15, eq.getMatk());
ps2.setInt(16, eq.getWdef());
ps2.setInt(17, eq.getMdef());
ps2.setInt(18, eq.getAcc());
ps2.setInt(19, eq.getAvoid());
ps2.setInt(20, eq.getHands());
ps2.setInt(21, eq.getSpeed());
ps2.setInt(22, eq.getJump());
ps2.setInt(23, eq.getFlag());
ps2.setString(24, eq.getOwner());
} else {
ps2 = con.prepareStatement("INSERT INTO dueyitems (PackageId, itemid, quantity, flag, owner) VALUES (?, ?, ?, ?, ?)");
ps2.setInt(2, item.getItemId());
ps2.setInt(3, quantity);
ps2.setInt(4, item.getFlag());
ps2.setString(5, item.getOwner());
}
ps2.setInt(1, rs.getInt(1));
ps2.executeUpdate();
ps2.close();
}
}
}
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM dueypackages WHERE PackageId = ?");
ps.setInt(1, packageId);
ps.executeUpdate();
ps.close();
deletePackageFromInventoryDB(con, packageId);
con.close();
} catch (SQLException e) {
@@ -301,49 +192,181 @@ public class DueyProcessor {
}
}
private static List<DueyPackages> loadItems(MapleCharacter chr) {
List<DueyPackages> packages = new LinkedList<>();
Connection con = null;
private static DueyPackage getPackageFromDB(ResultSet rs) {
try {
con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp LEFT JOIN dueyitems di ON dp.PackageId=di.PackageId WHERE ReceiverId = ?")) {
int packageId = rs.getInt("PackageId");
List<Pair<Item, MapleInventoryType>> dueyItems = ItemFactory.DUEY.loadItems(packageId, false);
DueyPackage dueypack;
if (!dueyItems.isEmpty()) { // in a duey package there's only one item
dueypack = new DueyPackage(packageId, dueyItems.get(0).getLeft());
} else {
dueypack = new DueyPackage(packageId);
}
dueypack.setSender(rs.getString("SenderName"));
dueypack.setMesos(rs.getInt("Mesos"));
dueypack.setSentTime(rs.getString("TimeStamp"));
dueypack.setMessage(rs.getString("Message"));
return dueypack;
} catch (SQLException sqle) {
sqle.printStackTrace();
return null;
}
}
private static List<DueyPackage> loadPackages(MapleCharacter chr) {
List<DueyPackage> packages = new LinkedList<>();
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp WHERE ReceiverId = ?")) {
ps.setInt(1, chr.getId());
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
DueyPackages dueypack = getItemByPID(rs);
dueypack.setSender(rs.getString("SenderName"));
dueypack.setMesos(rs.getInt("Mesos"));
dueypack.setSentTime(rs.getString("TimeStamp"));
DueyPackage dueypack = getPackageFromDB(rs);
if (dueypack == null) continue;
packages.add(dueypack);
}
}
}
con.close();
return packages;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return packages;
}
private static int createPackage(int mesos, String message, String sender, int toCid) {
try {
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("INSERT INTO `dueypackages` (ReceiverId, SenderName, Mesos, TimeStamp, Message, Checked) VALUES (?, ?, ?, ?, ?, 1)", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, toCid);
ps.setString(2, sender);
ps.setInt(3, mesos);
ps.setString(4, getCurrentDate());
ps.setString(5, message);
int updateRows = ps.executeUpdate();
if (updateRows < 1) {
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Error trying to create package [mesos: " + mesos + ", " + sender + ", to CharacterId: " + toCid + "]");
return -1;
}
int packageId;
rs = ps.getGeneratedKeys();
if (rs.next()) {
packageId = rs.getInt(1);
} else {
FilePrinter.printError(FilePrinter.INSERT_CHAR, "Failed inserting package [mesos: " + mesos + ", " + sender + ", to CharacterId: " + toCid + "]");
return -1;
}
return packageId;
} finally {
if (rs != null && !rs.isClosed()) {
rs.close();
}
if (ps != null && !ps.isClosed()) {
ps.close();
}
if (con != null && !con.isClosed()) {
con.close();
}
}
} catch (SQLException sqle) {
sqle.printStackTrace();
}
return -1;
}
private static boolean insertPackageItem(int packageId, Item item) {
try {
Pair<Item, MapleInventoryType> dueyItem = new Pair<>(item, MapleInventoryType.getByType(item.getItemType()));
Connection con = DatabaseConnection.getConnection();
ItemFactory.DUEY.saveItems(Collections.singletonList(dueyItem), packageId, con);
con.close();
return true;
} catch (SQLException sqle) {
sqle.printStackTrace();
return false;
}
}
public static void dueySendItem(MapleClient c, byte inventId, short itemPos, short amount, int mesos, String recipient) {
private static int addPackageItemFromInventory(int packageId, MapleClient c, byte invTypeId, short itemPos, short amount) {
if (invTypeId > 0) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType invType = MapleInventoryType.getByType(invTypeId);
MapleInventory inv = c.getPlayer().getInventory(invType);
Item item;
inv.lockInventory();
try {
item = inv.getItem(itemPos);
if (item != null && item.getQuantity() >= amount) {
if (item.isUntradeable() || ii.isUnmerchable(item.getItemId())) {
return -1;
}
if (ItemConstants.isRechargeable(item.getItemId())) {
MapleInventoryManipulator.removeFromSlot(c, invType, itemPos, item.getQuantity(), true);
} else {
MapleInventoryManipulator.removeFromSlot(c, invType, itemPos, amount, true, false);
}
item = item.copy();
} else {
return -2;
}
} finally {
inv.unlockInventory();
}
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
item.setQuantity(amount);
if (!insertPackageItem(packageId, item)) {
return 1;
}
}
return 0;
}
public static void dueySendItem(MapleClient c, byte invTypeId, short itemPos, short amount, int sendMesos, String sendMessage, String recipient) {
if (c.tryacquireClient()) {
try {
final int fee = 5000;
final long sendMesos = (long) mesos + fee;
if (mesos < 0 || sendMesos > Integer.MAX_VALUE || (amount < 1 && mesos == 0)) {
final int fee = 5000 + MapleTrade.getFee(sendMesos);
long finalcost = (long) sendMesos + fee;
if (finalcost < 0 || finalcost > Integer.MAX_VALUE || (amount < 1 && sendMesos == 0)) {
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + mesos + " and amount " + amount);
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + sendMesos + " and amount " + amount);
c.disconnect(true, false);
return;
}
int finalcost = mesos + fee;
Pair<Integer, Integer> accIdCid;
if (c.getPlayer().getMeso() >= finalcost) {
int accid = getAccIdFromCNAME(recipient, true);
if (accid != -1) {
if (accid == c.getAccID()) {
accIdCid = getAccountCharacterIdFromCNAME(recipient);
int recipientAccId = accIdCid.getLeft();
if (recipientAccId != -1) {
if (recipientAccId == c.getAccID()) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
return;
}
@@ -355,7 +378,29 @@ public class DueyProcessor {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NOT_ENOUGH_MESOS.getCode()));
return;
}
int recipientCid = accIdCid.getRight();
if (recipientCid == -1) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NAME_DOES_NOT_EXIST.getCode()));
return;
}
int packageId = createPackage(sendMesos, sendMessage, c.getPlayer().getName(), recipientCid);
if (packageId == -1) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_ENABLE_ACTIONS.getCode()));
return;
}
c.getPlayer().gainMeso((int) -finalcost, false);
int res = addPackageItemFromInventory(packageId, c, invTypeId, itemPos, amount);
if (res == 0) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
} else if (res > 0) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_ENABLE_ACTIONS.getCode()));
} else {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
}
MapleClient rClient = null;
int channel = c.getWorldServer().find(recipient);
if (channel > -1) {
@@ -367,40 +412,7 @@ public class DueyProcessor {
}
}
}
if (inventId > 0) {
MapleInventoryType inv = MapleInventoryType.getByType(inventId);
Item item = c.getPlayer().getInventory(inv).getItem(itemPos);
if (item != null && c.getPlayer().getItemQuantity(item.getItemId(), false) >= amount) {
if (item.isUntradeable()) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
return;
}
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
if (ItemConstants.isRechargeable(item.getItemId())) {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, item.getQuantity(), true);
} else {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, amount, true, false);
}
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
addItemToDB(item, amount, mesos - MapleTrade.getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
} else {
if (item != null) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
}
return;
}
} else {
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
addMesoToDB(mesos - MapleTrade.getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
}
if (rClient != null && rClient.isLoggedIn() && !rClient.getPlayer().isAwayFromWorld()) {
showDueyNotification(rClient, rClient.getPlayer());
}
@@ -410,55 +422,50 @@ public class DueyProcessor {
}
}
public static void dueyRemovePackage(MapleClient c, int packageid) {
public static void dueyRemovePackage(MapleClient c, int packageid, boolean playerRemove) {
if (c.tryacquireClient()) {
try {
removeItemFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(true, packageid));
removePackageFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(playerRemove, packageid));
} finally {
c.releaseClient();
}
}
}
public static void dueyClaimPackage(MapleClient c, int packageid) {
public static void dueyClaimPackage(MapleClient c, int packageId) {
if (c.tryacquireClient()) {
try {
List<DueyPackages> packages = new LinkedList<>();
DueyPackages dp = null;
Connection con = null;
try {
con = DatabaseConnection.getConnection();
DueyPackages dueypack;
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages LEFT JOIN dueyitems USING (PackageId) WHERE PackageId = ?")) {
ps.setInt(1, packageid);
DueyPackage dp = null;
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages dp WHERE PackageId = ?")) {
ps.setInt(1, packageId);
try (ResultSet rs = ps.executeQuery()) {
dueypack = null;
if (rs.next()) {
dueypack = getItemByPID(rs);
dueypack.setSender(rs.getString("SenderName"));
dueypack.setMesos(rs.getInt("Mesos"));
dueypack.setSentTime(rs.getString("TimeStamp"));
packages.add(dueypack);
dp = getPackageFromDB(rs);
}
}
}
dp = dueypack;
con.close();
if(dp == null) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to receive package from duey with id " + packageid);
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to receive package from duey with id " + packageId);
return;
}
if (dp.getItem() != null) {
Item dpItem = dp.getItem();
if (dpItem != null) {
if (!c.getPlayer().canHoldMeso(dp.getMesos())) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
return;
}
if (!MapleInventoryManipulator.checkSpace(c, dp.getItem().getItemId(), dp.getItem().getQuantity(), dp.getItem().getOwner())) {
int itemid = dp.getItem().getItemId();
if (!MapleInventoryManipulator.checkSpace(c, dpItem.getItemId(), dpItem.getQuantity(), dpItem.getOwner())) {
int itemid = dpItem.getItemId();
if(MapleItemInformationProvider.getInstance().isPickupRestricted(itemid) && c.getPlayer().getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) != null) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_RECEIVER_WITH_UNIQUE.getCode()));
} else {
@@ -467,16 +474,13 @@ public class DueyProcessor {
return;
} else {
MapleInventoryManipulator.addFromDrop(c, dp.getItem(), false);
MapleInventoryManipulator.addFromDrop(c, dpItem, false);
}
}
c.getPlayer().gainMeso(dp.getMesos(), false);
removeItemFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(false, packageid));
con.close();
dueyRemovePackage(c, packageId, false);
} catch (SQLException e) {
e.printStackTrace();
}
@@ -489,10 +493,17 @@ public class DueyProcessor {
public static void dueySendTalk(MapleClient c) {
if (c.tryacquireClient()) {
try {
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadItems(c.getPlayer())));
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadPackages(c.getPlayer())));
} finally {
c.releaseClient();
}
}
}
public static void dueyCreatePackage(Item item, int mesos, String sender, int recipientCid) {
int packageId = createPackage(mesos, "", sender, recipientCid);
if (packageId != -1) {
insertPackageItem(packageId, item);
}
}
}

View File

@@ -147,7 +147,6 @@ public class StorageProcessor {
chr.gainMeso(-storeFee, false, true, false);
item = item.copy(); // thanks Robin Schulz for pointing out an issue with stored items
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
item.setQuantity(quantity);
storage.store(item);