diff --git a/mychanges_ptbr.txt b/mychanges_ptbr.txt index 4d411b2540..6a7722e40c 100644 --- a/mychanges_ptbr.txt +++ b/mychanges_ptbr.txt @@ -250,4 +250,10 @@ Solu 25 Maio 2017, Solução final ao problema das Guild Alliances. Todas as funcionalidades implementadas. -Registros de objetos MapleGuildCharacter agora esta sincronizado entre MapleCharacter's e MapleGuild's. \ No newline at end of file +Registros de objetos MapleGuildCharacter agora esta sincronizado entre MapleCharacter's e MapleGuild's. + +26 Maio 2017, +Correção e proteção a acessos concorrentes em mecânicas de comercialização entre jogadores. +Quests com limite de tempo agora expiram. Tempo restante também é mostrado na aba da quest. +Estrutura de dados que lida com status de quests do jogador agora foi protegido para acesso concorrente. +Montarias, tanto como pets, não ficam com "fome" com o tempo caso os flags PETS_NEVER_HUNGRY estejam setados. \ No newline at end of file diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml index 6d8d3ad834..83e676f731 100644 --- a/nbproject/private/private.xml +++ b/nbproject/private/private.xml @@ -5,12 +5,38 @@ src/tools/MaplePacketCreator.java - 5939 + 5941 - + + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/command/Commands.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleStatEffect.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/provider/MapleDataTool.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerInteractionHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/UseCashItemHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/UseItemHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/MovePetHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/quest/QuestActionManager.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/guild/MapleAlliance.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/Server.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerLoggedinHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/LogHelper.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/world0/2010009.js + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleMount.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/guild/MapleGuild.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/TimerManager.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleQuestStatus.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/QuestActionHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleTrade.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleInventoryManipulator.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/CharInfoRequestHandler.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleClient.java + file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/quest/MapleQuest.java + diff --git a/scripts/npc/world0/2010009.js b/scripts/npc/world0/2010009.js index 4ba70595bb..03f1b62737 100644 --- a/scripts/npc/world0/2010009.js +++ b/scripts/npc/world0/2010009.js @@ -72,6 +72,12 @@ function action(mode, type, selection) { cm.sendYesNo("Oh, are you interested in forming a Guild Union? The current fee for this operation is #b" + allianceCost + " mesos#k."); } else if (selection == 3) { + if(cm.getPlayer().getMGC() == null) { + cm.sendOk("You can not expand a Guild Union if you don't own one."); + cm.dispose(); + return; + } + var rank = cm.getPlayer().getMGC().getAllianceRank(); if (rank == 1) cm.sendYesNo("Do you want to increase your Alliance by one guild slot? The fee for this procedure is #b" + increaseCost + " mesos#k."); @@ -80,6 +86,12 @@ function action(mode, type, selection) { cm.dispose(); } } else if(selection == 4) { + if(cm.getPlayer().getMGC() == null) { + cm.sendOk("You can not disband a Guild Union if you don't own one."); + cm.dispose(); + return; + } + var rank = cm.getPlayer().getMGC().getAllianceRank(); if (rank == 1) cm.sendYesNo("Are you sure you want to disband your Guild Union?"); diff --git a/scripts/quest/2230.js b/scripts/quest/2230.js index e16da4d081..6a1ea10a21 100644 --- a/scripts/quest/2230.js +++ b/scripts/quest/2230.js @@ -70,7 +70,8 @@ function end(mode, type, selection) { } else if (status == 5) { qm.sendYesNo("Now do you understand? Every action comes with consequences, and pets are no exception. The egg of the snail shall hatch soon."); } else if (status == 6) { - qm.gainItem(5000054, 1); // rune snail * 1 + qm.gainItem(5000054, 1, false, true, 5 * 60 * 60 * 1000); // rune snail (5hrs) + qm.gainItem(4032086, -1); // Mysterious Egg * -1 qm.forceCompleteQuest(); qm.sendNext("This snail will only be alive for #b5 hours#k. Shower it with love. Your love will be reciprocated in the end."); diff --git a/src/client/MapleCharacter.java b/src/client/MapleCharacter.java index f16b2199d7..e450efa4b0 100644 --- a/src/client/MapleCharacter.java +++ b/src/client/MapleCharacter.java @@ -239,7 +239,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { private SavedLocation savedLocations[]; private SkillMacro[] skillMacros = new SkillMacro[5]; private List lastmonthfameids; - private Map quests; + private final Map quests; private Set controlled = new LinkedHashSet<>(); private Map entered = new LinkedHashMap<>(); private Set visibleMapObjects = new LinkedHashSet<>(); @@ -2067,13 +2067,16 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { } public final List getCompletedQuests() { - List ret = new LinkedList<>(); - for (MapleQuestStatus q : quests.values()) { - if (q.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) { - ret.add(q); + synchronized (quests) { + List ret = new LinkedList<>(); + for (MapleQuestStatus q : quests.values()) { + if (q.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) { + ret.add(q); + } } + + return Collections.unmodifiableList(ret); } - return Collections.unmodifiableList(ret); } public Collection getControlledMonsters() { @@ -2603,46 +2606,58 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { } public final byte getQuestStatus(final int quest) { - for (final MapleQuestStatus q : quests.values()) { - if (q.getQuest().getId() == quest) { - return (byte) q.getStatus().getId(); + synchronized (quests) { + for (final MapleQuestStatus q : quests.values()) { + if (q.getQuest().getId() == quest) { + return (byte) q.getStatus().getId(); + } } + return 0; } - return 0; } public MapleQuestStatus getQuest(MapleQuest quest) { - if (!quests.containsKey(quest.getId())) { - return new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED); + synchronized (quests) { + if (!quests.containsKey(quest.getId())) { + return new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED); + } + return quests.get(quest.getId()); } - return quests.get(quest.getId()); } //---- \/ \/ \/ \/ \/ \/ \/ NOT TESTED \/ \/ \/ \/ \/ \/ \/ \/ \/ ---- public final void setQuestAdd(final MapleQuest quest, final byte status, final String customData) { - if (!quests.containsKey(quest.getId())) { - final MapleQuestStatus stat = new MapleQuestStatus(quest, MapleQuestStatus.Status.getById((int)status)); - stat.setCustomData(customData); - quests.put(quest.getId(), stat); + synchronized (quests) { + if (!quests.containsKey(quest.getId())) { + final MapleQuestStatus stat = new MapleQuestStatus(quest, MapleQuestStatus.Status.getById((int)status)); + stat.setCustomData(customData); + quests.put(quest.getId(), stat); + } } } public final MapleQuestStatus getQuestNAdd(final MapleQuest quest) { - if (!quests.containsKey(quest.getId())) { - final MapleQuestStatus status = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED); - quests.put(quest.getId(), status); - return status; + synchronized (quests) { + if (!quests.containsKey(quest.getId())) { + final MapleQuestStatus status = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED); + quests.put(quest.getId(), status); + return status; + } + return quests.get(quest.getId()); } - return quests.get(quest.getId()); } public final MapleQuestStatus getQuestNoAdd(final MapleQuest quest) { - return quests.get(quest.getId()); + synchronized (quests) { + return quests.get(quest.getId()); + } } public final MapleQuestStatus getQuestRemove(final MapleQuest quest) { - return quests.remove(quest.getId()); + synchronized (quests) { + return quests.remove(quest.getId()); + } } //---- /\ /\ /\ /\ /\ /\ /\ NOT TESTED /\ /\ /\ /\ /\ /\ /\ /\ /\ ---- @@ -2742,26 +2757,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { } public final List getStartedQuests() { - List ret = new LinkedList<>(); - for (MapleQuestStatus q : quests.values()) { - if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) { - ret.add(q); + synchronized (quests) { + List ret = new LinkedList<>(); + for (MapleQuestStatus q : quests.values()) { + if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) { + ret.add(q); + } } + return Collections.unmodifiableList(ret); } - return Collections.unmodifiableList(ret); } public final int getStartedQuestsSize() { - int i = 0; - for (MapleQuestStatus q : quests.values()) { - if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) { - if (q.getQuest().getInfoNumber() > 0) { + synchronized (quests) { + int i = 0; + for (MapleQuestStatus q : quests.values()) { + if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) { + if (q.getQuest().getInfoNumber() > 0) { + i++; + } i++; } - i++; } + return i; } - return i; } public MapleStatEffect getStatForBuff(MapleBuffStat effect) { @@ -3698,17 +3717,19 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { } int lastQuestProcessed = 0; try { - for (MapleQuestStatus q : quests.values()) { - lastQuestProcessed = q.getQuest().getId(); - if (q.getStatus() == MapleQuestStatus.Status.COMPLETED || q.getQuest().canComplete(this, null)) { - continue; - } - String progress = q.getProgress(id); - if (!progress.isEmpty() && Integer.parseInt(progress) >= q.getQuest().getMobAmountNeeded(id)) { - continue; - } - if (q.progress(id)) { - client.announce(MaplePacketCreator.updateQuest(q, false)); + synchronized (quests) { + for (MapleQuestStatus q : quests.values()) { + lastQuestProcessed = q.getQuest().getId(); + if (q.getStatus() == MapleQuestStatus.Status.COMPLETED || q.getQuest().canComplete(this, null)) { + continue; + } + String progress = q.getProgress(id); + if (!progress.isEmpty() && Integer.parseInt(progress) >= q.getQuest().getMobAmountNeeded(id)) { + continue; + } + if (q.progress(id)) { + client.announce(MaplePacketCreator.updateQuest(q, false)); + } } } } catch (Exception e) { @@ -4536,27 +4557,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { try (PreparedStatement pse = con.prepareStatement("INSERT INTO questprogress VALUES (DEFAULT, ?, ?, ?)")) { psf = con.prepareStatement("INSERT INTO medalmaps VALUES (DEFAULT, ?, ?)"); ps.setInt(1, id); - for (MapleQuestStatus q : quests.values()) { - ps.setInt(2, q.getQuest().getId()); - ps.setInt(3, q.getStatus().getId()); - ps.setInt(4, (int) (q.getCompletionTime() / 1000)); - ps.setInt(5, q.getForfeited()); - ps.executeUpdate(); - try (ResultSet rs = ps.getGeneratedKeys()) { - rs.next(); - for (int mob : q.getProgress().keySet()) { - pse.setInt(1, rs.getInt(1)); - pse.setInt(2, mob); - pse.setString(3, q.getProgress(mob)); - pse.addBatch(); + + synchronized (quests) { + for (MapleQuestStatus q : quests.values()) { + ps.setInt(2, q.getQuest().getId()); + ps.setInt(3, q.getStatus().getId()); + ps.setInt(4, (int) (q.getCompletionTime() / 1000)); + ps.setInt(5, q.getForfeited()); + ps.executeUpdate(); + try (ResultSet rs = ps.getGeneratedKeys()) { + rs.next(); + for (int mob : q.getProgress().keySet()) { + pse.setInt(1, rs.getInt(1)); + pse.setInt(2, mob); + pse.setString(3, q.getProgress(mob)); + pse.addBatch(); + } + for (int i = 0; i < q.getMedalMaps().size(); i++) { + psf.setInt(1, rs.getInt(1)); + psf.setInt(2, q.getMedalMaps().get(i)); + psf.addBatch(); + } + pse.executeBatch(); + psf.executeBatch(); } - for (int i = 0; i < q.getMedalMaps().size(); i++) { - psf.setInt(1, rs.getInt(1)); - psf.setInt(2, q.getMedalMaps().get(i)); - psf.addBatch(); - } - pse.executeBatch(); - psf.executeBatch(); } } } @@ -5334,7 +5358,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { MapleQuestStatus qs = getQuest(q); qs.setInfo(info); - quests.put(q.getId(), qs); + synchronized (quests) { + quests.put(q.getId(), qs); + } announce(MaplePacketCreator.updateQuest(qs, false)); if (qs.getQuest().getInfoNumber() > 0) { @@ -5354,7 +5380,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { } public void updateQuest(MapleQuestStatus quest) { - quests.put(quest.getQuestID(), quest); + synchronized (quests) { + quests.put(quest.getQuestID(), quest); + } if (quest.getStatus().equals(MapleQuestStatus.Status.STARTED)) { announce(MaplePacketCreator.updateQuest(quest, false)); if (quest.getQuest().getInfoNumber() > 0) { @@ -5375,17 +5403,20 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject { } } - public void questTimeLimit(final MapleQuest quest, int time) { + public void questTimeLimit(final MapleQuest quest, int seconds) { + final MapleCharacter chr = this; ScheduledFuture sf = TimerManager.getInstance().schedule(new Runnable() { @Override public void run() { + if(chr.getQuestStatus(quest.getId()) == MapleQuestStatus.Status.COMPLETED.getId()) return; + announce(MaplePacketCreator.questExpire(quest.getId())); MapleQuestStatus newStatus = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED); newStatus.setForfeited(getQuest(quest).getForfeited() + 1); updateQuest(newStatus); } - }, time * 60 * 1000); - announce(MaplePacketCreator.addQuestTimeLimit(quest.getId(), time * 60 * 1000)); + }, seconds * 1000); + announce(MaplePacketCreator.addQuestTimeLimit(quest.getId(), seconds * 1000)); timers.add(sf); } diff --git a/src/client/MapleClient.java b/src/client/MapleClient.java index 42b9b45ea6..d8b783f05d 100644 --- a/src/client/MapleClient.java +++ b/src/client/MapleClient.java @@ -786,7 +786,7 @@ public class MapleClient { final MapleGuild guild = player.getGuild(); if (channel == -1 || shutdown) { - chrg.setCharacter(null); + if(chrg != null) chrg.setCharacter(null); removePlayer(); player.saveCooldowns(); diff --git a/src/client/MapleMount.java b/src/client/MapleMount.java index c7f159713c..7038ed53a6 100644 --- a/src/client/MapleMount.java +++ b/src/client/MapleMount.java @@ -97,18 +97,19 @@ public class MapleMount { } private void increaseTiredness() { - if(owner != null) { - this.tiredness++; - owner.getMap().broadcastMessage(MaplePacketCreator.updateMount(owner.getId(), this, false)); - if (tiredness > 99) { - this.tiredness = 99; - owner.dispelSkill(owner.getJobType() * 10000000 + 1004); - } - } else { - if(this.tirednessSchedule != null) { - this.tirednessSchedule.cancel(false); - } - } + if(owner != null) { + this.tiredness++; + owner.getMap().broadcastMessage(MaplePacketCreator.updateMount(owner.getId(), this, false)); + if (tiredness > 99) { + this.tiredness = 99; + owner.dispelSkill(owner.getJobType() * 10000000 + 1004); + owner.dropMessage("Your mount grew tired! Treat it some revitalizer before riding it again!"); + } + } else { + if(this.tirednessSchedule != null) { + this.tirednessSchedule.cancel(false); + } + } } public void setExp(int newexp) { diff --git a/src/net/server/channel/handlers/MovePetHandler.java b/src/net/server/channel/handlers/MovePetHandler.java index 0cf813617d..005f265604 100644 --- a/src/net/server/channel/handlers/MovePetHandler.java +++ b/src/net/server/channel/handlers/MovePetHandler.java @@ -21,7 +21,6 @@ */ package net.server.channel.handlers; -import net.server.channel.handlers.AbstractMovementPacketHandler; import java.util.List; import client.MapleCharacter; import client.MapleClient; @@ -30,6 +29,7 @@ import tools.MaplePacketCreator; import tools.data.input.SeekableLittleEndianAccessor; public final class MovePetHandler extends AbstractMovementPacketHandler { + @Override public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { int petId = slea.readInt(); slea.readLong(); diff --git a/src/net/server/channel/handlers/PlayerLoggedinHandler.java b/src/net/server/channel/handlers/PlayerLoggedinHandler.java index 8cf8bf3b72..e5fdaedef7 100644 --- a/src/net/server/channel/handlers/PlayerLoggedinHandler.java +++ b/src/net/server/channel/handlers/PlayerLoggedinHandler.java @@ -191,6 +191,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler { } else { playerGuild.getMGC(player.getId()).setCharacter(player); player.setMGC(playerGuild.getMGC(player.getId())); + server.setGuildMemberOnline(player, true, c.getChannel()); c.announce(MaplePacketCreator.showGuildInfo(player)); int allianceId = player.getGuild().getAllianceId(); @@ -204,6 +205,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler { player.getGuild().setAllianceId(0); } } + if (newAlliance != null) { c.announce(MaplePacketCreator.updateAllianceInfo(newAlliance, c)); c.announce(MaplePacketCreator.allianceNotice(newAlliance.getId(), newAlliance.getNotice())); @@ -267,11 +269,11 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler { if (player.getMap().getHPDec() > 0) { final MapleCharacter mc = player; - ScheduledFuture hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() { - @Override - public void run() { - mc.doHurtHp(); - } + TimerManager.getInstance().schedule(new Runnable() { + @Override + public void run() { + mc.doHurtHp(); + } }, 10000); } } diff --git a/src/net/server/world/World.java b/src/net/server/world/World.java index f067dfaff6..b8448ab87d 100644 --- a/src/net/server/world/World.java +++ b/src/net/server/world/World.java @@ -194,6 +194,8 @@ public class World { } public MapleGuild getGuild(MapleGuildCharacter mgc) { + if(mgc == null) return null; + int gid = mgc.getGuildId(); MapleGuild g; g = Server.getInstance().getGuild(gid, mgc.getWorld(), mgc.getCharacter()); diff --git a/src/server/MapleStatEffect.java b/src/server/MapleStatEffect.java index 60d2cddffb..4d5a7b3bbd 100644 --- a/src/server/MapleStatEffect.java +++ b/src/server/MapleStatEffect.java @@ -943,7 +943,10 @@ public class MapleStatEffect { if (applyto.getMount() == null) { applyto.mount(ridingLevel, sourceid); } - applyto.getMount().startSchedule(); + + if(!(ServerConstants.PETS_NEVER_HUNGRY || applyto.isGM() && ServerConstants.GM_PETS_NEVER_HUNGRY)) { + applyto.getMount().startSchedule(); + } } if (sourceid == Corsair.BATTLE_SHIP) { givemount = new MapleMount(applyto, 1932000, sourceid); diff --git a/src/server/MapleTrade.java b/src/server/MapleTrade.java index b1e52e6b9b..e0b14e5a87 100644 --- a/src/server/MapleTrade.java +++ b/src/server/MapleTrade.java @@ -26,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import tools.LogHelper; import tools.MaplePacketCreator; @@ -33,10 +34,11 @@ import client.MapleCharacter; import client.inventory.Item; import client.inventory.MapleInventoryType; import constants.ItemConstants; +import constants.ServerConstants; /** * - * @author Matze + * @author Matze, Ronan (concurrency safety) */ public class MapleTrade { private MapleTrade partner = null; @@ -44,7 +46,7 @@ public class MapleTrade { private List exchangeItems; private int meso = 0; private int exchangeMeso; - boolean locked = false; + private AtomicBoolean locked = new AtomicBoolean(false); private MapleCharacter chr; private byte number; private boolean fullTrade = false; @@ -73,7 +75,7 @@ public class MapleTrade { } private void lock() { - locked = true; + locked.set(true); partner.getChr().getClient().announce(MaplePacketCreator.getTradeConfirmation()); } @@ -83,16 +85,18 @@ public class MapleTrade { } private void complete2() { + boolean show = ServerConstants.USE_DEBUG; + items.clear(); meso = 0; for (Item item : exchangeItems) { if ((item.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA) item.setFlag((byte) (item.getFlag() ^ ItemConstants.KARMA)); //items with scissors of karma used on them are reset once traded - MapleInventoryManipulator.addFromDrop(chr.getClient(), item, true); + MapleInventoryManipulator.addFromDrop(chr.getClient(), item, show); } if (exchangeMeso > 0) { - chr.gainMeso(exchangeMeso - getFee(exchangeMeso), true, true, true); + chr.gainMeso(exchangeMeso - getFee(exchangeMeso), show, true, show); } exchangeMeso = 0; if (exchangeItems != null) { @@ -102,11 +106,13 @@ public class MapleTrade { } private void cancel() { + boolean show = ServerConstants.USE_DEBUG; + for (Item item : items) { - MapleInventoryManipulator.addFromDrop(chr.getClient(), item, true); + MapleInventoryManipulator.addFromDrop(chr.getClient(), item, show); } if (meso > 0) { - chr.gainMeso(meso, true, true, true); + chr.gainMeso(meso, show, true, show); } meso = 0; if (items != null) { @@ -120,7 +126,7 @@ public class MapleTrade { } private boolean isLocked() { - return locked; + return locked.get(); } private int getMeso() { @@ -128,7 +134,7 @@ public class MapleTrade { } public void setMeso(int meso) { - if (locked) { + if (locked.get()) { throw new RuntimeException("Trade is locked."); } if (meso < 0) { @@ -166,7 +172,7 @@ public class MapleTrade { } public void setPartner(MapleTrade partner) { - if (locked) { + if (locked.get()) { return; } this.partner = partner; @@ -210,9 +216,15 @@ public class MapleTrade { if (partner.isLocked()) { local.complete1(); partner.complete1(); - if (!local.fitsInInventory() || !partner.fitsInInventory()) { + if (!local.fitsInInventory()) { cancelTrade(c); c.message("There is not enough inventory space to complete the trade."); + partner.getChr().message("Partner does not have enough inventory space to complete the trade."); + return; + } + else if (!partner.fitsInInventory()) { + cancelTrade(c); + c.message("Partner does not have enough inventory space to complete the trade."); partner.getChr().message("There is not enough inventory space to complete the trade."); return; } @@ -224,13 +236,13 @@ public class MapleTrade { } else { local.getChr().addMesosTraded(local.exchangeMeso); } - } else if (c.getTrade().getChr().getLevel() < 15) { - if (c.getMesosTraded() + c.getTrade().exchangeMeso > 1000000) { + } else if (partner.getChr().getLevel() < 15) { + if (partner.getChr().getMesosTraded() + partner.exchangeMeso > 1000000) { cancelTrade(c); - c.getClient().announce(MaplePacketCreator.serverNotice(1, "Characters under level 15 may not trade more than 1 million mesos per day.")); + partner.getChr().getClient().announce(MaplePacketCreator.serverNotice(1, "Characters under level 15 may not trade more than 1 million mesos per day.")); return; } else { - c.addMesosTraded(local.exchangeMeso); + partner.getChr().addMesosTraded(partner.exchangeMeso); } } LogHelper.logTrade(local, partner); diff --git a/src/server/quest/MapleQuest.java b/src/server/quest/MapleQuest.java index 19700bd68c..66ebf72c6d 100644 --- a/src/server/quest/MapleQuest.java +++ b/src/server/quest/MapleQuest.java @@ -46,7 +46,7 @@ public class MapleQuest { private static Map quests = new HashMap<>(); protected short infoNumber, id; - protected int timeLimit, timeLimit2; + protected int timeLimit; protected String infoex; protected Map startReqs = new EnumMap<>(MapleQuestRequirementType.class); protected Map completeReqs = new EnumMap<>(MapleQuestRequirementType.class); @@ -57,20 +57,22 @@ public class MapleQuest { private boolean autoPreComplete, autoComplete; private boolean repeatable = false; private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz")); - private static MapleData questInfo; - private static MapleData questAct; - private static MapleData questReq; + private static MapleData questInfo; + private static MapleData questAct; + private static MapleData questReq; private MapleQuest(int id) { this.id = (short) id; - if(questInfo != null) { - timeLimit = MapleDataTool.getInt("timeLimit", questInfo, 0); - timeLimit2 = MapleDataTool.getInt("timeLimit2", questInfo, 0); - autoStart = MapleDataTool.getInt("autoStart", questInfo, 0) == 1; - autoPreComplete = MapleDataTool.getInt("autoPreComplete", questInfo, 0) == 1; - autoComplete = MapleDataTool.getInt("autoComplete", questInfo, 0) == 1; - } + if(questInfo != null) { + MapleData reqData = questInfo.getChildByPath(String.valueOf(id)); + + timeLimit = MapleDataTool.getInt("timeLimit", reqData, 0); + timeLimit = Math.max(timeLimit, MapleDataTool.getInt("timeLimit2", reqData, 0)); // alas, nexon made we deal with 2 timeLimits + autoStart = MapleDataTool.getInt("autoStart", reqData, 0) == 1; + autoPreComplete = MapleDataTool.getInt("autoPreComplete", reqData, 0) == 1; + autoComplete = MapleDataTool.getInt("autoComplete", reqData, 0) == 1; + } MapleData reqData = questReq.getChildByPath(String.valueOf(id)); if (reqData == null) {//most likely infoEx @@ -84,7 +86,7 @@ public class MapleQuest { repeatable = true; } - if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) { + if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) { infoNumber = (short) MapleDataTool.getInt(startReq, 0); } @@ -280,11 +282,9 @@ public class MapleQuest { newStatus.setForfeited(c.getQuest(this).getForfeited()); if (timeLimit > 0) { - c.questTimeLimit(this, 30000);//timeLimit * 1000 - } - if (timeLimit2 > 0) {//=\ - + c.questTimeLimit(this, timeLimit); } + c.updateQuest(newStatus); return true; } diff --git a/src/tools/MaplePacketCreator.java b/src/tools/MaplePacketCreator.java index ee284ce2ab..1a08a5fe14 100644 --- a/src/tools/MaplePacketCreator.java +++ b/src/tools/MaplePacketCreator.java @@ -2337,16 +2337,18 @@ public class MaplePacketCreator { mplew.write(chr.getMarriageRing() != null ? 1 : 0); String guildName = ""; String allianceName = ""; - MapleGuildSummary gs = chr.getClient().getWorldServer().getGuildSummary(chr.getGuildId(), chr.getWorld()); - if (chr.getGuildId() > 0 && gs != null) { - guildName = gs.getName(); - MapleAlliance alliance = Server.getInstance().getAlliance(gs.getAllianceId()); + if (chr.getGuildId() > 0) { + MapleGuild mg = Server.getInstance().getGuild(chr.getGuildId()); + guildName = mg.getName(); + + MapleAlliance alliance = Server.getInstance().getAlliance(chr.getGuild().getAllianceId()); if (alliance != null) { allianceName = alliance.getName(); } } mplew.writeMapleAsciiString(guildName); - mplew.writeMapleAsciiString(allianceName); + mplew.writeMapleAsciiString(allianceName); // does not seems to work + mplew.write(0); MaplePet[] pets = chr.getPets(); Item inv = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -114); diff --git a/todo.txt b/todo.txt index 3265476950..5a5d298176 100644 --- a/todo.txt +++ b/todo.txt @@ -1,2 +1 @@ -guild npc PQs \ No newline at end of file