Protected Hired Merchant + Buff system patch
Fixed some issues with Fredrick not retrieving the right amount of items from Hired Merchants. Added concurrency protection for HM. Patched a minor issue on buff system.
This commit is contained in:
@@ -39,6 +39,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import net.MapleServerHandler;
|
||||
import net.mina.MapleCodecFactory;
|
||||
@@ -79,6 +81,7 @@ public class Server implements Runnable {
|
||||
private static Server instance = null;
|
||||
private List<Pair<Integer, String>> worldRecommendedList = new LinkedList<>();
|
||||
private final Map<Integer, MapleGuild> guilds = new LinkedHashMap<>();
|
||||
private final Lock shutdownLock = new ReentrantLock();
|
||||
private final PlayerBuffStorage buffStorage = new PlayerBuffStorage();
|
||||
private final Map<Integer, MapleAlliance> alliances = new LinkedHashMap<>();
|
||||
private boolean online = false;
|
||||
@@ -99,7 +102,8 @@ public class Server implements Runnable {
|
||||
return worldRecommendedList;
|
||||
}
|
||||
|
||||
public void removeChannel(int worldid, int channel) {
|
||||
/*
|
||||
public void removeChannel(int worldid, int channel) { //lol don't!
|
||||
channels.remove(channel);
|
||||
|
||||
World world = worlds.get(worldid);
|
||||
@@ -107,6 +111,7 @@ public class Server implements Runnable {
|
||||
world.removeChannel(channel);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public Channel getChannel(int world, int channel) {
|
||||
return worlds.get(world).getChannel(channel);
|
||||
@@ -702,69 +707,75 @@ public class Server implements Runnable {
|
||||
return worlds;
|
||||
}
|
||||
|
||||
public final Runnable shutdown(final boolean restart) {//only once :D
|
||||
public final Runnable shutdown(final boolean restart) {//no player should be online when trying to shutdown!
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
|
||||
if (getWorlds() == null) return;//already shutdown
|
||||
for (World w : getWorlds()) {
|
||||
w.shutdown();
|
||||
}
|
||||
/*for (World w : getWorlds()) {
|
||||
while (w.getPlayerStorage().getAllCharacters().size() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
shutdownLock.lock();
|
||||
|
||||
try {
|
||||
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
|
||||
if (getWorlds() == null) return;//already shutdown
|
||||
for (World w : getWorlds()) {
|
||||
w.shutdown();
|
||||
}
|
||||
/*for (World w : getWorlds()) {
|
||||
while (w.getPlayerStorage().getAllCharacters().size() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Channel ch : getAllChannels()) {
|
||||
while (ch.getConnectedClients() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
for (Channel ch : getAllChannels()) {
|
||||
while (ch.getConnectedClients() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
TimerManager.getInstance().purge();
|
||||
TimerManager.getInstance().stop();
|
||||
|
||||
for (Channel ch : getAllChannels()) {
|
||||
while (!ch.finishedShutdown()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
worlds.clear();
|
||||
worlds = null;
|
||||
channels.clear();
|
||||
channels = null;
|
||||
worldRecommendedList.clear();
|
||||
worldRecommendedList = null;
|
||||
|
||||
TimerManager.getInstance().purge();
|
||||
TimerManager.getInstance().stop();
|
||||
|
||||
for (Channel ch : getAllChannels()) {
|
||||
while (!ch.finishedShutdown()) {
|
||||
System.out.println("Worlds + Channels are offline.");
|
||||
acceptor.unbind();
|
||||
acceptor = null;
|
||||
if (!restart) {
|
||||
System.exit(0);
|
||||
} else {
|
||||
System.out.println("\r\nRestarting the server....\r\n");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
System.err.println("FUCK MY LIFE");
|
||||
instance.finalize();//FUU I CAN AND IT'S FREE
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
instance = null;
|
||||
System.gc();
|
||||
getInstance().run();//DID I DO EVERYTHING?! D:
|
||||
}
|
||||
}
|
||||
worlds.clear();
|
||||
worlds = null;
|
||||
channels.clear();
|
||||
channels = null;
|
||||
worldRecommendedList.clear();
|
||||
worldRecommendedList = null;
|
||||
|
||||
System.out.println("Worlds + Channels are offline.");
|
||||
acceptor.unbind();
|
||||
acceptor = null;
|
||||
if (!restart) {
|
||||
System.exit(0);
|
||||
} else {
|
||||
System.out.println("\r\nRestarting the server....\r\n");
|
||||
try {
|
||||
instance.finalize();//FUU I CAN AND IT'S FREE
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
instance = null;
|
||||
System.gc();
|
||||
getInstance().run();//DID I DO EVERYTHING?! D:
|
||||
} finally {
|
||||
shutdownLock.unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,10 +72,10 @@ public class FredrickHandler extends AbstractMaplePacketHandler {
|
||||
chr.getHiredMerchant().clearItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Item item = items.get(i).getLeft();
|
||||
Item item = items.get(i).getLeft();
|
||||
MapleInventoryManipulator.addFromDrop(c, item, false);
|
||||
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
|
||||
FilePrinter.printError(FilePrinter.FREDRICK + chr.getName() + ".txt", chr.getName() + " gained " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
|
||||
FilePrinter.printError(FilePrinter.FREDRICK + chr.getName() + ".txt", chr.getName() + " gained " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
|
||||
}
|
||||
c.announce(MaplePacketCreator.fredrickMessage((byte) 0x1E));
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import client.MapleCharacter;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import client.MapleClient;
|
||||
import constants.ServerConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.maps.MapleMapObjectType;
|
||||
import tools.MaplePacketCreator;
|
||||
@@ -38,7 +39,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
public final class HiredMerchantRequest extends AbstractMaplePacketHandler {
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if (chr.getMap().getMapObjectsInRange(chr.getPosition(), 23000, Arrays.asList(MapleMapObjectType.HIRED_MERCHANT)).isEmpty() && chr.getMapId() > 910000000 && chr.getMapId() < 910000023) {
|
||||
if (chr.getMap().getMapObjectsInRange(chr.getPosition(), 23000, Arrays.asList(MapleMapObjectType.HIRED_MERCHANT)).isEmpty() && ((ServerConstants.USE_MERCHANT_ANYWHERE && chr.getMapId() != 910000000) || (chr.getMapId() > 910000000 && chr.getMapId() < 910000023))) {
|
||||
if (!chr.hasMerchant()) {
|
||||
try {
|
||||
if (ItemFactory.MERCHANT.loadItems(chr.getId(), false).isEmpty() && chr.getMerchantMeso() == 0) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -234,7 +235,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
} else if (!merchant.isOpen()) {
|
||||
chr.dropMessage(1, "This shop is in maintenance, please come by later.");
|
||||
return;
|
||||
} else if (merchant.getFreeSlot() == -1) {
|
||||
} else if (merchant.getFreeSlotThreadsafe() == -1) {
|
||||
chr.dropMessage(1, "This shop has reached it's maximum capacity, please come by later.");
|
||||
return;
|
||||
} else {
|
||||
@@ -259,10 +260,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
game.chat(c, slea.readMapleAsciiString());
|
||||
}
|
||||
} else if (merchant != null) {
|
||||
String message = chr.getName() + " : " + slea.readMapleAsciiString();
|
||||
byte slot = (byte) (merchant.getVisitorSlot(c.getPlayer()) + 1);
|
||||
merchant.getMessages().add(new Pair<>(message, slot));
|
||||
merchant.broadcastToVisitors(MaplePacketCreator.hiredMerchantChat(message, slot));
|
||||
merchant.sendMessage(c.getPlayer(), slea.readMapleAsciiString());
|
||||
}
|
||||
} else if (mode == Action.EXIT.getCode()) {
|
||||
if (chr.getTrade() != null) {
|
||||
@@ -408,7 +406,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
} else if (mode == Action.CONFIRM.getCode()) {
|
||||
MapleTrade.completeTrade(c.getPlayer());
|
||||
} else if (mode == Action.ADD_ITEM.getCode() || mode == Action.PUT_ITEM.getCode()) {
|
||||
MapleInventoryType type = MapleInventoryType.getByType(slea.readByte());
|
||||
MapleInventoryType type = MapleInventoryType.getByType(slea.readByte());
|
||||
short slot = slea.readShort();
|
||||
short bundles = slea.readShort();
|
||||
if (chr.getInventory(type).getItem(slot) == null || chr.getItemQuantity(chr.getInventory(type).getItem(slot).getItemId(), false) < bundles || chr.getInventory(type).getItem(slot).getFlag() == ItemConstants.UNTRADEABLE) {
|
||||
@@ -425,6 +423,9 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
Item sellItem = ivItem.copy();
|
||||
if (chr.getItemQuantity(ivItem.getItemId(), false) < perBundle * bundles) {
|
||||
return;
|
||||
} else if (ServerConstants.USE_ENFORCE_UNMERCHABLE_PET && ItemConstants.isPet(ivItem.getItemId())) {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "Pets are not allowed to be sold on the Player Shop."));
|
||||
return;
|
||||
}
|
||||
sellItem.setQuantity(perBundle);
|
||||
MaplePlayerShopItem item = new MaplePlayerShopItem(sellItem, bundles, price);
|
||||
@@ -521,7 +522,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
shop.broadcast(MaplePacketCreator.getPlayerShopItemUpdate(shop));
|
||||
} else if (merchant != null) {
|
||||
merchant.buy(c, item, quantity);
|
||||
merchant.broadcastToVisitors(MaplePacketCreator.updateHiredMerchant(merchant, c.getPlayer()));
|
||||
merchant.broadcastToVisitorsThreadsafe(MaplePacketCreator.updateHiredMerchant(merchant, c.getPlayer()));
|
||||
}
|
||||
} else if (mode == Action.TAKE_ITEM_BACK.getCode()) {
|
||||
HiredMerchant merchant = chr.getHiredMerchant();
|
||||
@@ -555,7 +556,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
chr.setHasMerchant(false);
|
||||
}
|
||||
if (merchant != null && merchant.isOwner(c.getPlayer())) {
|
||||
merchant.getMessages().clear();
|
||||
merchant.clearMessages();
|
||||
merchant.setOpen(true);
|
||||
}
|
||||
chr.setHiredMerchant(null);
|
||||
|
||||
@@ -117,8 +117,14 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
} catch(ClassCastException e) {
|
||||
e.printStackTrace();
|
||||
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Attacker is not a mob-type, rather is a " + map.getMapObject(oid).getClass().getName() + " entity.");
|
||||
//this happens due to mob on last map damaging player just before changing maps
|
||||
|
||||
if(ServerConstants.USE_DEBUG) {
|
||||
e.printStackTrace();
|
||||
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Attacker is not a mob-type, rather is a " + map.getMapObject(oid).getClass().getName() + " entity.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
direction = slea.readByte();
|
||||
|
||||
@@ -86,7 +86,6 @@ public class World {
|
||||
private long mountUpdate;
|
||||
|
||||
private Map<HiredMerchant, Byte> activeMerchants = new LinkedHashMap<>();
|
||||
private ScheduledFuture<?> MerchantsSchedule;
|
||||
private long merchantUpdate;
|
||||
|
||||
private ScheduledFuture<?> charactersSchedule;
|
||||
|
||||
Reference in New Issue
Block a user