Return map & MaplePacketEncoder & Quest status patch

Fixed null pointer issue when trying to use return scroll on maps such as Mu Lung.
Fixed a critical deadlock issue with MaplePacketEncoder.
Fixed a critical DB leak regarding player's quest status.
This commit is contained in:
ronancpl
2018-06-08 13:21:03 -03:00
parent cdac59326a
commit 0b8d3a0b2b
13 changed files with 218 additions and 35 deletions

View File

@@ -2032,6 +2032,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setInt(1, cid);
ps.executeUpdate();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM queststatus WHERE characterid = ?")) {
ps.setInt(1, cid);
ps.executeUpdate();
}
}
private void deleteWhereCharacterId(Connection con, String sql) throws SQLException {
@@ -3717,7 +3722,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
MapleBuffStatValueHolder mbsvh = effects.get(statup.getKey());
MapleBuffStatValueHolder statMbsvh = statup.getValue();
if(mbsvh == null || mbsvh.value < statMbsvh.value || (mbsvh.value == statMbsvh.value && mbsvh.effect.getStatups().size() < statMbsvh.effect.getStatups().size())) {
if(mbsvh == null || mbsvh.value < statMbsvh.value || (mbsvh.value == statMbsvh.value && mbsvh.effect.getStatups().size() <= statMbsvh.effect.getStatups().size())) {
toDeploy.put(statup.getKey(), statMbsvh);
} else {
if(!isSingletonStatup(statup.getKey())) {
@@ -5969,7 +5974,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
rs = ps.executeQuery();
Map<Integer, MapleQuestStatus> loadedQuestStatus = new LinkedHashMap<>();
while (rs.next()) {
MapleQuest q = MapleQuest.getInstance(rs.getShort("quest"));
MapleQuestStatus status = new MapleQuestStatus(q, MapleQuestStatus.Status.getById(rs.getInt("status")));
@@ -6011,9 +6015,11 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
/*
for(MapleQuestStatus mqs : loadedQuestStatus.values()) {
mqs.resetUpdated();
}
*/
loadedQuestStatus.clear();
@@ -7071,8 +7077,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
synchronized (quests) {
for (MapleQuestStatus q : quests.values()) {
if(!q.wasUpdated()) continue;
ps.setInt(2, q.getQuest().getId());
ps.setInt(3, q.getStatus().getId());
ps.setInt(4, (int) (q.getCompletionTime() / 1000));

View File

@@ -106,6 +106,7 @@ public class MapleClient {
private byte gender = -1;
private boolean disconnecting = false;
private final Lock lock = new MonitoredReentrantLock(MonitoredLockType.CLIENT, true);
private final Lock encoderLock = new MonitoredReentrantLock(MonitoredLockType.CLIENT, true);
private static final Lock loginLock = new MonitoredReentrantLock(MonitoredLockType.CLIENT, true);
private int votePoints;
private int voteTime = -1;
@@ -1142,6 +1143,14 @@ public class MapleClient {
public void unlockClient() {
lock.unlock();
}
public void lockEncoder() {
encoderLock.lock();
}
public void unlockEncoder() {
encoderLock.unlock();
}
private static class CharNameAndId {

View File

@@ -60,7 +60,7 @@ public class MapleQuestStatus {
}
private short questID;
private Status status;
private boolean updated;
//private boolean updated; //maybe this can be of use for someone?
private final Map<Integer, String> progress = new LinkedHashMap<Integer, String>();
private final List<Integer> medalProgress = new LinkedList<Integer>();
private int npc;
@@ -73,7 +73,7 @@ public class MapleQuestStatus {
this.setStatus(status);
this.completionTime = System.currentTimeMillis();
this.expirationTime = 0;
this.updated = true;
//this.updated = true;
if (status == Status.STARTED)
registerMobs();
}
@@ -84,7 +84,7 @@ public class MapleQuestStatus {
this.setNpc(npc);
this.completionTime = System.currentTimeMillis();
this.expirationTime = 0;
this.updated = true;
//this.updated = true;
if (status == Status.STARTED) {
registerMobs();
}
@@ -106,17 +106,19 @@ public class MapleQuestStatus {
this.status = status;
}
/*
public boolean wasUpdated() {
return updated;
}
public void setUpdated() {
private void setUpdated() {
this.updated = true;
}
public void resetUpdated() {
this.updated = false;
}
*/
public int getNpc() {
return npc;
@@ -130,13 +132,13 @@ public class MapleQuestStatus {
for (int i : MapleQuest.getInstance(questID).getRelevantMobs()) {
progress.put(i, "000");
}
this.setUpdated();
//this.setUpdated();
}
public boolean addMedalMap(int mapid) {
if (medalProgress.contains(mapid)) return false;
medalProgress.add(mapid);
this.setUpdated();
//this.setUpdated();
return true;
}
@@ -153,7 +155,7 @@ public class MapleQuestStatus {
int current = Integer.parseInt(progress.get(id));
String str = StringUtil.getLeftPaddedStr(Integer.toString(current + 1), '0', 3);
progress.put(id, str);
this.setUpdated();
//this.setUpdated();
return true;
}
return false;
@@ -161,7 +163,7 @@ public class MapleQuestStatus {
public void setProgress(int id, String pr) {
progress.put(id, pr);
this.setUpdated();
//this.setUpdated();
}
public boolean madeProgress() {
@@ -221,7 +223,7 @@ public class MapleQuestStatus {
public void setInfo(String newInfo) {
progress.put(0, newInfo);
this.setUpdated();
//this.setUpdated();
}
public void setForfeited(int forfeited) {

View File

@@ -110,7 +110,7 @@ public class ServerConstants {
public static final int MAX_EVENT_LEVELS = 8; //Event has different levels of rewarding system.
public static final long BLOCK_NPC_RACE_CONDT = (long)(0.5 * 1000); //Time the player client must wait before reopening a conversation with an NPC.
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //Time the pet must wait before trying to pick items up.
public static final int TOT_MOB_QUEST_REQUIREMENT = 0; //Overwrites old 999-mobs requirement for the ToT questline with new requirement value, set 0 for default.
public static final int TOT_MOB_QUEST_REQUIREMENT = 77; //Overwrites old 999-mobs requirement for the ToT questline with new requirement value, set 0 for default.
public static final int MOB_REACTOR_REFRESH_TIME = 30 * 1000; //Overwrites refresh time for those reactors oriented to inflict damage to bosses (Ice Queen, Riche), set 0 for default.
//Dangling Items/Locks Configuration

View File

@@ -22,7 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package net.mina;
import client.MapleClient;
import java.util.concurrent.locks.Lock;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoder;
@@ -36,7 +35,7 @@ public class MaplePacketEncoder implements ProtocolEncoder {
final MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
try {
client.lockClient();
client.lockEncoder();
try {
final MapleAESOFB send_crypto = client.getSendCrypto();
final byte[] input = (byte[]) message;
@@ -52,7 +51,7 @@ public class MaplePacketEncoder implements ProtocolEncoder {
out.write(IoBuffer.wrap(ret));
} finally {
client.unlockClient();
client.unlockEncoder();
}
// System.arraycopy(unencrypted, 0, ret, 4, unencrypted.length);
// out.write(ByteBuffer.wrap(ret));

View File

@@ -44,6 +44,7 @@ public final class ItemPickupHandler extends AbstractMaplePacketHandler {
int oid = slea.readInt();
MapleCharacter chr = c.getPlayer();
MapleMapObject ob = chr.getMap().getMapObject(oid);
if(ob == null) return;
Point charPos = chr.getPosition();
Point obPos = ob.getPosition();

View File

@@ -1037,26 +1037,26 @@ public class MapleStatEffect {
int seconds = localDuration / 1000;
MapleMount givemount = null;
if (isMonsterRiding()) {
int ridingLevel = 0;
int ridingMountId = 0;
Item mount = applyfrom.getInventory(MapleInventoryType.EQUIPPED).getItem((short) -18);
if (mount != null) {
ridingLevel = mount.getItemId();
ridingMountId = mount.getItemId();
}
if (sourceid == Corsair.BATTLE_SHIP) {
ridingLevel = 1932000;
ridingMountId = 1932000;
} else if (sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP) {
ridingLevel = 1932000 + applyto.getSkillLevel(sourceid);
ridingMountId = 1932000 + applyto.getSkillLevel(sourceid);
} else if (sourceid == Beginner.YETI_MOUNT1 || sourceid == Noblesse.YETI_MOUNT1 || sourceid == Legend.YETI_MOUNT1) {
ridingLevel = 1932003;
ridingMountId = 1932003;
} else if (sourceid == Beginner.YETI_MOUNT2 || sourceid == Noblesse.YETI_MOUNT2 || sourceid == Legend.YETI_MOUNT2) {
ridingLevel = 1932004;
ridingMountId = 1932004;
} else if (sourceid == Beginner.WITCH_BROOMSTICK || sourceid == Noblesse.WITCH_BROOMSTICK || sourceid == Legend.WITCH_BROOMSTICK) {
ridingLevel = 1932005;
ridingMountId = 1932005;
} else if (sourceid == Beginner.BALROG_MOUNT || sourceid == Noblesse.BALROG_MOUNT || sourceid == Legend.BALROG_MOUNT) {
ridingLevel = 1932010;
ridingMountId = 1932010;
} else {
if (applyto.getMount() == null) {
applyto.mount(ridingLevel, sourceid);
applyto.mount(ridingMountId, sourceid);
}
applyto.getClient().getWorldServer().registerMountHunger(applyto);
@@ -1077,7 +1077,7 @@ public class MapleStatEffect {
givemount = applyto.getMount();
}
localDuration = sourceid;
localsourceid = ridingLevel;
localsourceid = ridingMountId;
localstatups = Collections.singletonList(new Pair<>(MapleBuffStat.MONSTER_RIDING, 0));
} else if (isSkillMorph()) {
localstatups = Collections.singletonList(new Pair<>(MapleBuffStat.MORPH, getMorph(applyto)));

View File

@@ -257,6 +257,7 @@ public class MapleMap {
}
public MapleMap getReturnMap() {
if(returnMapId == 999999999) return this;
return Server.getInstance().getWorld(world).getChannel(channel).getMapFactory().getMap(returnMapId);
}