Multi World NPCs + patch on Player interactions
Made NPCs now work properly on multiworld system. Solved multiple issues regarding Player Shops not giving back items properly when owner exits. Added restriction on changing channels at FM rooms, preventing shop owner entering Cash Shop.
This commit is contained in:
@@ -70,6 +70,7 @@ import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleMiniGame;
|
||||
import server.MaplePlayerShop;
|
||||
import server.MaplePlayerShopItem;
|
||||
import server.MaplePortal;
|
||||
import server.MapleShop;
|
||||
import server.MapleStatEffect;
|
||||
@@ -1206,9 +1207,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
|
||||
private void changeMapInternal(final MapleMap to, final Point pos, final byte[] warpPacket) {
|
||||
if (this.getTrade() != null) {
|
||||
MapleTrade.cancelTrade(this);
|
||||
}
|
||||
this.closePlayerInteractions();
|
||||
|
||||
client.announce(warpPacket);
|
||||
map.removePlayer(MapleCharacter.this);
|
||||
if (client.getChannelServer().getPlayerStorage().getCharacterById(getId()) != null) {
|
||||
@@ -2558,8 +2558,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
|
||||
public boolean isPartyMember(MapleCharacter chr) {
|
||||
for(MapleCharacter mpc: getPartyMembers()) {
|
||||
if(mpc.getId() == chr.getId()) {
|
||||
for(MapleCharacter mpcu: getPartyMembers()) {
|
||||
if(mpcu.getId() == chr.getId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2570,6 +2570,93 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
public MaplePlayerShop getPlayerShop() {
|
||||
return playerShop;
|
||||
}
|
||||
|
||||
public void closePlayerInteractions() {
|
||||
closeNpcShop();
|
||||
closeTrade();
|
||||
closePlayerShop();
|
||||
closeMiniGame();
|
||||
closeHiredMerchant(false);
|
||||
closePlayerMessenger();
|
||||
}
|
||||
|
||||
public void closeNpcShop() {
|
||||
setShop(null);
|
||||
}
|
||||
|
||||
public void closeTrade() {
|
||||
MapleTrade.cancelTrade(this);
|
||||
}
|
||||
|
||||
public void closePlayerShop() {
|
||||
MaplePlayerShop mps = this.getPlayerShop();
|
||||
if(mps == null) return;
|
||||
|
||||
if (mps.isOwner(this)) {
|
||||
for (MaplePlayerShopItem mpsi : mps.getItems()) {
|
||||
if (mpsi.getBundles() >= 2) {
|
||||
Item iItem = mpsi.getItem().copy();
|
||||
iItem.setQuantity((short) (mpsi.getBundles() * iItem.getQuantity()));
|
||||
MapleInventoryManipulator.addFromDrop(this.getClient(), iItem, false);
|
||||
} else if (mpsi.isExist()) {
|
||||
MapleInventoryManipulator.addFromDrop(this.getClient(), mpsi.getItem(), true);
|
||||
}
|
||||
}
|
||||
this.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(this));
|
||||
mps.removeVisitors();
|
||||
} else {
|
||||
mps.removeVisitor(this);
|
||||
}
|
||||
this.setPlayerShop(null);
|
||||
}
|
||||
|
||||
public void closeMiniGame() {
|
||||
MapleMiniGame game = this.getMiniGame();
|
||||
if(game == null) return;
|
||||
|
||||
this.setMiniGame(null);
|
||||
if (game.isOwner(this)) {
|
||||
this.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(this));
|
||||
game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose());
|
||||
} else {
|
||||
game.removeVisitor(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeHiredMerchant(boolean closeMerchant) {
|
||||
HiredMerchant merchant = this.getHiredMerchant();
|
||||
if(merchant == null) return;
|
||||
|
||||
if(closeMerchant) {
|
||||
merchant.removeVisitor(this);
|
||||
this.setHiredMerchant(null);
|
||||
}
|
||||
else {
|
||||
if (merchant.isOwner(this)) {
|
||||
merchant.setOpen(true);
|
||||
} else {
|
||||
merchant.removeVisitor(this);
|
||||
}
|
||||
try {
|
||||
merchant.saveItems(false);
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
System.out.println("Error while saving Hired Merchant items.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void closePlayerMessenger() {
|
||||
MapleMessenger m = this.getMessenger();
|
||||
if(m == null) return;
|
||||
|
||||
World w = client.getWorldServer();
|
||||
MapleMessengerCharacter messengerplayer = new MapleMessengerCharacter(this, this.getMessengerPosition());
|
||||
|
||||
w.leaveMessenger(m.getId(), messengerplayer);
|
||||
this.setMessenger(null);
|
||||
this.setMessengerPosition(4);
|
||||
}
|
||||
|
||||
public MaplePet[] getPets() {
|
||||
return pets;
|
||||
|
||||
@@ -721,41 +721,12 @@ public class MapleClient {
|
||||
try {
|
||||
player.cancelAllBuffs(true);
|
||||
player.cancelAllDebuffs();
|
||||
final MaplePlayerShop mps = player.getPlayerShop();
|
||||
if (mps != null) {
|
||||
mps.removeVisitors();
|
||||
player.setPlayerShop(null);
|
||||
}
|
||||
final HiredMerchant merchant = player.getHiredMerchant();
|
||||
if (merchant != null) {
|
||||
if (merchant.isOwner(player)) {
|
||||
merchant.setOpen(true);
|
||||
} else {
|
||||
merchant.removeVisitor(player);
|
||||
}
|
||||
try {
|
||||
merchant.saveItems(false);
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
System.out.println("Error while saving Hired Merchant items.");
|
||||
}
|
||||
}
|
||||
player.setMessenger(null);
|
||||
final MapleMiniGame game = player.getMiniGame();
|
||||
if (game != null) {
|
||||
player.setMiniGame(null);
|
||||
if (game.isOwner(player)) {
|
||||
player.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(player));
|
||||
game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose());
|
||||
} else {
|
||||
game.removeVisitor(player);
|
||||
}
|
||||
}
|
||||
|
||||
player.closePlayerInteractions();
|
||||
|
||||
NPCScriptManager.getInstance().dispose(this);
|
||||
QuestScriptManager.getInstance().dispose(this);
|
||||
if (player.getTrade() != null) {
|
||||
MapleTrade.cancelTrade(player);
|
||||
}
|
||||
|
||||
if (player.getEventInstance() != null) {
|
||||
player.getEventInstance().playerDisconnected(player);
|
||||
}
|
||||
@@ -1236,7 +1207,7 @@ public class MapleClient {
|
||||
disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
if (!player.isAlive() || FieldLimit.CHANGECHANNEL.check(player.getMap().getFieldLimit())) {
|
||||
if (!player.isAlive() || FieldLimit.CANNOTMIGRATE.check(player.getMap().getFieldLimit())) {
|
||||
announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -559,7 +559,7 @@ public class Commands {
|
||||
break;
|
||||
*/
|
||||
case "joinevent":
|
||||
if(!FieldLimit.CHANGECHANNEL.check(player.getMap().getFieldLimit())) {
|
||||
if(!FieldLimit.CANNOTMIGRATE.check(player.getMap().getFieldLimit())) {
|
||||
MapleEvent event = c.getChannelServer().getEvent();
|
||||
if(event != null) {
|
||||
if(event.getMapId() != player.getMapId()) {
|
||||
|
||||
@@ -178,7 +178,9 @@ public class Server implements Runnable {
|
||||
|
||||
|
||||
try {
|
||||
for (int i = 0; i < Integer.parseInt(p.getProperty("worlds")); i++) {
|
||||
Integer worldCount = Math.min(ServerConstants.WORLD_NAMES.length, Integer.parseInt(p.getProperty("worlds")));
|
||||
|
||||
for (int i = 0; i < worldCount; i++) {
|
||||
System.out.println("Starting world " + i);
|
||||
World world = new World(i,
|
||||
Integer.parseInt(p.getProperty("flag" + i)),
|
||||
|
||||
@@ -25,6 +25,7 @@ import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.MapleTrade;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -41,6 +42,8 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
|
||||
if (mc.getCashShop().isOpened()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mc.closePlayerInteractions();
|
||||
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(mc.getId(), mc.getAllBuffs());
|
||||
mc.cancelBuffEffects();
|
||||
|
||||
@@ -33,12 +33,14 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
* @author Matze
|
||||
*/
|
||||
public final class ItemMoveHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.skip(4);
|
||||
if(c.getPlayer().getAutobanManager().getLastSpam(6) + 300 > System.currentTimeMillis()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if(c.getPlayer().getAutobanManager().getLastSpam(6) + 300 > System.currentTimeMillis()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
MapleInventoryType type = MapleInventoryType.getByType(slea.readByte());
|
||||
byte src = (byte) slea.readShort();
|
||||
byte action = (byte) slea.readShort();
|
||||
@@ -52,6 +54,6 @@ public final class ItemMoveHandler extends AbstractMaplePacketHandler {
|
||||
} else {
|
||||
MapleInventoryManipulator.move(c, type, src, action);
|
||||
}
|
||||
c.getPlayer().getAutobanManager().spam(6);
|
||||
c.getPlayer().getAutobanManager().spam(6);
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class MessengerHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
String input;
|
||||
byte mode = slea.readByte();
|
||||
@@ -59,12 +60,7 @@ public final class MessengerHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
if (messenger != null) {
|
||||
MapleMessengerCharacter messengerplayer = new MapleMessengerCharacter(player, player.getMessengerPosition());
|
||||
world.leaveMessenger(messenger.getId(), messengerplayer);
|
||||
player.setMessenger(null);
|
||||
player.setMessengerPosition(4);
|
||||
}
|
||||
player.closePlayerMessenger();
|
||||
break;
|
||||
case 0x03:
|
||||
if (messenger.getMembers().size() < 3) {
|
||||
|
||||
@@ -266,38 +266,9 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
if (chr.getTrade() != null) {
|
||||
MapleTrade.cancelTrade(c.getPlayer());
|
||||
} else {
|
||||
MaplePlayerShop shop = chr.getPlayerShop();
|
||||
MapleMiniGame game = chr.getMiniGame();
|
||||
HiredMerchant merchant = chr.getHiredMerchant();
|
||||
if (shop != null) {
|
||||
if (shop.isOwner(c.getPlayer())) {
|
||||
for (MaplePlayerShopItem mpsi : shop.getItems()) {
|
||||
if (mpsi.getBundles() > 2) {
|
||||
Item iItem = mpsi.getItem().copy();
|
||||
iItem.setQuantity((short) (mpsi.getBundles() * iItem.getQuantity()));
|
||||
MapleInventoryManipulator.addFromDrop(c, iItem, false);
|
||||
} else if (mpsi.isExist()) {
|
||||
MapleInventoryManipulator.addFromDrop(c, mpsi.getItem(), true);
|
||||
}
|
||||
}
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(c.getPlayer()));
|
||||
shop.removeVisitors();
|
||||
} else {
|
||||
shop.removeVisitor(c.getPlayer());
|
||||
}
|
||||
chr.setPlayerShop(null);
|
||||
} else if (game != null) {
|
||||
chr.setMiniGame(null);
|
||||
if (game.isOwner(c.getPlayer())) {
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(c.getPlayer()));
|
||||
game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose());
|
||||
} else {
|
||||
game.removeVisitor(c.getPlayer());
|
||||
}
|
||||
} else if (merchant != null) {
|
||||
merchant.removeVisitor(c.getPlayer());
|
||||
chr.setHiredMerchant(null);
|
||||
}
|
||||
chr.closePlayerShop();
|
||||
chr.closeMiniGame();
|
||||
chr.closeHiredMerchant(true);
|
||||
}
|
||||
} else if (mode == Action.OPEN.getCode()) {
|
||||
MaplePlayerShop shop = chr.getPlayerShop();
|
||||
|
||||
@@ -269,12 +269,14 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
if (player.getMap().getHPDec() > 0) {
|
||||
final MapleCharacter mc = player;
|
||||
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
ScheduledFuture<?> hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mc.doHurtHp();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
mc.setHpDecreaseTask(hpDecreaseTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +64,10 @@ public class NPCScriptManager extends AbstractScriptManager {
|
||||
cms.put(c, cm);
|
||||
Invocable iv = null;
|
||||
if (fileName != null) {
|
||||
iv = getInvocable("npc/world" + c.getWorld() + "/" + fileName + ".js", c);
|
||||
iv = getInvocable("npc/" + fileName + ".js", c);
|
||||
}
|
||||
if (iv == null) {
|
||||
iv = getInvocable("npc/world" + c.getWorld() + "/" + npc + ".js", c);
|
||||
iv = getInvocable("npc/" + npc + ".js", c);
|
||||
}
|
||||
if (iv == null) {
|
||||
FilePrinter.printError(FilePrinter.NPC_UNCODED, "NPC " + MapleLifeFactory.getNPC(npc).getName() + "(" + npc + ") is not coded.\r\n");
|
||||
@@ -122,9 +122,9 @@ public class NPCScriptManager extends AbstractScriptManager {
|
||||
scripts.remove(c);
|
||||
|
||||
if(cm.getScriptName() != null) {
|
||||
resetContext("npc/world" + c.getWorld() + "/" + cm.getScriptName() + ".js", c);
|
||||
resetContext("npc/" + cm.getScriptName() + ".js", c);
|
||||
} else {
|
||||
resetContext("npc/world" + c.getWorld() + "/" + cm.getNpc() + ".js", c);
|
||||
resetContext("npc/" + cm.getNpc() + ".js", c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -472,7 +472,7 @@ public class MapleInventoryManipulator {
|
||||
return;
|
||||
}
|
||||
int itemId = source.getItemId();
|
||||
if (itemId >= 5000000 && itemId <= 5000100) {
|
||||
if (itemId >= 5000000 && itemId <= 5000102) {
|
||||
return;
|
||||
}
|
||||
if (type == MapleInventoryType.EQUIPPED && itemId == 1122017) {
|
||||
|
||||
@@ -254,10 +254,13 @@ public class MapleTrade {
|
||||
}
|
||||
|
||||
public static void cancelTrade(MapleCharacter c) {
|
||||
c.getTrade().cancel();
|
||||
if (c.getTrade().getPartner() != null) {
|
||||
c.getTrade().getPartner().cancel();
|
||||
c.getTrade().getPartner().getChr().setTrade(null);
|
||||
MapleTrade trade = c.getTrade();
|
||||
if(trade == null) return;
|
||||
|
||||
trade.cancel();
|
||||
if (trade.getPartner() != null) {
|
||||
trade.getPartner().cancel();
|
||||
trade.getPartner().getChr().setTrade(null);
|
||||
}
|
||||
c.setTrade(null);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public enum FieldLimit {
|
||||
MOVEMENTSKILLS(0x02),
|
||||
SUMMON(0x04),
|
||||
DOOR(0x08),
|
||||
CHANGECHANNEL(0x10),
|
||||
CANNOTMIGRATE(0x10), //change channel, town portal scroll, access cash shop, etc etc
|
||||
//NO_NOTES(0x20),
|
||||
CANNOTVIPROCK(0x40),
|
||||
CANNOTMINIGAME(0x80),
|
||||
|
||||
@@ -57,7 +57,7 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
private String ownerName = "";
|
||||
private String description = "";
|
||||
private MapleCharacter[] visitors = new MapleCharacter[3];
|
||||
private List<MaplePlayerShopItem> items = new LinkedList<>();
|
||||
private final List<MaplePlayerShopItem> items = new LinkedList<>();
|
||||
private List<Pair<String, Byte>> messages = new LinkedList<>();
|
||||
private List<SoldItem> sold = new LinkedList<>();
|
||||
private boolean open;
|
||||
|
||||
@@ -36,6 +36,7 @@ import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import server.quest.actions.*;
|
||||
import server.quest.requirements.*;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
@@ -63,21 +64,25 @@ public class MapleQuest {
|
||||
|
||||
private MapleQuest(int id) {
|
||||
this.id = (short) id;
|
||||
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
||||
if(questInfo != null) {
|
||||
MapleData reqInfo = questInfo.getChildByPath(String.valueOf(id));
|
||||
if(reqInfo != null) {
|
||||
timeLimit = MapleDataTool.getInt("timeLimit", reqInfo, 0);
|
||||
timeLimit = Math.max(timeLimit, MapleDataTool.getInt("timeLimit2", reqInfo, 0)); // alas, nexon made we deal with 2 timeLimits
|
||||
autoStart = MapleDataTool.getInt("autoStart", reqInfo, 0) == 1;
|
||||
autoPreComplete = MapleDataTool.getInt("autoPreComplete", reqInfo, 0) == 1;
|
||||
autoComplete = MapleDataTool.getInt("autoComplete", reqInfo, 0) == 1;
|
||||
} else {
|
||||
System.out.println("no data " + id);
|
||||
}
|
||||
}
|
||||
|
||||
MapleData startReqData = reqData.getChildByPath("0");
|
||||
if (startReqData != null) {
|
||||
for (MapleData startReq : startReqData.getChildren()) {
|
||||
|
||||
Reference in New Issue
Block a user