After-quest messages & MCPQ patch + Scroll Generator

Fixed an issue within Restore Lost Item functionality.
New custom NPC: scroll generator. Trades a scroll for bundles of common miscellaneous items.
Revised several lock-acquiring flow scenarios.
Fixed pet autopot taking out "negative" amounts from inventory.
Added zombify and confuse diseases dispellable by all-cure potions.
Patched after-quest messages sometimes allowing player movement, that shouldn't be available until the message box is closed.
Reviewed multiclient component, now also evaluating passed HWID alongside remote IP.
Fixed missing info about questlines on skillbook announcer NPC after recent updates.
Fixed some Aran skills not applying MP consume properly.
Cleared a few issues within MCPQ collectable solo/party items and skills.
Improved response time on scroll generator by adding a cache for scroll requirements.
This commit is contained in:
ronancpl
2019-11-14 00:49:15 -03:00
parent d9f87f18a1
commit 6d57eb1033
59 changed files with 894 additions and 389 deletions

View File

@@ -242,14 +242,14 @@ public class MapleServerHandler extends IoHandlerAdapter {
long timeNow = Server.getInstance().getCurrentTime();
long timeThen = timeNow - 15000;
Set<MapleClient> pingClients = new HashSet<>();
idleLock.lock();
try {
for(Entry<MapleClient, Long> mc : idleSessions.entrySet()) {
if(timeNow - mc.getValue() >= 15000) {
mc.getKey().testPing(timeThen);
pingClients.add(mc.getKey());
}
}
idleSessions.clear();
if(!tempIdleSessions.isEmpty()) {
@@ -267,6 +267,10 @@ public class MapleServerHandler extends IoHandlerAdapter {
} finally {
idleLock.unlock();
}
for(MapleClient c : pingClients) {
c.testPing(timeThen);
}
}
private void idleManagerTask() {

View File

@@ -33,7 +33,6 @@ import tools.HexTool;
import tools.MapleAESOFB;
import tools.data.input.ByteArrayByteStream;
import tools.data.input.GenericLittleEndianAccessor;
import net.opcodes.RecvOpcode;
import tools.FilePrinter;
public class MaplePacketDecoder extends CumulativeProtocolDecoder {

View File

@@ -106,7 +106,6 @@ import tools.AutoJCE;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.Pair;
import org.apache.mina.core.session.IoSession;
public class Server {
@@ -1730,12 +1729,12 @@ public class Server {
}
}
private static String getRemoteIp(IoSession session) {
return MapleSessionCoordinator.getSessionRemoteAddress(session);
private static String getRemoteHost(MapleClient client) {
return MapleSessionCoordinator.getSessionRemoteHost(client.getSession());
}
public void setCharacteridInTransition(IoSession session, int charId) {
String remoteIp = getRemoteIp(session);
public void setCharacteridInTransition(MapleClient client, int charId) {
String remoteIp = getRemoteHost(client);
lgnWLock.lock();
try {
@@ -1745,12 +1744,12 @@ public class Server {
}
}
public boolean validateCharacteridInTransition(IoSession session, int charId) {
public boolean validateCharacteridInTransition(MapleClient client, int charId) {
if (!YamlConfig.config.server.USE_IP_VALIDATION) {
return true;
}
String remoteIp = getRemoteIp(session);
String remoteIp = getRemoteHost(client);
lgnWLock.lock();
try {
@@ -1761,12 +1760,12 @@ public class Server {
}
}
public Integer freeCharacteridInTransition(IoSession session) {
public Integer freeCharacteridInTransition(MapleClient client) {
if (!YamlConfig.config.server.USE_IP_VALIDATION) {
return null;
}
String remoteIp = getRemoteIp(session);
String remoteIp = getRemoteHost(client);
lgnWLock.lock();
try {
@@ -1776,13 +1775,13 @@ public class Server {
}
}
public boolean hasCharacteridInTransition(IoSession session) {
public boolean hasCharacteridInTransition(MapleClient client) {
if (!YamlConfig.config.server.USE_IP_VALIDATION) {
return true;
}
String remoteIp = getRemoteIp(session);
String remoteIp = getRemoteHost(client);
lgnRLock.lock();
try {
return transitioningChars.containsKey(remoteIp);

View File

@@ -375,7 +375,7 @@ public final class Channel {
for (Integer cid : playersAway) {
MapleCharacter chr = wserv.getPlayerStorage().getCharacterById(cid);
if (chr != null && chr.isLoggedin()) {
chr.getClient().disconnect(true, false);
chr.getClient().forceDisconnect();
}
}
}

View File

@@ -113,10 +113,11 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
public boolean ranged, magic;
public int speed = 4;
public Point position = new Point();
public MapleStatEffect getAttackEffect(MapleCharacter chr, Skill theSkill) {
Skill mySkill = theSkill;
if (mySkill == null) {
mySkill = SkillFactory.getSkill(GameConstants.getHiddenSkill(skill));
mySkill = SkillFactory.getSkill(skill);
}
int skillLevel = chr.getSkillLevel(mySkill);
@@ -149,8 +150,8 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
return;
}
if (attack.skill != 0) {
theSkill = SkillFactory.getSkill(GameConstants.getHiddenSkill(attack.skill)); //returns back the skill id if its not a hidden skill so we are gucci
attackEffect = attack.getAttackEffect(player, theSkill);
theSkill = SkillFactory.getSkill(attack.skill); // thanks Conrad for noticing some Aran skills not consuming MP
attackEffect = attack.getAttackEffect(player, theSkill); //returns back the player's attack effect so we are gucci
if (attackEffect == null) {
player.announce(MaplePacketCreator.enableActions());
return;

View File

@@ -37,6 +37,12 @@ public final class CancelChairHandler extends AbstractMaplePacketHandler {
return;
}
mc.sitChair(id);
if (c.tryacquireClient()) {
try {
mc.sitChair(id);
} finally {
c.releaseClient();
}
}
}
}

View File

@@ -40,7 +40,6 @@ import server.CashShop;
import server.CashShop.CashItem;
import server.CashShop.CashItemFactory;
import client.inventory.manipulator.MapleInventoryManipulator;
import constants.net.ServerConstants;
import server.MapleItemInformationProvider;
import tools.FilePrinter;
import tools.MaplePacketCreator;

View File

@@ -62,7 +62,6 @@ public final class ChangeMapHandler extends AbstractMaplePacketHandler {
String[] socket = c.getChannelServer().getIP().split(":");
chr.getCashShop().open(false);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
chr.setSessionTransitionState();
try {
c.announce(MaplePacketCreator.getChannelChange(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1])));

View File

@@ -126,13 +126,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
}
MapleCharacter player = wserv.getPlayerStorage().getCharacterById(cid);
boolean newcomer = false;
IoSession session = c.getSession();
if (!server.validateCharacteridInTransition(session, cid)) {
c.disconnect(true, false);
return;
}
String remoteHwid;
if (player == null) {
@@ -141,25 +135,37 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
c.disconnect(true, false);
return;
}
} else {
remoteHwid = player.getClient().getHWID();
}
int hwidLen = remoteHwid.length();
session.setAttribute(MapleClient.CLIENT_HWID, remoteHwid);
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, remoteHwid.substring(hwidLen - 8, hwidLen));
c.setHWID(remoteHwid);
if (!server.validateCharacteridInTransition(c, cid)) {
c.disconnect(true, false);
return;
}
boolean newcomer = false;
if (player == null) {
try {
player = MapleCharacter.loadCharFromDB(cid, c, true);
newcomer = true;
} catch (SQLException e) {
e.printStackTrace();
}
} else {
remoteHwid = player.getClient().getHWID();
if (player == null) { //If you are still getting null here then please just uninstall the game >.>, we dont need you fucking with the logs
c.disconnect(true, false);
return;
}
}
if (player == null) { //If you are still getting null here then please just uninstall the game >.>, we dont need you fucking with the logs
c.disconnect(true, false);
return;
}
c.setPlayer(player);
c.setAccID(player.getAccountID());
boolean allowLogin = true;
/* is this check really necessary?
@@ -211,11 +217,6 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
player.newClient(c);
}
int hwidLen = remoteHwid.length();
session.setAttribute(MapleClient.CLIENT_HWID, remoteHwid);
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, remoteHwid.substring(hwidLen - 8, hwidLen));
c.setHWID(remoteHwid);
cserv.addPlayer(player);
wserv.addPlayer(player);
player.setEnteredChannelWorld();
@@ -386,7 +387,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
player.announceBattleshipHp();
}
}
player.buffExpireTask();
player.diseaseExpireTask();
player.skillCooldownTask();

View File

@@ -33,7 +33,6 @@ import client.MapleCharacter;
import client.MapleClient;
import client.Skill;
import client.SkillFactory;
import constants.net.ServerConstants;
import constants.skills.Brawler;
import constants.skills.Corsair;
import constants.skills.DarkKnight;

View File

@@ -635,11 +635,11 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
position = it.getPosition();
}
}
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.CASH, position, (short) 1, true, false);
} finally {
cashInv.unlockInventory();
}
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.CASH, position, (short) 1, true, false);
}
private static boolean getIncubatedItem(MapleClient c, int id) {

View File

@@ -37,6 +37,12 @@ public final class UseChairHandler extends AbstractMaplePacketHandler {
return;
}
c.getPlayer().sitChair(itemId);
if (c.tryacquireClient()) {
try {
c.getPlayer().sitChair(itemId);
} finally {
c.releaseClient();
}
}
}
}

View File

@@ -53,7 +53,7 @@ public final class UseItemHandler extends AbstractMaplePacketHandler {
int itemId = slea.readInt();
Item toUse = chr.getInventory(MapleInventoryType.USE).getItem(slot);
if (toUse != null && toUse.getQuantity() > 0 && toUse.getItemId() == itemId) {
if (itemId == 2022178 || itemId == 2050004) {
if (itemId == 2050004) {
chr.dispelDebuffs();
remove(c, slot);
return;

View File

@@ -31,7 +31,6 @@ import constants.game.ExpTable;
import net.AbstractMaplePacketHandler;
import client.inventory.manipulator.MapleInventoryManipulator;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.data.input.SeekableLittleEndianAccessor;
/**

View File

@@ -58,20 +58,18 @@ public final class WeddingHandler extends AbstractMaplePacketHandler {
MapleInventoryType type = ItemConstants.getInventoryType(itemid);
MapleInventory chrInv = chr.getInventory(type);
Item newItem = null;
chrInv.lockInventory();
try {
Item item = chrInv.getItem((byte) slot);
if (item != null) {
if (!item.isUntradeable()) {
if (itemid == item.getItemId() && quantity <= item.getQuantity()) {
Item newItem = item.copy();
newItem = item.copy();
marriage.addGiftItem(groomWishlist, newItem);
MapleInventoryManipulator.removeFromSlot(c, type, slot, quantity, false, false);
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) chr.saveCharToDB(false);
marriage.saveGiftItemsToDb(c, groomWishlist, cid);
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(newItem);
marriage.setIntProperty(groomWishlistProp, giftCount + 1);
@@ -84,6 +82,11 @@ public final class WeddingHandler extends AbstractMaplePacketHandler {
} finally {
chrInv.unlockInventory();
}
if (newItem != null) {
if (YamlConfig.config.server.USE_ENFORCE_MERCHANT_SAVE) chr.saveCharToDB(false);
marriage.saveGiftItemsToDb(c, groomWishlist, cid);
}
} else {
c.announce(Wedding.OnWeddingGiftResult((byte) 0xE, marriage.getWishlistItems(groomWishlist), null));
}

View File

@@ -22,7 +22,6 @@ package net.server.coordinator.matchchecker;
import client.MapleCharacter;
import net.server.PlayerStorage;
import net.server.Server;
import net.server.coordinator.matchchecker.AbstractMatchCheckerListener;
import net.server.coordinator.matchchecker.MatchCheckerListenerFactory.MatchCheckerType;
import net.server.world.World;
import java.util.Collections;
@@ -260,19 +259,19 @@ public class MapleMatchCheckerCoordinator {
}
}
private void createMatchConfirmationInternal(MatchCheckerType matchType, int world, int leaderCid, AbstractMatchCheckerListener leaderListener, Set<Integer> players, String message) {
private MapleMatchCheckingElement createMatchConfirmationInternal(MatchCheckerType matchType, int world, int leaderCid, AbstractMatchCheckerListener leaderListener, Set<Integer> players, String message) {
MapleMatchCheckingElement mmce = new MapleMatchCheckingElement(matchType, leaderCid, world, leaderListener, players, message);
for (Integer cid : players) {
matchEntries.put(cid, mmce);
}
mmce.dispatchMatchCreated();
acceptMatchElement(mmce, leaderCid);
return mmce;
}
public boolean createMatchConfirmation(MatchCheckerType matchType, int world, int leaderCid, Set<Integer> players, String message) {
MapleMatchCheckingElement mmce = null;
try {
semaphorePool.acquire();
try {
@@ -280,8 +279,7 @@ public class MapleMatchCheckerCoordinator {
try {
if (isMatchingAvailable(players)) {
AbstractMatchCheckerListener leaderListener = matchType.getListener();
createMatchConfirmationInternal(matchType, world, leaderCid, leaderListener, players, message);
return true;
mmce = createMatchConfirmationInternal(matchType, world, leaderCid, leaderListener, players, message);
} else {
reenablePlayerMatching(players);
}
@@ -296,7 +294,12 @@ public class MapleMatchCheckerCoordinator {
ie.printStackTrace();
}
return false;
if (mmce != null) {
mmce.dispatchMatchCreated();
return true;
} else {
return false;
}
}
private void disposeMatchElement(MapleMatchCheckingElement mmce) {
@@ -320,16 +323,12 @@ public class MapleMatchCheckerCoordinator {
if (mmce.acceptEntry(cid)) {
unpoolMatchPlayer(cid);
disposeMatchElement(mmce);
mmce.dispatchMatchResult(true);
}
}
private void denyMatchElement(MapleMatchCheckingElement mmce, int cid) {
unpoolMatchPlayer(cid);
disposeMatchElement(mmce);
mmce.dispatchMatchResult(false);
}
private void dismissMatchElement(MapleMatchCheckingElement mmce, int cid) {
@@ -337,35 +336,32 @@ public class MapleMatchCheckerCoordinator {
unpoolMatchPlayer(cid);
disposeMatchElement(mmce);
mmce.dispatchMatchDismissed();
}
public boolean answerMatchConfirmation(int cid, boolean accept) {
MapleMatchCheckingElement mmce = null;
try {
semaphorePool.acquire();
try {
while (matchEntries.containsKey(cid)) {
if (poolMatchPlayer(cid)) {
try {
MapleMatchCheckingElement mmce = matchEntries.get(cid);
mmce = matchEntries.get(cid);
if (mmce != null) {
synchronized (mmce) {
if (!mmce.isMatchActive()) { // thanks Alex (CanIGetaPR) for noticing that exploiters could stall on match checking
matchEntries.remove(cid);
return false;
}
if (accept) {
acceptMatchElement(mmce, cid);
mmce = null;
} else {
denyMatchElement(mmce, cid);
matchEntries.remove(cid);
if (accept) {
acceptMatchElement(mmce, cid);
} else {
denyMatchElement(mmce, cid);
matchEntries.remove(cid);
}
}
}
return true;
}
} finally {
unpoolMatchPlayer(cid);
@@ -379,26 +375,30 @@ public class MapleMatchCheckerCoordinator {
ie.printStackTrace();
}
if (mmce != null) {
mmce.dispatchMatchResult(accept);
}
return false;
}
public boolean dismissMatchConfirmation(int cid) {
MapleMatchCheckingElement mmce = null;
try {
semaphorePool.acquire();
try {
while (matchEntries.containsKey(cid)) {
if (poolMatchPlayer(cid)) {
try {
MapleMatchCheckingElement mmce = matchEntries.get(cid);
mmce = matchEntries.get(cid);
if (mmce != null) {
synchronized (mmce) {
if (!mmce.isMatchActive()) {
return false;
mmce = null;
} else {
dismissMatchElement(mmce, cid);
}
dismissMatchElement(mmce, cid);
return true;
}
}
} finally {
@@ -413,7 +413,12 @@ public class MapleMatchCheckerCoordinator {
ie.printStackTrace();
}
return false;
if (mmce != null) {
mmce.dispatchMatchDismissed();
return true;
} else {
return false;
}
}
}

View File

@@ -224,6 +224,16 @@ public class MapleSessionCoordinator {
public static String getSessionRemoteAddress(IoSession session) {
return (String) session.getAttribute(MapleClient.CLIENT_REMOTE_ADDRESS);
}
public static String getSessionRemoteHost(IoSession session) {
String nibbleHwid = (String) session.getAttribute(MapleClient.CLIENT_NIBBLEHWID);
if (nibbleHwid != null) {
return getSessionRemoteAddress(session) + "-" + nibbleHwid;
} else {
return getSessionRemoteAddress(session);
}
}
private static MapleClient getSessionClient(IoSession session) {
return (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
@@ -246,7 +256,7 @@ public class MapleSessionCoordinator {
public boolean canStartLoginSession(IoSession session) {
if (!YamlConfig.config.server.DETERRED_MULTICLIENT) return true;
String remoteHost = getSessionRemoteAddress(session);
String remoteHost = getSessionRemoteHost(session);
Lock lock = getCoodinatorLock(remoteHost);
try {
@@ -306,7 +316,9 @@ public class MapleSessionCoordinator {
}
public void closeLoginSession(IoSession session) {
String remoteHost = getSessionRemoteAddress(session);
String nibbleHwid = (String) session.removeAttribute(MapleClient.CLIENT_NIBBLEHWID);
String remoteHost = getSessionRemoteHost(session);
Set<IoSession> lrh = loginRemoteHosts.get(remoteHost);
if (lrh != null) {
lrh.remove(session);
@@ -314,8 +326,7 @@ public class MapleSessionCoordinator {
loginRemoteHosts.remove(remoteHost);
}
}
String nibbleHwid = (String) session.removeAttribute(MapleClient.CLIENT_NIBBLEHWID);
if (nibbleHwid != null) {
onlineRemoteHwids.remove(nibbleHwid);
@@ -337,7 +348,7 @@ public class MapleSessionCoordinator {
return AntiMulticlientResult.SUCCESS;
}
String remoteHost = getSessionRemoteAddress(session);
String remoteHost = getSessionRemoteHost(session);
Lock lock = getCoodinatorLock(remoteHost);
try {
@@ -403,9 +414,10 @@ public class MapleSessionCoordinator {
}
public AntiMulticlientResult attemptGameSession(IoSession session, int accountId, String remoteHwid) {
String remoteHost = getSessionRemoteAddress(session);
String remoteHost = getSessionRemoteHost(session);
if (!YamlConfig.config.server.DETERRED_MULTICLIENT) {
associateRemoteHostHwid(remoteHost, remoteHwid);
associateRemoteHostHwid(getSessionRemoteAddress(session), remoteHwid); // no HWID information on the loggedin newcomer session...
return AntiMulticlientResult.SUCCESS;
}
@@ -451,6 +463,7 @@ public class MapleSessionCoordinator {
// updated session CLIENT_HWID attribute will be set when the player log in the game
onlineRemoteHwids.add(remoteHwid);
associateRemoteHostHwid(remoteHost, remoteHwid);
associateRemoteHostHwid(getSessionRemoteAddress(session), remoteHwid);
associateHwidAccountIfAbsent(remoteHwid, accountId);
return AntiMulticlientResult.SUCCESS;
@@ -486,7 +499,7 @@ public class MapleSessionCoordinator {
}
MapleClient client = new MapleClient(null, null, session);
Integer cid = Server.getInstance().freeCharacteridInTransition(session);
Integer cid = Server.getInstance().freeCharacteridInTransition(client);
if (cid != null) {
try {
client.setAccID(MapleCharacter.loadCharFromDB(cid, client, false).getAccountID());
@@ -535,7 +548,7 @@ public class MapleSessionCoordinator {
}
public String getGameSessionHwid(IoSession session) {
String remoteHost = getSessionRemoteAddress(session);
String remoteHost = getSessionRemoteHost(session);
return cachedHostHwids.get(remoteHost);
}

View File

@@ -101,8 +101,7 @@ public final class CharSelectedHandler extends AbstractMaplePacketHandler {
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
c.setCharacterOnSessionTransitionState(charId);
try {
c.announce(MaplePacketCreator.getServerIP(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1]), charId));

View File

@@ -84,8 +84,7 @@ public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
c.setCharacterOnSessionTransitionState(charId);
try {
c.announce(MaplePacketCreator.getServerIP(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1]), charId));

View File

@@ -86,8 +86,7 @@ public final class RegisterPicHandler extends AbstractMaplePacketHandler {
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
c.setCharacterOnSessionTransitionState(charId);
try {
c.announce(MaplePacketCreator.getServerIP(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1]), charId));

View File

@@ -89,8 +89,7 @@ public final class ViewAllCharRegisterPicHandler extends AbstractMaplePacketHand
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
c.setCharacterOnSessionTransitionState(charId);
try {
c.announce(MaplePacketCreator.getServerIP(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1]), charId));

View File

@@ -112,8 +112,7 @@ public final class ViewAllCharSelectedHandler extends AbstractMaplePacketHandler
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
c.setCharacterOnSessionTransitionState(charId);
try {
c.announce(MaplePacketCreator.getServerIP(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1]), charId));

View File

@@ -90,8 +90,7 @@ public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandle
}
server.unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
server.setCharacteridInTransition(session, charId);
c.setCharacterOnSessionTransitionState(charId);
try {
c.announce(MaplePacketCreator.getServerIP(InetAddress.getByName(socket[0]), Integer.parseInt(socket[1]), charId));

View File

@@ -356,7 +356,7 @@ public class MapleParty {
party = player.getWorldServer().createParty(partyplayer);
player.setParty(party);
player.setMPC(partyplayer);
player.getMap().addPartyMember(player);
player.getMap().addPartyMember(player, party.getId());
player.silentPartyUpdate();
player.updatePartySearchAvailability(false);
@@ -383,7 +383,7 @@ public class MapleParty {
if (party != null) {
if (party.getMembers().size() < 6) {
MaplePartyCharacter partyplayer = new MaplePartyCharacter(player);
player.getMap().addPartyMember(player);
player.getMap().addPartyMember(player, party.getId());
world.updateParty(party.getId(), PartyOperation.JOIN, partyplayer);
player.receivePartyMemberHP();
@@ -433,7 +433,7 @@ public class MapleParty {
} else {
MapleMap map = player.getMap();
if (map != null) {
map.removePartyMember(player);
map.removePartyMember(player, party.getId());
}
MonsterCarnival mcpq = player.getMonsterCarnival();
@@ -472,7 +472,7 @@ public class MapleParty {
List<MapleCharacter> partyMembers = emc.getPartyMembersOnline();
MapleMap map = emc.getMap();
if(map != null) map.removePartyMember(emc);
if(map != null) map.removePartyMember(emc, party.getId());
MonsterCarnival mcpq = player.getMonsterCarnival();
if (mcpq != null) {