Protected Trade/Quest system + Expirable quests
Added true protection against race conditions on player trades and fixed some situational issues. Character's quest status table also received concurrency treatment. Quests with time limit now expires properly. Increased subtly the performance on the server start-up.
This commit is contained in:
@@ -250,4 +250,10 @@ Solu
|
|||||||
|
|
||||||
25 Maio 2017,
|
25 Maio 2017,
|
||||||
Solução final ao problema das Guild Alliances. Todas as funcionalidades implementadas.
|
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.
|
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.
|
||||||
@@ -5,12 +5,38 @@
|
|||||||
<url>src/tools/MaplePacketCreator.java</url>
|
<url>src/tools/MaplePacketCreator.java</url>
|
||||||
<bookmark id="1">
|
<bookmark id="1">
|
||||||
<name/>
|
<name/>
|
||||||
<line>5939</line>
|
<line>5941</line>
|
||||||
<key/>
|
<key/>
|
||||||
</bookmark>
|
</bookmark>
|
||||||
</file>
|
</file>
|
||||||
</editor-bookmarks>
|
</editor-bookmarks>
|
||||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||||
<group/>
|
<group>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/command/Commands.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleStatEffect.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/provider/MapleDataTool.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerInteractionHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/UseCashItemHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/UseItemHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/MovePetHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/scripting/quest/QuestActionManager.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/guild/MapleAlliance.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/Server.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerLoggedinHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/LogHelper.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/world0/2010009.js</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleMount.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/guild/MapleGuild.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/TimerManager.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleQuestStatus.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/QuestActionHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleTrade.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleInventoryManipulator.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/CharInfoRequestHandler.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleClient.java</file>
|
||||||
|
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/quest/MapleQuest.java</file>
|
||||||
|
</group>
|
||||||
</open-files>
|
</open-files>
|
||||||
</project-private>
|
</project-private>
|
||||||
|
|||||||
@@ -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.");
|
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) {
|
} 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();
|
var rank = cm.getPlayer().getMGC().getAllianceRank();
|
||||||
if (rank == 1)
|
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.");
|
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();
|
cm.dispose();
|
||||||
}
|
}
|
||||||
} else if(selection == 4) {
|
} 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();
|
var rank = cm.getPlayer().getMGC().getAllianceRank();
|
||||||
if (rank == 1)
|
if (rank == 1)
|
||||||
cm.sendYesNo("Are you sure you want to disband your Guild Union?");
|
cm.sendYesNo("Are you sure you want to disband your Guild Union?");
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ function end(mode, type, selection) {
|
|||||||
} else if (status == 5) {
|
} 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.");
|
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) {
|
} 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.gainItem(4032086, -1); // Mysterious Egg * -1
|
||||||
qm.forceCompleteQuest();
|
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.");
|
qm.sendNext("This snail will only be alive for #b5 hours#k. Shower it with love. Your love will be reciprocated in the end.");
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
private SavedLocation savedLocations[];
|
private SavedLocation savedLocations[];
|
||||||
private SkillMacro[] skillMacros = new SkillMacro[5];
|
private SkillMacro[] skillMacros = new SkillMacro[5];
|
||||||
private List<Integer> lastmonthfameids;
|
private List<Integer> lastmonthfameids;
|
||||||
private Map<Short, MapleQuestStatus> quests;
|
private final Map<Short, MapleQuestStatus> quests;
|
||||||
private Set<MapleMonster> controlled = new LinkedHashSet<>();
|
private Set<MapleMonster> controlled = new LinkedHashSet<>();
|
||||||
private Map<Integer, String> entered = new LinkedHashMap<>();
|
private Map<Integer, String> entered = new LinkedHashMap<>();
|
||||||
private Set<MapleMapObject> visibleMapObjects = new LinkedHashSet<>();
|
private Set<MapleMapObject> visibleMapObjects = new LinkedHashSet<>();
|
||||||
@@ -2067,13 +2067,16 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final List<MapleQuestStatus> getCompletedQuests() {
|
public final List<MapleQuestStatus> getCompletedQuests() {
|
||||||
List<MapleQuestStatus> ret = new LinkedList<>();
|
synchronized (quests) {
|
||||||
for (MapleQuestStatus q : quests.values()) {
|
List<MapleQuestStatus> ret = new LinkedList<>();
|
||||||
if (q.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) {
|
for (MapleQuestStatus q : quests.values()) {
|
||||||
ret.add(q);
|
if (q.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) {
|
||||||
|
ret.add(q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(ret);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<MapleMonster> getControlledMonsters() {
|
public Collection<MapleMonster> getControlledMonsters() {
|
||||||
@@ -2603,46 +2606,58 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final byte getQuestStatus(final int quest) {
|
public final byte getQuestStatus(final int quest) {
|
||||||
for (final MapleQuestStatus q : quests.values()) {
|
synchronized (quests) {
|
||||||
if (q.getQuest().getId() == quest) {
|
for (final MapleQuestStatus q : quests.values()) {
|
||||||
return (byte) q.getStatus().getId();
|
if (q.getQuest().getId() == quest) {
|
||||||
|
return (byte) q.getStatus().getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleQuestStatus getQuest(MapleQuest quest) {
|
public MapleQuestStatus getQuest(MapleQuest quest) {
|
||||||
if (!quests.containsKey(quest.getId())) {
|
synchronized (quests) {
|
||||||
return new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
|
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 \/ \/ \/ \/ \/ \/ \/ \/ \/ ----
|
//---- \/ \/ \/ \/ \/ \/ \/ NOT TESTED \/ \/ \/ \/ \/ \/ \/ \/ \/ ----
|
||||||
|
|
||||||
public final void setQuestAdd(final MapleQuest quest, final byte status, final String customData) {
|
public final void setQuestAdd(final MapleQuest quest, final byte status, final String customData) {
|
||||||
if (!quests.containsKey(quest.getId())) {
|
synchronized (quests) {
|
||||||
final MapleQuestStatus stat = new MapleQuestStatus(quest, MapleQuestStatus.Status.getById((int)status));
|
if (!quests.containsKey(quest.getId())) {
|
||||||
stat.setCustomData(customData);
|
final MapleQuestStatus stat = new MapleQuestStatus(quest, MapleQuestStatus.Status.getById((int)status));
|
||||||
quests.put(quest.getId(), stat);
|
stat.setCustomData(customData);
|
||||||
|
quests.put(quest.getId(), stat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final MapleQuestStatus getQuestNAdd(final MapleQuest quest) {
|
public final MapleQuestStatus getQuestNAdd(final MapleQuest quest) {
|
||||||
if (!quests.containsKey(quest.getId())) {
|
synchronized (quests) {
|
||||||
final MapleQuestStatus status = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
|
if (!quests.containsKey(quest.getId())) {
|
||||||
quests.put(quest.getId(), status);
|
final MapleQuestStatus status = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
|
||||||
return status;
|
quests.put(quest.getId(), status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return quests.get(quest.getId());
|
||||||
}
|
}
|
||||||
return quests.get(quest.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final MapleQuestStatus getQuestNoAdd(final MapleQuest quest) {
|
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) {
|
public final MapleQuestStatus getQuestRemove(final MapleQuest quest) {
|
||||||
return quests.remove(quest.getId());
|
synchronized (quests) {
|
||||||
|
return quests.remove(quest.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- /\ /\ /\ /\ /\ /\ /\ NOT TESTED /\ /\ /\ /\ /\ /\ /\ /\ /\ ----
|
//---- /\ /\ /\ /\ /\ /\ /\ NOT TESTED /\ /\ /\ /\ /\ /\ /\ /\ /\ ----
|
||||||
@@ -2742,26 +2757,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final List<MapleQuestStatus> getStartedQuests() {
|
public final List<MapleQuestStatus> getStartedQuests() {
|
||||||
List<MapleQuestStatus> ret = new LinkedList<>();
|
synchronized (quests) {
|
||||||
for (MapleQuestStatus q : quests.values()) {
|
List<MapleQuestStatus> ret = new LinkedList<>();
|
||||||
if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
for (MapleQuestStatus q : quests.values()) {
|
||||||
ret.add(q);
|
if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
||||||
|
ret.add(q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return Collections.unmodifiableList(ret);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getStartedQuestsSize() {
|
public final int getStartedQuestsSize() {
|
||||||
int i = 0;
|
synchronized (quests) {
|
||||||
for (MapleQuestStatus q : quests.values()) {
|
int i = 0;
|
||||||
if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
for (MapleQuestStatus q : quests.values()) {
|
||||||
if (q.getQuest().getInfoNumber() > 0) {
|
if (q.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
||||||
|
if (q.getQuest().getInfoNumber() > 0) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapleStatEffect getStatForBuff(MapleBuffStat effect) {
|
public MapleStatEffect getStatForBuff(MapleBuffStat effect) {
|
||||||
@@ -3698,17 +3717,19 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
}
|
}
|
||||||
int lastQuestProcessed = 0;
|
int lastQuestProcessed = 0;
|
||||||
try {
|
try {
|
||||||
for (MapleQuestStatus q : quests.values()) {
|
synchronized (quests) {
|
||||||
lastQuestProcessed = q.getQuest().getId();
|
for (MapleQuestStatus q : quests.values()) {
|
||||||
if (q.getStatus() == MapleQuestStatus.Status.COMPLETED || q.getQuest().canComplete(this, null)) {
|
lastQuestProcessed = q.getQuest().getId();
|
||||||
continue;
|
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)) {
|
String progress = q.getProgress(id);
|
||||||
continue;
|
if (!progress.isEmpty() && Integer.parseInt(progress) >= q.getQuest().getMobAmountNeeded(id)) {
|
||||||
}
|
continue;
|
||||||
if (q.progress(id)) {
|
}
|
||||||
client.announce(MaplePacketCreator.updateQuest(q, false));
|
if (q.progress(id)) {
|
||||||
|
client.announce(MaplePacketCreator.updateQuest(q, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -4536,27 +4557,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
try (PreparedStatement pse = con.prepareStatement("INSERT INTO questprogress VALUES (DEFAULT, ?, ?, ?)")) {
|
try (PreparedStatement pse = con.prepareStatement("INSERT INTO questprogress VALUES (DEFAULT, ?, ?, ?)")) {
|
||||||
psf = con.prepareStatement("INSERT INTO medalmaps VALUES (DEFAULT, ?, ?)");
|
psf = con.prepareStatement("INSERT INTO medalmaps VALUES (DEFAULT, ?, ?)");
|
||||||
ps.setInt(1, id);
|
ps.setInt(1, id);
|
||||||
for (MapleQuestStatus q : quests.values()) {
|
|
||||||
ps.setInt(2, q.getQuest().getId());
|
synchronized (quests) {
|
||||||
ps.setInt(3, q.getStatus().getId());
|
for (MapleQuestStatus q : quests.values()) {
|
||||||
ps.setInt(4, (int) (q.getCompletionTime() / 1000));
|
ps.setInt(2, q.getQuest().getId());
|
||||||
ps.setInt(5, q.getForfeited());
|
ps.setInt(3, q.getStatus().getId());
|
||||||
ps.executeUpdate();
|
ps.setInt(4, (int) (q.getCompletionTime() / 1000));
|
||||||
try (ResultSet rs = ps.getGeneratedKeys()) {
|
ps.setInt(5, q.getForfeited());
|
||||||
rs.next();
|
ps.executeUpdate();
|
||||||
for (int mob : q.getProgress().keySet()) {
|
try (ResultSet rs = ps.getGeneratedKeys()) {
|
||||||
pse.setInt(1, rs.getInt(1));
|
rs.next();
|
||||||
pse.setInt(2, mob);
|
for (int mob : q.getProgress().keySet()) {
|
||||||
pse.setString(3, q.getProgress(mob));
|
pse.setInt(1, rs.getInt(1));
|
||||||
pse.addBatch();
|
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);
|
MapleQuestStatus qs = getQuest(q);
|
||||||
qs.setInfo(info);
|
qs.setInfo(info);
|
||||||
|
|
||||||
quests.put(q.getId(), qs);
|
synchronized (quests) {
|
||||||
|
quests.put(q.getId(), qs);
|
||||||
|
}
|
||||||
|
|
||||||
announce(MaplePacketCreator.updateQuest(qs, false));
|
announce(MaplePacketCreator.updateQuest(qs, false));
|
||||||
if (qs.getQuest().getInfoNumber() > 0) {
|
if (qs.getQuest().getInfoNumber() > 0) {
|
||||||
@@ -5354,7 +5380,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateQuest(MapleQuestStatus quest) {
|
public void updateQuest(MapleQuestStatus quest) {
|
||||||
quests.put(quest.getQuestID(), quest);
|
synchronized (quests) {
|
||||||
|
quests.put(quest.getQuestID(), quest);
|
||||||
|
}
|
||||||
if (quest.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
if (quest.getStatus().equals(MapleQuestStatus.Status.STARTED)) {
|
||||||
announce(MaplePacketCreator.updateQuest(quest, false));
|
announce(MaplePacketCreator.updateQuest(quest, false));
|
||||||
if (quest.getQuest().getInfoNumber() > 0) {
|
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() {
|
ScheduledFuture<?> sf = TimerManager.getInstance().schedule(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
if(chr.getQuestStatus(quest.getId()) == MapleQuestStatus.Status.COMPLETED.getId()) return;
|
||||||
|
|
||||||
announce(MaplePacketCreator.questExpire(quest.getId()));
|
announce(MaplePacketCreator.questExpire(quest.getId()));
|
||||||
MapleQuestStatus newStatus = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
|
MapleQuestStatus newStatus = new MapleQuestStatus(quest, MapleQuestStatus.Status.NOT_STARTED);
|
||||||
newStatus.setForfeited(getQuest(quest).getForfeited() + 1);
|
newStatus.setForfeited(getQuest(quest).getForfeited() + 1);
|
||||||
updateQuest(newStatus);
|
updateQuest(newStatus);
|
||||||
}
|
}
|
||||||
}, time * 60 * 1000);
|
}, seconds * 1000);
|
||||||
announce(MaplePacketCreator.addQuestTimeLimit(quest.getId(), time * 60 * 1000));
|
announce(MaplePacketCreator.addQuestTimeLimit(quest.getId(), seconds * 1000));
|
||||||
timers.add(sf);
|
timers.add(sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -786,7 +786,7 @@ public class MapleClient {
|
|||||||
final MapleGuild guild = player.getGuild();
|
final MapleGuild guild = player.getGuild();
|
||||||
|
|
||||||
if (channel == -1 || shutdown) {
|
if (channel == -1 || shutdown) {
|
||||||
chrg.setCharacter(null);
|
if(chrg != null) chrg.setCharacter(null);
|
||||||
|
|
||||||
removePlayer();
|
removePlayer();
|
||||||
player.saveCooldowns();
|
player.saveCooldowns();
|
||||||
|
|||||||
@@ -97,18 +97,19 @@ public class MapleMount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void increaseTiredness() {
|
private void increaseTiredness() {
|
||||||
if(owner != null) {
|
if(owner != null) {
|
||||||
this.tiredness++;
|
this.tiredness++;
|
||||||
owner.getMap().broadcastMessage(MaplePacketCreator.updateMount(owner.getId(), this, false));
|
owner.getMap().broadcastMessage(MaplePacketCreator.updateMount(owner.getId(), this, false));
|
||||||
if (tiredness > 99) {
|
if (tiredness > 99) {
|
||||||
this.tiredness = 99;
|
this.tiredness = 99;
|
||||||
owner.dispelSkill(owner.getJobType() * 10000000 + 1004);
|
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) {
|
} else {
|
||||||
this.tirednessSchedule.cancel(false);
|
if(this.tirednessSchedule != null) {
|
||||||
}
|
this.tirednessSchedule.cancel(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExp(int newexp) {
|
public void setExp(int newexp) {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.server.channel.handlers;
|
package net.server.channel.handlers;
|
||||||
|
|
||||||
import net.server.channel.handlers.AbstractMovementPacketHandler;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import client.MapleClient;
|
import client.MapleClient;
|
||||||
@@ -30,6 +29,7 @@ import tools.MaplePacketCreator;
|
|||||||
import tools.data.input.SeekableLittleEndianAccessor;
|
import tools.data.input.SeekableLittleEndianAccessor;
|
||||||
|
|
||||||
public final class MovePetHandler extends AbstractMovementPacketHandler {
|
public final class MovePetHandler extends AbstractMovementPacketHandler {
|
||||||
|
@Override
|
||||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||||
int petId = slea.readInt();
|
int petId = slea.readInt();
|
||||||
slea.readLong();
|
slea.readLong();
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
|||||||
} else {
|
} else {
|
||||||
playerGuild.getMGC(player.getId()).setCharacter(player);
|
playerGuild.getMGC(player.getId()).setCharacter(player);
|
||||||
player.setMGC(playerGuild.getMGC(player.getId()));
|
player.setMGC(playerGuild.getMGC(player.getId()));
|
||||||
|
|
||||||
server.setGuildMemberOnline(player, true, c.getChannel());
|
server.setGuildMemberOnline(player, true, c.getChannel());
|
||||||
c.announce(MaplePacketCreator.showGuildInfo(player));
|
c.announce(MaplePacketCreator.showGuildInfo(player));
|
||||||
int allianceId = player.getGuild().getAllianceId();
|
int allianceId = player.getGuild().getAllianceId();
|
||||||
@@ -204,6 +205,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
|||||||
player.getGuild().setAllianceId(0);
|
player.getGuild().setAllianceId(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newAlliance != null) {
|
if (newAlliance != null) {
|
||||||
c.announce(MaplePacketCreator.updateAllianceInfo(newAlliance, c));
|
c.announce(MaplePacketCreator.updateAllianceInfo(newAlliance, c));
|
||||||
c.announce(MaplePacketCreator.allianceNotice(newAlliance.getId(), newAlliance.getNotice()));
|
c.announce(MaplePacketCreator.allianceNotice(newAlliance.getId(), newAlliance.getNotice()));
|
||||||
@@ -267,11 +269,11 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
|||||||
if (player.getMap().getHPDec() > 0) {
|
if (player.getMap().getHPDec() > 0) {
|
||||||
final MapleCharacter mc = player;
|
final MapleCharacter mc = player;
|
||||||
|
|
||||||
ScheduledFuture<?> hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() {
|
TimerManager.getInstance().schedule(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mc.doHurtHp();
|
mc.doHurtHp();
|
||||||
}
|
}
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,6 +194,8 @@ public class World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MapleGuild getGuild(MapleGuildCharacter mgc) {
|
public MapleGuild getGuild(MapleGuildCharacter mgc) {
|
||||||
|
if(mgc == null) return null;
|
||||||
|
|
||||||
int gid = mgc.getGuildId();
|
int gid = mgc.getGuildId();
|
||||||
MapleGuild g;
|
MapleGuild g;
|
||||||
g = Server.getInstance().getGuild(gid, mgc.getWorld(), mgc.getCharacter());
|
g = Server.getInstance().getGuild(gid, mgc.getWorld(), mgc.getCharacter());
|
||||||
|
|||||||
@@ -943,7 +943,10 @@ public class MapleStatEffect {
|
|||||||
if (applyto.getMount() == null) {
|
if (applyto.getMount() == null) {
|
||||||
applyto.mount(ridingLevel, sourceid);
|
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) {
|
if (sourceid == Corsair.BATTLE_SHIP) {
|
||||||
givemount = new MapleMount(applyto, 1932000, sourceid);
|
givemount = new MapleMount(applyto, 1932000, sourceid);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import tools.LogHelper;
|
import tools.LogHelper;
|
||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
@@ -33,10 +34,11 @@ import client.MapleCharacter;
|
|||||||
import client.inventory.Item;
|
import client.inventory.Item;
|
||||||
import client.inventory.MapleInventoryType;
|
import client.inventory.MapleInventoryType;
|
||||||
import constants.ItemConstants;
|
import constants.ItemConstants;
|
||||||
|
import constants.ServerConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Matze
|
* @author Matze, Ronan (concurrency safety)
|
||||||
*/
|
*/
|
||||||
public class MapleTrade {
|
public class MapleTrade {
|
||||||
private MapleTrade partner = null;
|
private MapleTrade partner = null;
|
||||||
@@ -44,7 +46,7 @@ public class MapleTrade {
|
|||||||
private List<Item> exchangeItems;
|
private List<Item> exchangeItems;
|
||||||
private int meso = 0;
|
private int meso = 0;
|
||||||
private int exchangeMeso;
|
private int exchangeMeso;
|
||||||
boolean locked = false;
|
private AtomicBoolean locked = new AtomicBoolean(false);
|
||||||
private MapleCharacter chr;
|
private MapleCharacter chr;
|
||||||
private byte number;
|
private byte number;
|
||||||
private boolean fullTrade = false;
|
private boolean fullTrade = false;
|
||||||
@@ -73,7 +75,7 @@ public class MapleTrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void lock() {
|
private void lock() {
|
||||||
locked = true;
|
locked.set(true);
|
||||||
partner.getChr().getClient().announce(MaplePacketCreator.getTradeConfirmation());
|
partner.getChr().getClient().announce(MaplePacketCreator.getTradeConfirmation());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,16 +85,18 @@ public class MapleTrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void complete2() {
|
private void complete2() {
|
||||||
|
boolean show = ServerConstants.USE_DEBUG;
|
||||||
|
|
||||||
items.clear();
|
items.clear();
|
||||||
meso = 0;
|
meso = 0;
|
||||||
for (Item item : exchangeItems) {
|
for (Item item : exchangeItems) {
|
||||||
if ((item.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA)
|
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
|
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) {
|
if (exchangeMeso > 0) {
|
||||||
chr.gainMeso(exchangeMeso - getFee(exchangeMeso), true, true, true);
|
chr.gainMeso(exchangeMeso - getFee(exchangeMeso), show, true, show);
|
||||||
}
|
}
|
||||||
exchangeMeso = 0;
|
exchangeMeso = 0;
|
||||||
if (exchangeItems != null) {
|
if (exchangeItems != null) {
|
||||||
@@ -102,11 +106,13 @@ public class MapleTrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void cancel() {
|
private void cancel() {
|
||||||
|
boolean show = ServerConstants.USE_DEBUG;
|
||||||
|
|
||||||
for (Item item : items) {
|
for (Item item : items) {
|
||||||
MapleInventoryManipulator.addFromDrop(chr.getClient(), item, true);
|
MapleInventoryManipulator.addFromDrop(chr.getClient(), item, show);
|
||||||
}
|
}
|
||||||
if (meso > 0) {
|
if (meso > 0) {
|
||||||
chr.gainMeso(meso, true, true, true);
|
chr.gainMeso(meso, show, true, show);
|
||||||
}
|
}
|
||||||
meso = 0;
|
meso = 0;
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
@@ -120,7 +126,7 @@ public class MapleTrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLocked() {
|
private boolean isLocked() {
|
||||||
return locked;
|
return locked.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMeso() {
|
private int getMeso() {
|
||||||
@@ -128,7 +134,7 @@ public class MapleTrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setMeso(int meso) {
|
public void setMeso(int meso) {
|
||||||
if (locked) {
|
if (locked.get()) {
|
||||||
throw new RuntimeException("Trade is locked.");
|
throw new RuntimeException("Trade is locked.");
|
||||||
}
|
}
|
||||||
if (meso < 0) {
|
if (meso < 0) {
|
||||||
@@ -166,7 +172,7 @@ public class MapleTrade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPartner(MapleTrade partner) {
|
public void setPartner(MapleTrade partner) {
|
||||||
if (locked) {
|
if (locked.get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.partner = partner;
|
this.partner = partner;
|
||||||
@@ -210,9 +216,15 @@ public class MapleTrade {
|
|||||||
if (partner.isLocked()) {
|
if (partner.isLocked()) {
|
||||||
local.complete1();
|
local.complete1();
|
||||||
partner.complete1();
|
partner.complete1();
|
||||||
if (!local.fitsInInventory() || !partner.fitsInInventory()) {
|
if (!local.fitsInInventory()) {
|
||||||
cancelTrade(c);
|
cancelTrade(c);
|
||||||
c.message("There is not enough inventory space to complete the trade.");
|
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.");
|
partner.getChr().message("There is not enough inventory space to complete the trade.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -224,13 +236,13 @@ public class MapleTrade {
|
|||||||
} else {
|
} else {
|
||||||
local.getChr().addMesosTraded(local.exchangeMeso);
|
local.getChr().addMesosTraded(local.exchangeMeso);
|
||||||
}
|
}
|
||||||
} else if (c.getTrade().getChr().getLevel() < 15) {
|
} else if (partner.getChr().getLevel() < 15) {
|
||||||
if (c.getMesosTraded() + c.getTrade().exchangeMeso > 1000000) {
|
if (partner.getChr().getMesosTraded() + partner.exchangeMeso > 1000000) {
|
||||||
cancelTrade(c);
|
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;
|
return;
|
||||||
} else {
|
} else {
|
||||||
c.addMesosTraded(local.exchangeMeso);
|
partner.getChr().addMesosTraded(partner.exchangeMeso);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogHelper.logTrade(local, partner);
|
LogHelper.logTrade(local, partner);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class MapleQuest {
|
|||||||
|
|
||||||
private static Map<Integer, MapleQuest> quests = new HashMap<>();
|
private static Map<Integer, MapleQuest> quests = new HashMap<>();
|
||||||
protected short infoNumber, id;
|
protected short infoNumber, id;
|
||||||
protected int timeLimit, timeLimit2;
|
protected int timeLimit;
|
||||||
protected String infoex;
|
protected String infoex;
|
||||||
protected Map<MapleQuestRequirementType, MapleQuestRequirement> startReqs = new EnumMap<>(MapleQuestRequirementType.class);
|
protected Map<MapleQuestRequirementType, MapleQuestRequirement> startReqs = new EnumMap<>(MapleQuestRequirementType.class);
|
||||||
protected Map<MapleQuestRequirementType, MapleQuestRequirement> completeReqs = new EnumMap<>(MapleQuestRequirementType.class);
|
protected Map<MapleQuestRequirementType, MapleQuestRequirement> completeReqs = new EnumMap<>(MapleQuestRequirementType.class);
|
||||||
@@ -57,20 +57,22 @@ public class MapleQuest {
|
|||||||
private boolean autoPreComplete, autoComplete;
|
private boolean autoPreComplete, autoComplete;
|
||||||
private boolean repeatable = false;
|
private boolean repeatable = false;
|
||||||
private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz"));
|
private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz"));
|
||||||
private static MapleData questInfo;
|
private static MapleData questInfo;
|
||||||
private static MapleData questAct;
|
private static MapleData questAct;
|
||||||
private static MapleData questReq;
|
private static MapleData questReq;
|
||||||
|
|
||||||
private MapleQuest(int id) {
|
private MapleQuest(int id) {
|
||||||
this.id = (short) id;
|
this.id = (short) id;
|
||||||
|
|
||||||
if(questInfo != null) {
|
if(questInfo != null) {
|
||||||
timeLimit = MapleDataTool.getInt("timeLimit", questInfo, 0);
|
MapleData reqData = questInfo.getChildByPath(String.valueOf(id));
|
||||||
timeLimit2 = MapleDataTool.getInt("timeLimit2", questInfo, 0);
|
|
||||||
autoStart = MapleDataTool.getInt("autoStart", questInfo, 0) == 1;
|
timeLimit = MapleDataTool.getInt("timeLimit", reqData, 0);
|
||||||
autoPreComplete = MapleDataTool.getInt("autoPreComplete", questInfo, 0) == 1;
|
timeLimit = Math.max(timeLimit, MapleDataTool.getInt("timeLimit2", reqData, 0)); // alas, nexon made we deal with 2 timeLimits
|
||||||
autoComplete = MapleDataTool.getInt("autoComplete", questInfo, 0) == 1;
|
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));
|
MapleData reqData = questReq.getChildByPath(String.valueOf(id));
|
||||||
if (reqData == null) {//most likely infoEx
|
if (reqData == null) {//most likely infoEx
|
||||||
@@ -84,7 +86,7 @@ public class MapleQuest {
|
|||||||
repeatable = true;
|
repeatable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
|
if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
|
||||||
infoNumber = (short) MapleDataTool.getInt(startReq, 0);
|
infoNumber = (short) MapleDataTool.getInt(startReq, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,11 +282,9 @@ public class MapleQuest {
|
|||||||
newStatus.setForfeited(c.getQuest(this).getForfeited());
|
newStatus.setForfeited(c.getQuest(this).getForfeited());
|
||||||
|
|
||||||
if (timeLimit > 0) {
|
if (timeLimit > 0) {
|
||||||
c.questTimeLimit(this, 30000);//timeLimit * 1000
|
c.questTimeLimit(this, timeLimit);
|
||||||
}
|
|
||||||
if (timeLimit2 > 0) {//=\
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.updateQuest(newStatus);
|
c.updateQuest(newStatus);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2337,16 +2337,18 @@ public class MaplePacketCreator {
|
|||||||
mplew.write(chr.getMarriageRing() != null ? 1 : 0);
|
mplew.write(chr.getMarriageRing() != null ? 1 : 0);
|
||||||
String guildName = "";
|
String guildName = "";
|
||||||
String allianceName = "";
|
String allianceName = "";
|
||||||
MapleGuildSummary gs = chr.getClient().getWorldServer().getGuildSummary(chr.getGuildId(), chr.getWorld());
|
if (chr.getGuildId() > 0) {
|
||||||
if (chr.getGuildId() > 0 && gs != null) {
|
MapleGuild mg = Server.getInstance().getGuild(chr.getGuildId());
|
||||||
guildName = gs.getName();
|
guildName = mg.getName();
|
||||||
MapleAlliance alliance = Server.getInstance().getAlliance(gs.getAllianceId());
|
|
||||||
|
MapleAlliance alliance = Server.getInstance().getAlliance(chr.getGuild().getAllianceId());
|
||||||
if (alliance != null) {
|
if (alliance != null) {
|
||||||
allianceName = alliance.getName();
|
allianceName = alliance.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mplew.writeMapleAsciiString(guildName);
|
mplew.writeMapleAsciiString(guildName);
|
||||||
mplew.writeMapleAsciiString(allianceName);
|
mplew.writeMapleAsciiString(allianceName); // does not seems to work
|
||||||
|
|
||||||
mplew.write(0);
|
mplew.write(0);
|
||||||
MaplePet[] pets = chr.getPets();
|
MaplePet[] pets = chr.getPets();
|
||||||
Item inv = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -114);
|
Item inv = chr.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -114);
|
||||||
|
|||||||
Reference in New Issue
Block a user