Hired Merchant & Player shop fixes + Owl of Minerva
Thanks to BenjixD DietStory's dev team, many bugs found by them have been patched (pirate quests, missing drop data, fly command, etc). Implemented Owl of Minerva. Fixed many issues with Hired Merchant and Player Shops. Fixed an error with the slot checking system. Added Wish Tickets (circa-2006 GMS event) to be dropped on AmoriaPQ.
This commit is contained in:
@@ -267,6 +267,7 @@ public class MapleInventoryManipulator {
|
||||
public static int checkSpaceProgressively(MapleClient c, int itemid, int quantity, String owner, int usedSlots) {
|
||||
// return value --> bit0: if has space for this one;
|
||||
// value after: new slots filled;
|
||||
// assumption: equipments always have slotMax == 1.
|
||||
|
||||
int returnValue;
|
||||
|
||||
@@ -302,9 +303,11 @@ public class MapleInventoryManipulator {
|
||||
|
||||
returnValue = ((numSlotsNeeded + usedSlots) << 1);
|
||||
returnValue += (numSlotsNeeded == 0 || !c.getPlayer().getInventory(type).isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0;
|
||||
//System.out.print(" needed " + numSlotsNeeded + " used " + usedSlots + " rval " + returnValue);
|
||||
} else {
|
||||
returnValue = ((1 + usedSlots) << 1);
|
||||
returnValue = ((quantity + usedSlots) << 1);
|
||||
returnValue += (!c.getPlayer().getInventory(type).isFullAfterSomeItems(0, usedSlots)) ? 1 : 0;
|
||||
//System.out.print(" eqpneeded " + 1 + " used " + usedSlots + " rval " + returnValue);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
|
||||
@@ -916,20 +916,13 @@ public class MapleItemInformationProvider {
|
||||
}
|
||||
nEquip.setLevel((byte) (nEquip.getLevel() + 1));
|
||||
}
|
||||
}
|
||||
|
||||
if (ServerConstants.USE_PERFECT_SCROLLING == false && !ItemConstants.isCleanSlate(scrollId)) {
|
||||
if (!assertGM && !usingWhiteScroll) {
|
||||
} else {
|
||||
if (ServerConstants.USE_PERFECT_SCROLLING == false && !usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
|
||||
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
|
||||
}
|
||||
//nEquip.setLevel((byte) (nEquip.getLevel() + 1));
|
||||
}
|
||||
} else {
|
||||
if (!usingWhiteScroll && !ItemConstants.isCleanSlate(scrollId) && !assertGM) {
|
||||
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
|
||||
}
|
||||
if (Randomizer.nextInt(101) < stats.get("cursed")) {
|
||||
return null;
|
||||
if (Randomizer.nextInt(101) < stats.get("cursed")) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,25 +26,33 @@ import client.MapleClient;
|
||||
import client.inventory.Item;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import net.SendOpcode;
|
||||
import server.maps.AbstractMapleMapObject;
|
||||
import server.maps.MapleMapObjectType;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.data.output.MaplePacketLittleEndianWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
* @author Ronan (concurrency protection)
|
||||
*/
|
||||
public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
private AtomicBoolean open = new AtomicBoolean(false);
|
||||
private MapleCharacter owner;
|
||||
private MapleCharacter[] visitors = new MapleCharacter[3];
|
||||
private List<MaplePlayerShopItem> items = new ArrayList<>();
|
||||
private MapleCharacter[] slot = {null, null, null};
|
||||
private String description;
|
||||
private int boughtnumber = 0;
|
||||
private List<String> bannedList = new ArrayList<>();
|
||||
private List<Pair<MapleCharacter, String>> chatLog = new LinkedList<>();
|
||||
private Map<Integer, Byte> chatSlot = new LinkedHashMap<>();
|
||||
|
||||
public MaplePlayerShop(MapleCharacter owner, String description) {
|
||||
this.setPosition(owner.getPosition());
|
||||
@@ -52,96 +60,145 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getChannel() {
|
||||
return owner.getClient().getChannel();
|
||||
}
|
||||
|
||||
public int getMapId() {
|
||||
return owner.getMapId();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open.get();
|
||||
}
|
||||
|
||||
public void setOpen(boolean openShop) {
|
||||
open.set(openShop);
|
||||
}
|
||||
|
||||
public boolean hasFreeSlot() {
|
||||
return visitors[0] == null || visitors[1] == null || visitors[2] == null;
|
||||
synchronized (visitors) {
|
||||
return visitors[0] == null || visitors[1] == null || visitors[2] == null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOwner(MapleCharacter c) {
|
||||
return owner.equals(c);
|
||||
}
|
||||
|
||||
public void addVisitor(MapleCharacter visitor) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] == null) {
|
||||
visitors[i] = visitor;
|
||||
if (this.getSlot(0) == null) {
|
||||
this.setSlot(visitor, 0);
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, 1));
|
||||
} else if (this.getSlot(1) == null) {
|
||||
this.setSlot(visitor, 1);
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, 2));
|
||||
} else if (this.getSlot(2) == null) {
|
||||
this.setSlot(visitor, 2);
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, 3));
|
||||
visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(this.getOwner(), 1));
|
||||
private void addVisitor(MapleCharacter visitor) {
|
||||
synchronized (visitors) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] == null) {
|
||||
visitors[i] = visitor;
|
||||
visitor.setSlot(i);
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, i + 1));
|
||||
|
||||
if(i == 2) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(this.getOwner(), 1));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVisitor(MapleCharacter visitor) {
|
||||
public void forceRemoveVisitor(MapleCharacter visitor) {
|
||||
if (visitor == owner) {
|
||||
owner.getMap().removeMapObject(this);
|
||||
owner.setPlayerShop(null);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null && visitors[i].getId() == visitor.getId()) {
|
||||
int slot_ = visitor.getSlot();
|
||||
visitors[i] = null;
|
||||
this.setSlot(null, i);
|
||||
visitor.setSlot(-1);
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopRemoveVisitor(slot_ + 1));
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopRemoveVisitor(i + 1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVisitor(MapleCharacter visitor) {
|
||||
if (visitor == owner) {
|
||||
owner.getMap().removeMapObject(this);
|
||||
owner.setPlayerShop(null);
|
||||
} else {
|
||||
synchronized (visitors) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null && visitors[i].getId() == visitor.getId()) {
|
||||
visitor.setSlot(-1); //absolutely cant remove player slot for late players without dc'ing them... heh
|
||||
|
||||
for(int j = i; j < 2; j++) {
|
||||
if(visitors[j] != null) owner.announce(MaplePacketCreator.getPlayerShopRemoveVisitor(j + 1));
|
||||
visitors[j] = visitors[j + 1];
|
||||
if(visitors[j] != null) visitors[j].setSlot(j);
|
||||
}
|
||||
visitors[2] = null;
|
||||
for(int j = i; j < 2; j++) {
|
||||
if(visitors[j] != null) owner.announce(MaplePacketCreator.getPlayerShopNewVisitor(visitors[j], j + 1));
|
||||
}
|
||||
|
||||
this.broadcastRestoreToVisitors();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.getOwner().getPlayerShop() != null) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(this.getOwner(), 4));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isVisitor(MapleCharacter visitor) {
|
||||
return visitors[0] == visitor || visitors[1] == visitor || visitors[2] == visitor;
|
||||
synchronized (visitors) {
|
||||
return visitors[0] == visitor || visitors[1] == visitor || visitors[2] == visitor;
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(MaplePlayerShopItem item) {
|
||||
items.add(item);
|
||||
synchronized (items) {
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(int item) {
|
||||
items.remove(item);
|
||||
synchronized (items) {
|
||||
items.remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* no warnings for now o.op
|
||||
* no warnings for now o.o
|
||||
* @param c
|
||||
* @param item
|
||||
* @param quantity
|
||||
*/
|
||||
public void buy(MapleClient c, int item, short quantity) {
|
||||
if (isVisitor(c.getPlayer())) {
|
||||
MaplePlayerShopItem pItem = items.get(item);
|
||||
Item newItem = pItem.getItem().copy();
|
||||
newItem.setQuantity(newItem.getQuantity());
|
||||
if (quantity < 1 || pItem.getBundles() < 1 || newItem.getQuantity() > pItem.getBundles() || !pItem.isExist()) {
|
||||
return;
|
||||
} else if (newItem.getType() == 1 && newItem.getQuantity() > 1) {
|
||||
return;
|
||||
}
|
||||
synchronized (c.getPlayer()) {
|
||||
if (c.getPlayer().getMeso() >= (long) pItem.getPrice() * quantity) {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
|
||||
c.getPlayer().gainMeso(-pItem.getPrice() * quantity, true);
|
||||
owner.gainMeso(pItem.getPrice() * quantity, true);
|
||||
pItem.setBundles((short) (pItem.getBundles() - quantity));
|
||||
if (pItem.getBundles() < 1) {
|
||||
pItem.setDoesExist(false);
|
||||
if (++boughtnumber == items.size()) {
|
||||
owner.setPlayerShop(null);
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(owner));
|
||||
this.removeVisitors();
|
||||
owner.dropMessage(1, "Your items are sold out, and therefore your shop is closed.");
|
||||
synchronized (items) {
|
||||
if (isVisitor(c.getPlayer())) {
|
||||
MaplePlayerShopItem pItem = items.get(item);
|
||||
Item newItem = pItem.getItem().copy();
|
||||
newItem.setQuantity(newItem.getQuantity());
|
||||
if (quantity < 1 || pItem.getBundles() < 1 || newItem.getQuantity() > pItem.getBundles() || !pItem.isExist()) {
|
||||
return;
|
||||
} else if (newItem.getType() == 1 && newItem.getQuantity() > 1) {
|
||||
return;
|
||||
}
|
||||
synchronized (c.getPlayer()) {
|
||||
if (c.getPlayer().getMeso() >= (long) pItem.getPrice() * quantity) {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
|
||||
c.getPlayer().gainMeso(-pItem.getPrice() * quantity, true);
|
||||
owner.gainMeso(pItem.getPrice() * quantity, true);
|
||||
pItem.setBundles((short) (pItem.getBundles() - quantity));
|
||||
if (pItem.getBundles() < 1) {
|
||||
pItem.setDoesExist(false);
|
||||
if (++boughtnumber == items.size()) {
|
||||
owner.setPlayerShop(null);
|
||||
this.setOpen(false);
|
||||
this.closeShop();
|
||||
owner.dropMessage(1, "Your items are sold out, and therefore your shop is closed.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(1, "Your inventory is full. Please clean a slot before buying this item.");
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(1, "Your inventory is full. Please clean a slot before buying this item.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,26 +206,51 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void broadcastToVisitors(final byte[] packet) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].getClient().announce(packet);
|
||||
synchronized (visitors) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].getClient().announce(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastRestoreToVisitors() {
|
||||
synchronized (visitors) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].getClient().announce(MaplePacketCreator.getPlayerShopRemoveVisitor(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].getClient().announce(MaplePacketCreator.getPlayerShop(this, false));
|
||||
}
|
||||
}
|
||||
|
||||
recoverChatLog();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVisitors() {
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].getClient().announce(MaplePacketCreator.shopErrorMessage(10, 1));
|
||||
removeVisitor(visitors[i]);
|
||||
List<MapleCharacter> visitorList = new ArrayList<>(3);
|
||||
synchronized (visitors) {
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].getClient().announce(MaplePacketCreator.shopErrorMessage(10, 1));
|
||||
visitorList.add(visitors[i]);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for(MapleCharacter mc : visitorList) forceRemoveVisitor(mc);
|
||||
if (owner != null) {
|
||||
removeVisitor(getOwner());
|
||||
forceRemoveVisitor(getOwner());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,23 +270,61 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
broadcastToVisitors(packet);
|
||||
}
|
||||
|
||||
public void chat(MapleClient c, String chat) {
|
||||
private byte getVisitorSlot(MapleCharacter chr) {
|
||||
byte s = 0;
|
||||
for (MapleCharacter mc : getVisitors()) {
|
||||
s++;
|
||||
if (mc != null) {
|
||||
if (mc.getName().equalsIgnoreCase(c.getPlayer().getName())) {
|
||||
if (mc.getName().equalsIgnoreCase(chr.getName())) {
|
||||
break;
|
||||
}
|
||||
} else if (s == 3) {
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public void chat(MapleClient c, String chat) {
|
||||
byte s = getVisitorSlot(c.getPlayer());
|
||||
|
||||
synchronized(chatLog) {
|
||||
chatLog.add(new Pair<>(c.getPlayer(), chat));
|
||||
if(chatLog.size() > 25) chatLog.remove(0);
|
||||
chatSlot.put(c.getPlayer().getId(), s);
|
||||
}
|
||||
|
||||
broadcast(MaplePacketCreator.getPlayerShopChat(c.getPlayer(), chat, s));
|
||||
}
|
||||
|
||||
private void recoverChatLog() {
|
||||
synchronized(chatLog) {
|
||||
for(Pair<MapleCharacter, String> it : chatLog) {
|
||||
MapleCharacter chr = it.getLeft();
|
||||
Byte pos = chatSlot.get(chr.getId());
|
||||
|
||||
broadcastToVisitors(MaplePacketCreator.getPlayerShopChat(chr, it.getRight(), pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearChatLog() {
|
||||
synchronized(chatLog) {
|
||||
chatLog.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeShop() {
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(owner));
|
||||
clearChatLog();
|
||||
removeVisitors();
|
||||
}
|
||||
|
||||
public void sendShop(MapleClient c) {
|
||||
c.announce(MaplePacketCreator.getPlayerShop(c, this, isOwner(c.getPlayer())));
|
||||
synchronized(visitors) {
|
||||
c.announce(MaplePacketCreator.getPlayerShop(this, isOwner(c.getPlayer())));
|
||||
}
|
||||
}
|
||||
|
||||
public MapleCharacter getOwner() {
|
||||
@@ -212,22 +332,28 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public MapleCharacter[] getVisitors() {
|
||||
return visitors;
|
||||
}
|
||||
|
||||
public MapleCharacter getSlot(int s) {
|
||||
return slot[s];
|
||||
}
|
||||
|
||||
private void setSlot(MapleCharacter person, int s) {
|
||||
slot[s] = person;
|
||||
if (person != null) {
|
||||
person.setSlot(s);
|
||||
synchronized(visitors) {
|
||||
MapleCharacter[] copy = new MapleCharacter[3];
|
||||
for(int i = 0; i < visitors.length; i++) copy[i] = visitors[i];
|
||||
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
public List<MaplePlayerShopItem> getItems() {
|
||||
return Collections.unmodifiableList(items);
|
||||
synchronized (items) {
|
||||
return Collections.unmodifiableList(items);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasItem(int itemid) {
|
||||
for(MaplePlayerShopItem mpsi : getItems()) {
|
||||
if(mpsi.getItem().getItemId() == itemid && mpsi.isExist() && mpsi.getBundles() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
@@ -242,18 +368,64 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
if (!bannedList.contains(name)) {
|
||||
bannedList.add(name);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null && visitors[i].getName().equals(name)) {
|
||||
visitors[i].getClient().announce(MaplePacketCreator.shopErrorMessage(5, 1));
|
||||
removeVisitor(visitors[i]);
|
||||
return; //I'm guessing this was the intended action
|
||||
|
||||
MapleCharacter target = null;
|
||||
synchronized(visitors) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null && visitors[i].getName().equals(name)) {
|
||||
target = visitors[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(target != null) {
|
||||
target.getClient().announce(MaplePacketCreator.shopErrorMessage(5, 1));
|
||||
removeVisitor(target);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBanned(String name) {
|
||||
return bannedList.contains(name);
|
||||
}
|
||||
|
||||
public synchronized boolean visitShop(MapleCharacter chr) {
|
||||
if(!open.get()) {
|
||||
chr.dropMessage(1, "This store is not yet open.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isBanned(chr.getName())) {
|
||||
chr.dropMessage(1, "You have been banned from this store.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.hasFreeSlot() && !this.isVisitor(chr)) {
|
||||
this.addVisitor(chr);
|
||||
chr.setPlayerShop(this);
|
||||
this.sendShop(chr.getClient());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<MaplePlayerShopItem> sendAvailableBundles(int itemid) {
|
||||
List<MaplePlayerShopItem> list = new LinkedList<>();
|
||||
List<MaplePlayerShopItem> all = new ArrayList<>();
|
||||
|
||||
synchronized (items) {
|
||||
for(MaplePlayerShopItem mpsi : items) all.add(mpsi);
|
||||
}
|
||||
|
||||
for(MaplePlayerShopItem mpsi : all) {
|
||||
if(mpsi.getItem().getItemId() == itemid && mpsi.getBundles() > 0 && mpsi.isExist()) {
|
||||
list.add(mpsi);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import net.server.Server;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
@@ -46,8 +47,9 @@ import tools.Pair;
|
||||
/**
|
||||
*
|
||||
* @author XoticStory
|
||||
* @author Ronan (concurrency protection)
|
||||
*/
|
||||
public class HiredMerchant extends AbstractMapleMapObject {
|
||||
public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
|
||||
private int ownerId, itemId, mesos = 0;
|
||||
private int channel, world;
|
||||
@@ -58,10 +60,10 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
private final List<MaplePlayerShopItem> items = new LinkedList<>();
|
||||
private List<Pair<String, Byte>> messages = new LinkedList<>();
|
||||
private List<SoldItem> sold = new LinkedList<>();
|
||||
private boolean open;
|
||||
private AtomicBoolean open = new AtomicBoolean();
|
||||
private MapleMap map;
|
||||
|
||||
public HiredMerchant(final MapleCharacter owner, int itemId, String desc) {
|
||||
public MapleHiredMerchant(final MapleCharacter owner, int itemId, String desc) {
|
||||
this.setPosition(owner.getPosition());
|
||||
this.start = System.currentTimeMillis();
|
||||
this.ownerId = owner.getId();
|
||||
@@ -87,13 +89,17 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void addVisitor(MapleCharacter visitor) {
|
||||
public boolean addVisitor(MapleCharacter visitor) {
|
||||
synchronized(visitors) {
|
||||
int i = this.getFreeSlot();
|
||||
if (i > -1) {
|
||||
visitors[i] = visitor;
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorAdd(visitor, i + 1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,9 +111,7 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
if (visitors[slot] != null && visitors[slot].getId() == visitor.getId()) {
|
||||
visitors[slot] = null;
|
||||
if (slot != -1) {
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1));
|
||||
}
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,15 +131,15 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
return -1; //Actually 0 because of the +1's.
|
||||
}
|
||||
|
||||
public void removeAllVisitors(String message) {
|
||||
public void removeAllVisitors() {
|
||||
synchronized(visitors) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].setHiredMerchant(null);
|
||||
|
||||
visitors[i].getClient().announce(MaplePacketCreator.leaveHiredMerchant(i + 1, 0x11));
|
||||
if (message.length() > 0) {
|
||||
visitors[i].dropMessage(1, message);
|
||||
}
|
||||
visitors[i].getClient().announce(MaplePacketCreator.hiredMerchantMaintenanceMessage());
|
||||
|
||||
visitors[i] = null;
|
||||
}
|
||||
}
|
||||
@@ -163,7 +167,7 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
int price = (int)Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
|
||||
if (c.getPlayer().getMeso() >= price) {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, newItem, true)) {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
|
||||
c.getPlayer().gainMeso(-price, false);
|
||||
|
||||
synchronized (sold) {
|
||||
@@ -322,6 +326,16 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
return Collections.unmodifiableList(items);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasItem(int itemid) {
|
||||
for(MaplePlayerShopItem mpsi : getItems()) {
|
||||
if(mpsi.getItem().getItemId() == itemid && mpsi.isExist() && mpsi.getBundles() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addItem(MaplePlayerShopItem item) {
|
||||
synchronized (items) {
|
||||
@@ -367,11 +381,11 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return open;
|
||||
return open.get();
|
||||
}
|
||||
|
||||
public void setOpen(boolean set) {
|
||||
this.open = set;
|
||||
open.getAndSet(set);
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
@@ -389,7 +403,25 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
synchronized (messages) {
|
||||
messages.add(new Pair<>(message, slot));
|
||||
}
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantChat(message, slot));
|
||||
broadcastToVisitorsThreadsafe(MaplePacketCreator.hiredMerchantChat(message, slot));
|
||||
}
|
||||
|
||||
public List<MaplePlayerShopItem> sendAvailableBundles(int itemid) {
|
||||
List<MaplePlayerShopItem> list = new LinkedList<>();
|
||||
List<MaplePlayerShopItem> all = new ArrayList<>();
|
||||
|
||||
if(!open.get()) return list;
|
||||
|
||||
synchronized (items) {
|
||||
for(MaplePlayerShopItem mpsi : items) all.add(mpsi);
|
||||
}
|
||||
|
||||
for(MaplePlayerShopItem mpsi : all) {
|
||||
if(mpsi.getItem().getItemId() == itemid && mpsi.getBundles() > 0 && mpsi.isExist()) {
|
||||
list.add(mpsi);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void saveItems(boolean shutdown) throws SQLException {
|
||||
@@ -490,6 +522,10 @@ public class HiredMerchant extends AbstractMapleMapObject {
|
||||
public int getMapId() {
|
||||
return map.getId();
|
||||
}
|
||||
|
||||
public MapleMap getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public List<SoldItem> getSold() {
|
||||
synchronized (sold) {
|
||||
Reference in New Issue
Block a user