Turnabout on Character stats concurrency + Null remote IP patch

Cleared the concurrency conflicts that started occuring after the abstract character's listener code was set to run on new thread, potentally leading to several onStatChange mishaps.
Added a check for remoteHost being possibly null when opening a new session with the client.
This commit is contained in:
ronancpl
2019-04-23 11:14:40 -03:00
parent 1376c295e1
commit e18061ffaf
7 changed files with 48 additions and 42 deletions

View File

@@ -47,7 +47,6 @@ Missing features list:
--------------------------- ---------------------------
** Packet issues & advanced PQs ** ** Packet issues & advanced PQs **
- Mystic Doors (won't deploy players properly is some situations, only destination map matches). - Mystic Doors (won't deploy players properly is some situations, only destination map matches).
- Ariant Party Quest
- Nett's Pyramid Party Quest - Nett's Pyramid Party Quest
--------------------------- ---------------------------

View File

@@ -1,6 +1,7 @@
// Missing contents in HeavenMS (as of commit 311), compiled here thanks to --- // Missing contents in HeavenMS (as of commit 311), compiled here thanks to ---
Uncoded features: Uncoded features:
NX Format
Name Change Name Change
World transfer World transfer
MTS (v53) MTS (v53)

View File

@@ -1817,4 +1817,7 @@ Ajustado drops de mobs, agora sendo buscado na DB.
Ajustado diversas mecânicas da AriantPQ, tais como update visual da pontuação de jogadores (ao dropar itens, ganhar itens, acessar mapa de evento), pontos de batalha persistindo na DB, etc. Ajustado diversas mecânicas da AriantPQ, tais como update visual da pontuação de jogadores (ao dropar itens, ganhar itens, acessar mapa de evento), pontos de batalha persistindo na DB, etc.
21 Abril 2019, 21 Abril 2019,
Adicionado debug de packets descrito pelo Atoot. Adicionado debug de packets descrito pelo Atoot.Adicionado debug de packets descrito pelo Atoot.
22 Abril 2019,
Revisado refatoração recente em acesso a valores de stats de jogadores levando a inconsistência nos valores dos mesmos ao colocá-los para rodar em uma nova thread sem proteção concorrente.

View File

@@ -213,36 +213,15 @@ public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMaple
} }
private void dispatchHpChanged(final int oldHp) { private void dispatchHpChanged(final int oldHp) {
Runnable r = new Runnable() { // thanks BHB (BHB88) for detecting a deadlock case within player stats. listener.onHpChanged(oldHp);
@Override
public void run() {
listener.onHpChanged(oldHp);
}
};
map.registerCharacterStatUpdate(r);
} }
private void dispatchHpmpPoolUpdated() { private void dispatchHpmpPoolUpdated() {
Runnable r = new Runnable() { listener.onHpmpPoolUpdate();
@Override
public void run() {
listener.onHpmpPoolUpdate();
}
};
map.registerCharacterStatUpdate(r);
} }
private void dispatchStatPoolUpdateAnnounced() { private void dispatchStatPoolUpdateAnnounced() {
Runnable r = new Runnable() { listener.onAnnounceStatPoolUpdate();
@Override
public void run() {
listener.onAnnounceStatPoolUpdate();
}
};
map.registerCharacterStatUpdate(r);
} }
protected void setHp(int newHp) { protected void setHp(int newHp) {

View File

@@ -8590,14 +8590,22 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
} }
} }
} }
final boolean chrDied = playerDied;
Runnable r = new Runnable() {
@Override
public void run() {
updatePartyMemberHP(); // thanks BHB (BHB88) for detecting a deadlock case within player stats.
updatePartyMemberHP(); if (chrDied) {
playerDead();
if (playerDied) { } else {
playerDead(); checkBerserk(isHidden());
} else { }
checkBerserk(isHidden()); }
} };
map.registerCharacterStatUpdate(r);
} }
private Pair<MapleStat, Integer> calcHpRatioUpdate(int newHp, int oldHp) { private Pair<MapleStat, Integer> calcHpRatioUpdate(int newHp, int oldHp) {

View File

@@ -106,7 +106,18 @@ public class MapleServerHandler extends IoHandlerAdapter {
@Override @Override
public void sessionOpened(IoSession session) { public void sessionOpened(IoSession session) {
session.setAttribute(MapleClient.CLIENT_REMOTE_ADDRESS, ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress()); String remoteHost;
try {
remoteHost = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
if (remoteHost == null) {
remoteHost = "null";
}
} catch (NullPointerException npe) { // thanks Agassy, Alchemist for pointing out possibility of remoteHost = null.
remoteHost = "null";
}
session.setAttribute(MapleClient.CLIENT_REMOTE_ADDRESS, remoteHost);
if (!Server.getInstance().isOnline()) { if (!Server.getInstance().isOnline()) {
MapleSessionCoordinator.getInstance().closeSession(session, true); MapleSessionCoordinator.getInstance().closeSession(session, true);

View File

@@ -63,16 +63,21 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
@Override @Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
String remoteHost = getRemoteIp(c.getSession()); String remoteHost = getRemoteIp(c.getSession());
if (remoteHost.startsWith("127.")) { if (!remoteHost.contentEquals("null")) {
if (!ServerConstants.LOCALSERVER) { // thanks Mills for noting HOST can also have a field named "localhost" if (remoteHost.startsWith("127.")) {
c.announce(MaplePacketCreator.getLoginFailed(13)); // cannot login as localhost if it's not a local server if (!ServerConstants.LOCALSERVER) { // thanks Mills for noting HOST can also have a field named "localhost"
return; c.announce(MaplePacketCreator.getLoginFailed(13)); // cannot login as localhost if it's not a local server
return;
}
} else {
if (ServerConstants.LOCALSERVER) {
c.announce(MaplePacketCreator.getLoginFailed(13)); // cannot login as non-localhost if it's a local server
return;
}
} }
} else { } else {
if (ServerConstants.LOCALSERVER) { c.announce(MaplePacketCreator.getLoginFailed(14)); // thanks Alchemist for noting remoteHost could be null
c.announce(MaplePacketCreator.getLoginFailed(13)); // cannot login as non-localhost if it's a local server return;
return;
}
} }
String login = slea.readMapleAsciiString(); String login = slea.readMapleAsciiString();