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