Buff System & Map skipping fix + properly disposing Storage + Fairness to locks
Fixed buff system behaving oddly if a buff has value zero, that would render some skills "broken". Fixed players skipping maps when trying to access portals while under a poor Internet connection. Fixed storage not disposing players properly in cases where the players does not meet the storage conditions. Set some locks to use fairness strategy when dealing with atomic code, in order to make the calls to it properly synchronized. Fixed Aran introductory questline stucking players when certain conditions were met. Added drop data for some mob versions of Fairy, Yeti and Pepe.
This commit is contained in:
@@ -208,6 +208,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private String chalktext;
|
||||
private String dataString;
|
||||
private String search = null;
|
||||
private AtomicBoolean mapTransitioning = new AtomicBoolean(true); // player client is currently trying to change maps or log in the game map
|
||||
private AtomicBoolean awayFromWorld = new AtomicBoolean(true); // player is online, but on cash shop or mts
|
||||
private AtomicInteger exp = new AtomicInteger();
|
||||
private AtomicInteger gachaexp = new AtomicInteger();
|
||||
@@ -268,9 +269,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private ScheduledFuture<?> chairRecoveryTask = null;
|
||||
private ScheduledFuture<?> pendantOfSpirit = null; //1122017
|
||||
private List<ScheduledFuture<?>> timers = new ArrayList<>();
|
||||
private Lock chrLock = new ReentrantLock();
|
||||
private Lock effLock = new ReentrantLock();
|
||||
private Lock petLock = new ReentrantLock();
|
||||
private Lock chrLock = new ReentrantLock(true);
|
||||
private Lock effLock = new ReentrantLock(true);
|
||||
private Lock petLock = new ReentrantLock(true);
|
||||
private Lock prtLock = new ReentrantLock();
|
||||
private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>();
|
||||
private Set<Integer> excludedItems = new LinkedHashSet<>();
|
||||
@@ -1251,6 +1252,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private void changeMapInternal(final MapleMap to, final Point pos, final byte[] warpPacket) {
|
||||
if(!canWarpMap) return;
|
||||
|
||||
this.mapTransitioning.set(true);
|
||||
|
||||
this.unregisterChairBuff();
|
||||
this.clearBanishPlayerData();
|
||||
this.closePlayerInteractions();
|
||||
@@ -1288,18 +1291,26 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
int temp = newWarpMap;
|
||||
newWarpMap = -1;
|
||||
changeMap(temp);
|
||||
} else {
|
||||
// if this event map has a gate already opened, render it
|
||||
EventInstanceManager eim = getEventInstance();
|
||||
if(eim != null) {
|
||||
eim.recoverOpenedGate(this, map.getId());
|
||||
}
|
||||
|
||||
// if this map has obstacle components moving, make it do so for this client
|
||||
for(Entry<String, Integer> e: map.getEnvironment().entrySet()) {
|
||||
announce(MaplePacketCreator.environmentMove(e.getKey(), e.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
// if this event map has a gate already opened, render it
|
||||
EventInstanceManager eim = getEventInstance();
|
||||
if(eim != null) {
|
||||
eim.recoverOpenedGate(this, map.getId());
|
||||
}
|
||||
|
||||
// if this map has obstacle components moving, make it do so for this client
|
||||
for(Entry<String, Integer> e: map.getEnvironment().entrySet()) {
|
||||
announce(MaplePacketCreator.environmentMove(e.getKey(), e.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isChangingMaps() {
|
||||
return this.mapTransitioning.get();
|
||||
}
|
||||
|
||||
public void setMapTransitionComplete() {
|
||||
this.mapTransitioning.set(false);
|
||||
}
|
||||
|
||||
public void changePage(int page) {
|
||||
@@ -3322,7 +3333,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
addItemEffectHolder(sourceid, expirationtime, appliedStatups);
|
||||
|
||||
for (Entry<MapleBuffStat, MapleBuffStatValueHolder> statup : toDeploy.entrySet()) {
|
||||
if(statup.getValue().value != 0) effects.put(statup.getKey(), statup.getValue());
|
||||
effects.put(statup.getKey(), statup.getValue());
|
||||
}
|
||||
} finally {
|
||||
chrLock.unlock();
|
||||
|
||||
@@ -111,7 +111,7 @@ public class MapleClient {
|
||||
private int picattempt = 0;
|
||||
private byte gender = -1;
|
||||
private boolean disconnecting = false;
|
||||
private final Lock mutex = new ReentrantLock(true);
|
||||
private final Lock lock = new ReentrantLock(true);
|
||||
private int votePoints;
|
||||
private int voteTime = -1;
|
||||
private long lastNpcClick;
|
||||
@@ -1150,8 +1150,12 @@ public class MapleClient {
|
||||
}
|
||||
}
|
||||
|
||||
public final Lock getLock() {
|
||||
return mutex;
|
||||
public void lockClient() {
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
public void unlockClient() {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
private static class CharNameAndId {
|
||||
|
||||
@@ -50,7 +50,7 @@ public class MapleInventory implements Iterable<Item> {
|
||||
private byte slotLimit;
|
||||
private MapleInventoryType type;
|
||||
private boolean checked = false;
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Lock lock = new ReentrantLock(true);
|
||||
|
||||
public MapleInventory(MapleCharacter mc, MapleInventoryType type, byte slotLimit) {
|
||||
this.owner = mc;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ServerConstants {
|
||||
|
||||
public static final int PARTY_EXPERIENCE_MOD = 1; //Change for event stuff.
|
||||
|
||||
//Miscellaneous COnfiguration
|
||||
//Miscellaneous Configuration
|
||||
public static final byte MIN_UNDERLEVEL_FOR_EXP_GAIN = 5; //Characters are unable to get EXP from a mob if their level are under this threshold, only if "USE_UNDERLEVELED_EXP_BLOCK" is enabled.
|
||||
public static final byte MAX_MONITORED_BUFFSTATS = 5; //Limits accounting for "dormant" buff effects, that should take place when stronger stat buffs expires.
|
||||
public static final int MAX_AP = 32767; //Max AP allotted on the auto-assigner.
|
||||
|
||||
@@ -231,7 +231,7 @@ public final class PacketProcessor {
|
||||
registerHandler(RecvOpcode.ACCEPT_FAMILY, new AcceptFamilyHandler());
|
||||
registerHandler(RecvOpcode.DUEY_ACTION, new DueyHandler());
|
||||
registerHandler(RecvOpcode.USE_DEATHITEM, new UseDeathItemHandler());
|
||||
//registerHandler(RecvOpcode.PLAYER_UPDATE, new PlayerUpdateHandler());don't use unused stuff
|
||||
registerHandler(RecvOpcode.PLAYER_UPDATE, new PlayerUpdateHandler());
|
||||
registerHandler(RecvOpcode.USE_MAPLELIFE, new UseMapleLifeHandler());
|
||||
registerHandler(RecvOpcode.USE_CATCH_ITEM, new UseCatchItemHandler());
|
||||
registerHandler(RecvOpcode.MOB_DAMAGE_MOB_FRIENDLY, new MobDamageMobFriendlyHandler());
|
||||
|
||||
@@ -44,15 +44,14 @@ public class MaplePacketEncoder implements ProtocolEncoder {
|
||||
final byte[] header = send_crypto.getPacketHeader(unencrypted.length);
|
||||
MapleCustomEncryption.encryptData(unencrypted);
|
||||
|
||||
final Lock mutex = client.getLock();
|
||||
mutex.lock();
|
||||
client.lockClient();
|
||||
try {
|
||||
send_crypto.crypt(unencrypted);
|
||||
System.arraycopy(header, 0, ret, 0, 4);
|
||||
System.arraycopy(unencrypted, 0, ret, 4, unencrypted.length);
|
||||
out.write(IoBuffer.wrap(ret));
|
||||
} finally {
|
||||
mutex.unlock();
|
||||
client.unlockClient();
|
||||
}
|
||||
// System.arraycopy(unencrypted, 0, ret, 4, unencrypted.length);
|
||||
// out.write(ByteBuffer.wrap(ret));
|
||||
|
||||
@@ -33,24 +33,24 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
public class PlayerBuffStorage {
|
||||
private int id = (int) (Math.random() * 100);
|
||||
private final Lock mutex = new ReentrantLock();
|
||||
private Map<Integer, List<PlayerBuffValueHolder>> buffs = new HashMap<Integer, List<PlayerBuffValueHolder>>();
|
||||
private final Lock lock = new ReentrantLock(true);
|
||||
private Map<Integer, List<PlayerBuffValueHolder>> buffs = new HashMap<>();
|
||||
|
||||
public void addBuffsToStorage(int chrid, List<PlayerBuffValueHolder> toStore) {
|
||||
mutex.lock();
|
||||
lock.lock();
|
||||
try {
|
||||
buffs.put(chrid, toStore);//Old one will be replaced if it's in here.
|
||||
} finally {
|
||||
mutex.unlock();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public List<PlayerBuffValueHolder> getBuffsFromStorage(int chrid) {
|
||||
mutex.lock();
|
||||
lock.lock();
|
||||
try {
|
||||
return buffs.remove(chrid);
|
||||
} finally {
|
||||
mutex.unlock();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,11 +90,11 @@ public final class Channel {
|
||||
private Map<Integer, Integer> dojoParty = new HashMap<>();
|
||||
private Map<Integer, MapleMiniDungeon> dungeons = new HashMap<>();
|
||||
|
||||
private ReentrantReadWriteLock merchant_lock = new ReentrantReadWriteLock(true);
|
||||
private ReadLock merchRlock = merchant_lock.readLock();
|
||||
private WriteLock merchWlock = merchant_lock.writeLock();
|
||||
private ReentrantReadWriteLock merchantLock = new ReentrantReadWriteLock(true);
|
||||
private ReadLock merchRlock = merchantLock.readLock();
|
||||
private WriteLock merchWlock = merchantLock.writeLock();
|
||||
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Lock lock = new ReentrantLock(true);
|
||||
|
||||
public Channel(final int world, final int channel) {
|
||||
this.world = world;
|
||||
|
||||
@@ -41,7 +41,8 @@ public final class ChangeMapHandler extends AbstractMaplePacketHandler {
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
|
||||
if (chr.isBanned()) {
|
||||
if (chr.isChangingMaps() || chr.isBanned()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (chr.getTrade() != null) {
|
||||
|
||||
@@ -31,20 +31,21 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
public final class ChangeMapSpecialHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.readByte();
|
||||
String startwp = slea.readMapleAsciiString();
|
||||
slea.readShort();
|
||||
MaplePortal portal = c.getPlayer().getMap().getPortal(startwp);
|
||||
if (portal == null || c.getPlayer().portalDelay() > System.currentTimeMillis() || c.getPlayer().getBlockedPortals().contains(portal.getScriptName())) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().isBanned()) {
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().getTrade() != null) {
|
||||
MapleTrade.cancelTrade(c.getPlayer());
|
||||
}
|
||||
portal.enterPortal(c);
|
||||
slea.readByte();
|
||||
String startwp = slea.readMapleAsciiString();
|
||||
slea.readShort();
|
||||
MaplePortal portal = c.getPlayer().getMap().getPortal(startwp);
|
||||
if (portal == null || c.getPlayer().portalDelay() > System.currentTimeMillis() || c.getPlayer().getBlockedPortals().contains(portal.getScriptName())) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().isChangingMaps() || c.getPlayer().isBanned()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().getTrade() != null) {
|
||||
MapleTrade.cancelTrade(c.getPlayer());
|
||||
}
|
||||
portal.enterPortal(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,11 +229,10 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
} else if (!merchant.isOpen()) {
|
||||
c.announce(MaplePacketCreator.hiredMerchantMaintenanceMessage());
|
||||
return;
|
||||
} else if (merchant.getFreeSlotThreadsafe() == -1) {
|
||||
} else if (!merchant.addVisitor(c.getPlayer())) {
|
||||
chr.dropMessage(1, "This shop has reached it's maximum capacity, please come by later.");
|
||||
return;
|
||||
} else {
|
||||
merchant.addVisitor(c.getPlayer());
|
||||
c.announce(MaplePacketCreator.getHiredMerchant(c.getPlayer(), merchant, false));
|
||||
}
|
||||
chr.setHiredMerchant(merchant);
|
||||
|
||||
34
src/net/server/channel/handlers/PlayerUpdateHandler.java
Normal file
34
src/net/server/channel/handlers/PlayerUpdateHandler.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class PlayerUpdateHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
c.getPlayer().setMapTransitionComplete();
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ public final class StorageHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
if (chr.getLevel() < 15){
|
||||
chr.message("You may only use the storage once you have reached level 15.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (mode == 4) { // take out
|
||||
@@ -103,6 +104,7 @@ public final class StorageHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
if (quantity < 1 || chr.getItemQuantity(itemId, false) < quantity) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (storage.isFull()) {
|
||||
@@ -139,11 +141,13 @@ public final class StorageHandler extends AbstractMaplePacketHandler {
|
||||
if (meso < 0 && (storageMesos - meso) < 0) {
|
||||
meso = -2147483648 + storageMesos;
|
||||
if (meso < playerMesos) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
} else if (meso > 0 && (playerMesos + meso) < 0) {
|
||||
meso = 2147483647 - playerMesos;
|
||||
if (meso > storageMesos) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -151,6 +155,7 @@ public final class StorageHandler extends AbstractMaplePacketHandler {
|
||||
chr.gainMeso(meso, false, true, false);
|
||||
FilePrinter.print(FilePrinter.STORAGE + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + (meso > 0 ? " took out " : " stored ") + Math.abs(meso) + " mesos\r\n");
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
storage.sendMeso(c);
|
||||
|
||||
@@ -43,7 +43,7 @@ public class MapleParty {
|
||||
private Map<Integer, Integer> histMembers = new HashMap<>();
|
||||
private int nextEntry = 0;
|
||||
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Lock lock = new ReentrantLock(true);
|
||||
|
||||
public MapleParty(int id, MaplePartyCharacter chrfor) {
|
||||
this.leaderId = chrfor.getId();
|
||||
|
||||
@@ -79,31 +79,38 @@ public class World {
|
||||
private int id, flag, exprate, droprate, mesorate, bossdroprate;
|
||||
private String eventmsg;
|
||||
private List<Channel> channels = new ArrayList<>();
|
||||
private Map<Integer, MapleParty> parties = new HashMap<>();
|
||||
private AtomicInteger runningPartyId = new AtomicInteger();
|
||||
private Map<Integer, MapleMessenger> messengers = new HashMap<>();
|
||||
private AtomicInteger runningMessengerId = new AtomicInteger();
|
||||
private Map<Integer, MapleFamily> families = new LinkedHashMap<>();
|
||||
private Map<Integer, MapleGuildSummary> gsStore = new HashMap<>();
|
||||
private PlayerStorage players = new PlayerStorage();
|
||||
|
||||
private Set<Integer> queuedGuilds = new HashSet<>();
|
||||
|
||||
private Map<Integer, MapleParty> parties = new HashMap<>();
|
||||
private AtomicInteger runningPartyId = new AtomicInteger();
|
||||
private Lock partyLock = new ReentrantLock(true);
|
||||
|
||||
private Map<Integer, Integer> owlSearched = new LinkedHashMap<>();
|
||||
private Lock owlLock = new ReentrantLock();
|
||||
|
||||
private Lock activePetsLock = new ReentrantLock(true);
|
||||
private Map<Integer, Byte> activePets = new LinkedHashMap<>();
|
||||
private ScheduledFuture<?> petsSchedule;
|
||||
private long petUpdate;
|
||||
|
||||
private Lock activeMountsLock = new ReentrantLock(true);
|
||||
private Map<Integer, Byte> activeMounts = new LinkedHashMap<>();
|
||||
private ScheduledFuture<?> mountsSchedule;
|
||||
private long mountUpdate;
|
||||
|
||||
private Lock activePlayerShopsLock = new ReentrantLock(true);
|
||||
private Map<Integer, MaplePlayerShop> activePlayerShops = new LinkedHashMap<>();
|
||||
|
||||
private Lock activeMerchantsLock = new ReentrantLock(true);
|
||||
private Map<Integer, Pair<MapleHiredMerchant, Byte>> activeMerchants = new LinkedHashMap<>();
|
||||
private long merchantUpdate;
|
||||
|
||||
private Map<Integer, MaplePlayerShop> activePlayerShops = new LinkedHashMap<>();
|
||||
|
||||
private ScheduledFuture<?> charactersSchedule;
|
||||
|
||||
public World(int world, int flag, String eventmsg, int exprate, int droprate, int mesorate, int bossdroprate) {
|
||||
@@ -366,21 +373,32 @@ public class World {
|
||||
public MapleParty createParty(MaplePartyCharacter chrfor) {
|
||||
int partyid = runningPartyId.getAndIncrement();
|
||||
MapleParty party = new MapleParty(partyid, chrfor);
|
||||
synchronized(parties) {
|
||||
|
||||
partyLock.lock();
|
||||
try {
|
||||
parties.put(party.getId(), party);
|
||||
} finally {
|
||||
partyLock.unlock();
|
||||
}
|
||||
|
||||
return party;
|
||||
}
|
||||
|
||||
public MapleParty getParty(int partyid) {
|
||||
synchronized(parties) {
|
||||
partyLock.lock();
|
||||
try {
|
||||
return parties.get(partyid);
|
||||
} finally {
|
||||
partyLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public MapleParty disbandParty(int partyid) {
|
||||
synchronized(parties) {
|
||||
partyLock.lock();
|
||||
try {
|
||||
return parties.remove(partyid);
|
||||
} finally {
|
||||
partyLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,27 +784,39 @@ public class World {
|
||||
}
|
||||
|
||||
Integer key = getPetKey(chr, petSlot);
|
||||
synchronized(activePets) {
|
||||
|
||||
activePetsLock.lock();
|
||||
try {
|
||||
byte initProc;
|
||||
if(System.currentTimeMillis() - petUpdate > 55000) initProc = ServerConstants.PET_EXHAUST_COUNT - 2;
|
||||
else initProc = ServerConstants.PET_EXHAUST_COUNT - 1;
|
||||
|
||||
activePets.put(key, initProc);
|
||||
} finally {
|
||||
activePetsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterPetHunger(MapleCharacter chr, byte petSlot) {
|
||||
Integer key = getPetKey(chr, petSlot);
|
||||
synchronized(activePets) {
|
||||
|
||||
activePetsLock.lock();
|
||||
try {
|
||||
activePets.remove(key);
|
||||
} finally {
|
||||
activePetsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void runPetSchedule() {
|
||||
Map<Integer, Byte> deployedPets;
|
||||
synchronized(activePets) {
|
||||
|
||||
activePetsLock.lock();
|
||||
try {
|
||||
petUpdate = System.currentTimeMillis();
|
||||
deployedPets = Collections.unmodifiableMap(activePets);
|
||||
} finally {
|
||||
activePetsLock.unlock();
|
||||
}
|
||||
|
||||
for(Map.Entry<Integer, Byte> dp: deployedPets.entrySet()) {
|
||||
@@ -799,8 +829,11 @@ public class World {
|
||||
dpVal = 0;
|
||||
}
|
||||
|
||||
synchronized(activePets) {
|
||||
activePetsLock.lock();
|
||||
try {
|
||||
activePets.put(dp.getKey(), dpVal);
|
||||
} finally {
|
||||
activePetsLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -811,27 +844,37 @@ public class World {
|
||||
}
|
||||
|
||||
Integer key = chr.getId();
|
||||
synchronized(activeMounts) {
|
||||
activeMountsLock.lock();
|
||||
try {
|
||||
byte initProc;
|
||||
if(System.currentTimeMillis() - mountUpdate > 45000) initProc = ServerConstants.MOUNT_EXHAUST_COUNT - 2;
|
||||
else initProc = ServerConstants.MOUNT_EXHAUST_COUNT - 1;
|
||||
|
||||
activeMounts.put(key, initProc);
|
||||
} finally {
|
||||
activeMountsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterMountHunger(MapleCharacter chr) {
|
||||
Integer key = chr.getId();
|
||||
synchronized(activeMounts) {
|
||||
|
||||
activeMountsLock.lock();
|
||||
try {
|
||||
activeMounts.remove(key);
|
||||
} finally {
|
||||
activeMountsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void runMountSchedule() {
|
||||
Map<Integer, Byte> deployedMounts;
|
||||
synchronized(activeMounts) {
|
||||
activeMountsLock.lock();
|
||||
try {
|
||||
mountUpdate = System.currentTimeMillis();
|
||||
deployedMounts = Collections.unmodifiableMap(activeMounts);
|
||||
} finally {
|
||||
activeMountsLock.unlock();
|
||||
}
|
||||
|
||||
for(Map.Entry<Integer, Byte> dp: deployedMounts.entrySet()) {
|
||||
@@ -844,60 +887,82 @@ public class World {
|
||||
dpVal = 0;
|
||||
}
|
||||
|
||||
synchronized(activeMounts) {
|
||||
activeMountsLock.lock();
|
||||
try {
|
||||
activeMounts.put(dp.getKey(), dpVal);
|
||||
} finally {
|
||||
activeMountsLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerPlayerShop(MaplePlayerShop ps) {
|
||||
synchronized(activePlayerShops) {
|
||||
activePlayerShopsLock.lock();
|
||||
try {
|
||||
activePlayerShops.put(ps.getOwner().getId(), ps);
|
||||
} finally {
|
||||
activePlayerShopsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterPlayerShop(MaplePlayerShop ps) {
|
||||
synchronized(activePlayerShops) {
|
||||
activePlayerShopsLock.lock();
|
||||
try {
|
||||
activePlayerShops.remove(ps.getOwner().getId());
|
||||
} finally {
|
||||
activePlayerShopsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public List<MaplePlayerShop> getActivePlayerShops() {
|
||||
List<MaplePlayerShop> psList = new ArrayList<>();
|
||||
synchronized(activePlayerShops) {
|
||||
activePlayerShopsLock.lock();
|
||||
try {
|
||||
for(MaplePlayerShop mps : activePlayerShops.values()) {
|
||||
psList.add(mps);
|
||||
}
|
||||
|
||||
return psList;
|
||||
} finally {
|
||||
activePlayerShopsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public MaplePlayerShop getPlayerShop(int ownerid) {
|
||||
synchronized(activePlayerShops) {
|
||||
activePlayerShopsLock.lock();
|
||||
try {
|
||||
return activePlayerShops.get(ownerid);
|
||||
} finally {
|
||||
activePlayerShopsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerHiredMerchant(MapleHiredMerchant hm) {
|
||||
synchronized(activeMerchants) {
|
||||
activeMerchantsLock.lock();
|
||||
try {
|
||||
byte initProc;
|
||||
if(System.currentTimeMillis() - merchantUpdate > 5 * 60 * 1000) initProc = 1;
|
||||
else initProc = 0;
|
||||
|
||||
activeMerchants.put(hm.getOwnerId(), new Pair<>(hm, initProc));
|
||||
} finally {
|
||||
activeMerchantsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterHiredMerchant(MapleHiredMerchant hm) {
|
||||
synchronized(activeMerchants) {
|
||||
activeMerchantsLock.lock();
|
||||
try {
|
||||
activeMerchants.remove(hm.getOwnerId());
|
||||
} finally {
|
||||
activeMerchantsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void runHiredMerchantSchedule() {
|
||||
Map<Integer, Pair<MapleHiredMerchant, Byte>> deployedMerchants;
|
||||
synchronized(activeMerchants) {
|
||||
activeMerchantsLock.lock();
|
||||
try {
|
||||
merchantUpdate = System.currentTimeMillis();
|
||||
deployedMerchants = new LinkedHashMap<>(activeMerchants);
|
||||
|
||||
@@ -914,12 +979,15 @@ public class World {
|
||||
activeMerchants.remove(dm.getKey());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
activeMerchantsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public List<MapleHiredMerchant> getActiveMerchants() {
|
||||
List<MapleHiredMerchant> hmList = new ArrayList<>();
|
||||
synchronized(activeMerchants) {
|
||||
activeMerchantsLock.lock();
|
||||
try {
|
||||
for(Pair<MapleHiredMerchant, Byte> hmp : activeMerchants.values()) {
|
||||
MapleHiredMerchant hm = hmp.getLeft();
|
||||
if(hm.isOpen()) {
|
||||
@@ -928,16 +996,21 @@ public class World {
|
||||
}
|
||||
|
||||
return hmList;
|
||||
} finally {
|
||||
activeMerchantsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public MapleHiredMerchant getHiredMerchant(int ownerid) {
|
||||
synchronized(activeMerchants) {
|
||||
activeMerchantsLock.lock();
|
||||
try {
|
||||
if(activeMerchants.containsKey(ownerid)) {
|
||||
return activeMerchants.get(ownerid).getLeft();
|
||||
}
|
||||
|
||||
return null;
|
||||
} finally {
|
||||
activeMerchantsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,13 +87,16 @@ public class EventInstanceManager {
|
||||
private long timeStarted = 0;
|
||||
private long eventTime = 0;
|
||||
private MapleExpedition expedition = null;
|
||||
private List<Integer> mapIds = new LinkedList<Integer>();
|
||||
private List<Boolean> isInstanced = new LinkedList<Boolean>();
|
||||
private final ReentrantReadWriteLock mutex = new ReentrantReadWriteLock();
|
||||
private final Lock pL = new ReentrantLock();
|
||||
private List<Integer> mapIds = new LinkedList<>();
|
||||
private List<Boolean> isInstanced = new LinkedList<>();
|
||||
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
|
||||
private final ReadLock rL = lock.readLock();
|
||||
private final WriteLock wL = lock.writeLock();
|
||||
|
||||
private final Lock pL = new ReentrantLock(true);
|
||||
private final Lock sL = new ReentrantLock();
|
||||
private final ReadLock rL = mutex.readLock();
|
||||
private final WriteLock wL = mutex.writeLock();
|
||||
|
||||
private ScheduledFuture<?> event_schedule = null;
|
||||
private boolean disposed = false;
|
||||
private boolean eventCleared = false;
|
||||
|
||||
@@ -214,15 +214,6 @@ public class EventManager {
|
||||
return Integer.parseInt(props.getProperty(key));
|
||||
}
|
||||
|
||||
private boolean getLockLobby(int lobbyId) {
|
||||
lobbyLock.lock();
|
||||
try {
|
||||
return openedLobbys.get(lobbyId);
|
||||
} finally {
|
||||
lobbyLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void setLockLobby(int lobbyId, boolean lock) {
|
||||
lobbyLock.lock();
|
||||
try {
|
||||
@@ -239,11 +230,11 @@ public class EventManager {
|
||||
openedLobbys.set(lobbyId, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
lobbyLock.unlock();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void freeLobbyInstance(String lobbyName) {
|
||||
@@ -292,8 +283,7 @@ public class EventManager {
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(getLockLobby(lobbyId)) return false;
|
||||
startLobbyInstance(lobbyId);
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", leader.getClient().getChannel()));
|
||||
@@ -331,8 +321,7 @@ public class EventManager {
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(getLockLobby(lobbyId)) return false;
|
||||
startLobbyInstance(lobbyId);
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : leader.getId()));
|
||||
@@ -368,8 +357,7 @@ public class EventManager {
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(getLockLobby(lobbyId)) return false;
|
||||
startLobbyInstance(lobbyId);
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", (Object) null));
|
||||
@@ -406,8 +394,7 @@ public class EventManager {
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(getLockLobby(lobbyId)) return false;
|
||||
startLobbyInstance(lobbyId);
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
EventInstanceManager eim = (EventInstanceManager) (iv.invokeFunction("setup", difficulty, (lobbyId > -1) ? lobbyId : party.getLeaderId()));
|
||||
@@ -448,8 +435,7 @@ public class EventManager {
|
||||
if(lobbyId == -1) return false;
|
||||
}
|
||||
else {
|
||||
if(getLockLobby(lobbyId)) return false;
|
||||
startLobbyInstance(lobbyId);
|
||||
if(!startLobbyInstance(lobbyId)) return false;
|
||||
}
|
||||
|
||||
if(eim == null) {
|
||||
|
||||
@@ -31,6 +31,8 @@ import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import net.SendOpcode;
|
||||
import server.maps.AbstractMapleMapObject;
|
||||
import server.maps.MapleMapObjectType;
|
||||
@@ -53,6 +55,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
private List<String> bannedList = new ArrayList<>();
|
||||
private List<Pair<MapleCharacter, String>> chatLog = new LinkedList<>();
|
||||
private Map<Integer, Byte> chatSlot = new LinkedHashMap<>();
|
||||
private Lock visitorLock = new ReentrantLock(true);
|
||||
|
||||
public MaplePlayerShop(MapleCharacter owner, String description) {
|
||||
this.setPosition(owner.getPosition());
|
||||
@@ -322,8 +325,11 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void sendShop(MapleClient c) {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
c.announce(MaplePacketCreator.getPlayerShop(this, isOwner(c.getPlayer())));
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,11 +338,14 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public MapleCharacter[] getVisitors() {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
MapleCharacter[] copy = new MapleCharacter[3];
|
||||
for(int i = 0; i < visitors.length; i++) copy[i] = visitors[i];
|
||||
|
||||
return copy;
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,13 +379,16 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
MapleCharacter target = null;
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null && visitors[i].getName().equals(name)) {
|
||||
target = visitors[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
|
||||
if(target != null) {
|
||||
@@ -400,15 +412,17 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.hasFreeSlot() && !this.isVisitor(chr)) {
|
||||
this.addVisitor(chr);
|
||||
chr.setPlayerShop(this);
|
||||
this.sendShop(chr.getClient());
|
||||
synchronized (visitors) {
|
||||
if (this.hasFreeSlot() && !this.isVisitor(chr)) {
|
||||
this.addVisitor(chr);
|
||||
chr.setPlayerShop(this);
|
||||
this.sendShop(chr.getClient());
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<MaplePlayerShopItem> sendAvailableBundles(int itemid) {
|
||||
|
||||
@@ -191,6 +191,7 @@ public class MapleStatEffect {
|
||||
ret.duration *= 1000; // items have their times stored in ms, of course
|
||||
ret.overTime = overTime;
|
||||
}
|
||||
|
||||
ArrayList<Pair<MapleBuffStat, Integer>> statups = new ArrayList<>();
|
||||
ret.watk = (short) MapleDataTool.getInt("pad", source, 0);
|
||||
ret.wdef = (short) MapleDataTool.getInt("pdd", source, 0);
|
||||
@@ -206,15 +207,6 @@ public class MapleStatEffect {
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MAP_PROTECTION, Integer.valueOf(ret.mapProtection));
|
||||
|
||||
if (ret.overTime && ret.getSummonMovementType() == null) {
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WATK, Integer.valueOf(ret.watk));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WDEF, Integer.valueOf(ret.wdef));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MATK, Integer.valueOf(ret.matk));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MDEF, Integer.valueOf(ret.mdef));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.ACC, Integer.valueOf(ret.acc));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.AVOID, Integer.valueOf(ret.avoid));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.SPEED, Integer.valueOf(ret.speed));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
|
||||
|
||||
if(!skill) {
|
||||
if(isPyramidBuff(sourceid)) {
|
||||
ret.berserk = MapleDataTool.getInt("berserk", source, 0);
|
||||
@@ -273,7 +265,17 @@ public class MapleStatEffect {
|
||||
ret.speed *= 15;
|
||||
}
|
||||
}
|
||||
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WATK, Integer.valueOf(ret.watk));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.WDEF, Integer.valueOf(ret.wdef));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MATK, Integer.valueOf(ret.matk));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MDEF, Integer.valueOf(ret.mdef));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.ACC, Integer.valueOf(ret.acc));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.AVOID, Integer.valueOf(ret.avoid));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.SPEED, Integer.valueOf(ret.speed));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
|
||||
}
|
||||
|
||||
MapleData ltd = source.getChildByPath("lt");
|
||||
if (ltd != null) {
|
||||
ret.lt = (Point) ltd.getData();
|
||||
@@ -730,6 +732,7 @@ public class MapleStatEffect {
|
||||
applyto.toggleHide(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
int hpchange = calcHPChange(applyfrom, primary);
|
||||
int mpchange = calcMPChange(applyfrom, primary);
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -51,7 +50,7 @@ public class MapleStorage {
|
||||
private byte slots;
|
||||
private Map<MapleInventoryType, List<Item>> typeItems = new HashMap<>();
|
||||
private List<Item> items;
|
||||
private Lock lock = new ReentrantLock();
|
||||
private Lock lock = new ReentrantLock(true);
|
||||
|
||||
private MapleStorage(int id, byte slots, int meso) {
|
||||
this.id = id;
|
||||
@@ -224,6 +223,14 @@ public class MapleStorage {
|
||||
}
|
||||
|
||||
public void sendStorage(MapleClient c, int npcId) {
|
||||
/*
|
||||
if (c.getPlayer().getLevel() < 15){
|
||||
c.getPlayer().message("You may only use the storage once you have reached level 15.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
lock.lock();
|
||||
|
||||
@@ -14,7 +14,7 @@ import server.TimerManager;
|
||||
public class BalrogPQ {
|
||||
public static final int[] EasyBalrogParts = {8830002, 8830003, 8830000};
|
||||
public static final int[] HardBalrogParts = {8830000, 8830001, 8830002};
|
||||
public static List<MapleCharacter> candidates = new ArrayList<MapleCharacter>();
|
||||
public static List<MapleCharacter> candidates = new ArrayList<>();
|
||||
public static boolean hasStarted = false;
|
||||
public static String partyLeader = "undefined";
|
||||
public static boolean balrogSpawned = false;
|
||||
@@ -28,8 +28,10 @@ public class BalrogPQ {
|
||||
}
|
||||
|
||||
public static void warpAllCandidates(){
|
||||
for(MapleCharacter c : candidates){
|
||||
c.changeMap(105100300);
|
||||
synchronized(candidates){
|
||||
for(MapleCharacter c : candidates){
|
||||
c.changeMap(105100300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +50,7 @@ public class BalrogPQ {
|
||||
TimerManager tMan = TimerManager.getInstance();
|
||||
tMan.schedule(new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
public void run(){
|
||||
for(MapleCharacter chrs : fmap.getCharacters()){
|
||||
chrs.changeMap(105100100);
|
||||
chrs.message("You did not defeat the balrog in time..");
|
||||
@@ -57,9 +59,9 @@ public class BalrogPQ {
|
||||
}
|
||||
} , 60 * 60 * 1000);
|
||||
|
||||
tMan.schedule(new Runnable(){
|
||||
tMan.schedule(new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
public void run(){
|
||||
if(fmap.getCharacters().size() <= 3){
|
||||
if(fmap.getCharacters().size() > 0){
|
||||
for(MapleCharacter chrs : fmap.getCharacters()){
|
||||
@@ -92,7 +94,9 @@ public class BalrogPQ {
|
||||
hasStarted = false;
|
||||
balrogSpawned = false;
|
||||
partyLeader = "undefined";
|
||||
candidates.clear();
|
||||
synchronized(candidates){
|
||||
candidates.clear();
|
||||
}
|
||||
timeStamp = 0;
|
||||
}
|
||||
public static void spawnBalrog(int mode, MapleCharacter chr){
|
||||
|
||||
@@ -85,7 +85,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
private final HashMap<Integer, AtomicInteger> takenDamage = new HashMap<>();
|
||||
|
||||
private ReentrantLock externalLock = new ReentrantLock();
|
||||
private ReentrantLock monsterLock = new ReentrantLock();
|
||||
private ReentrantLock monsterLock = new ReentrantLock(true);
|
||||
private ReentrantLock statiLock = new ReentrantLock();
|
||||
|
||||
public MapleMonster(int id, MapleMonsterStats stats) {
|
||||
|
||||
@@ -36,6 +36,8 @@ import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import net.server.Server;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
@@ -50,7 +52,6 @@ import tools.Pair;
|
||||
* @author Ronan (concurrency protection)
|
||||
*/
|
||||
public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
|
||||
private int ownerId, itemId, mesos = 0;
|
||||
private int channel, world;
|
||||
private long start;
|
||||
@@ -62,6 +63,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
private List<SoldItem> sold = new LinkedList<>();
|
||||
private AtomicBoolean open = new AtomicBoolean();
|
||||
private MapleMap map;
|
||||
private Lock visitorLock = new ReentrantLock(true);
|
||||
|
||||
public MapleHiredMerchant(final MapleCharacter owner, int itemId, String desc) {
|
||||
this.setPosition(owner.getPosition());
|
||||
@@ -76,8 +78,11 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void broadcastToVisitorsThreadsafe(final byte[] packet) {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
broadcastToVisitors(packet);
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +95,8 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public boolean addVisitor(MapleCharacter visitor) {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
int i = this.getFreeSlot();
|
||||
if (i > -1) {
|
||||
visitors[i] = visitor;
|
||||
@@ -100,25 +106,33 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVisitor(MapleCharacter visitor) {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
int slot = getVisitorSlot(visitor);
|
||||
if (slot < 0){ //Not found
|
||||
return;
|
||||
if (slot < 0) { //Not found
|
||||
return;
|
||||
}
|
||||
if (visitors[slot] != null && visitors[slot].getId() == visitor.getId()) {
|
||||
visitors[slot] = null;
|
||||
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1));
|
||||
}
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getVisitorSlotThreadsafe(MapleCharacter visitor) {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
return getVisitorSlot(visitor);
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +146,8 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void removeAllVisitors() {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] != null) {
|
||||
visitors[i].setHiredMerchant(null);
|
||||
@@ -143,6 +158,8 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
visitors[i] = null;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,11 +331,14 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public MapleCharacter[] getVisitors() {
|
||||
synchronized(visitors) {
|
||||
visitorLock.lock();
|
||||
try {
|
||||
MapleCharacter[] copy = new MapleCharacter[3];
|
||||
for(int i = 0; i < visitors.length; i++) copy[i] = visitors[i];
|
||||
|
||||
return copy;
|
||||
} finally {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,12 +382,6 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
public int getFreeSlotThreadsafe() {
|
||||
synchronized(visitors) {
|
||||
return getFreeSlot();
|
||||
}
|
||||
}
|
||||
|
||||
private int getFreeSlot() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (visitors[i] == null) {
|
||||
|
||||
@@ -2724,7 +2724,6 @@ public class MapleMap {
|
||||
if (reactor.getShouldCollect() == true && mapitem != null && mapitem == getMapObject(mapitem.getObjectId())) {
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
TimerManager tMan = TimerManager.getInstance();
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
@@ -2735,6 +2734,7 @@ public class MapleMap {
|
||||
reactor.hitReactor(c);
|
||||
|
||||
if (reactor.getDelay() > 0) {
|
||||
TimerManager tMan = TimerManager.getInstance();
|
||||
tMan.schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -22,7 +22,7 @@ import tools.MaplePacketCreator;
|
||||
public class MapleMiniDungeon {
|
||||
List<MapleCharacter> players = new ArrayList<>();
|
||||
ScheduledFuture<?> timeoutTask = null;
|
||||
Lock lock = new ReentrantLock();
|
||||
Lock lock = new ReentrantLock(true);
|
||||
|
||||
int baseMap;
|
||||
long expireTime;
|
||||
|
||||
@@ -59,7 +59,7 @@ public class MapleReactor extends AbstractMapleMapObject {
|
||||
this.evstate = (byte)0;
|
||||
this.stats = stats;
|
||||
this.rid = rid;
|
||||
alive = true;
|
||||
this.alive = true;
|
||||
}
|
||||
|
||||
public void setShouldCollect(boolean collect) {
|
||||
|
||||
@@ -84,7 +84,7 @@ public class DatabaseConnection {
|
||||
config.setMaximumPoolSize(poolSize);
|
||||
|
||||
config.addDataSourceProperty("cachePrepStmts", true);
|
||||
config.addDataSourceProperty("prepStmtCacheSize", 250);
|
||||
config.addDataSourceProperty("prepStmtCacheSize", 25);
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
|
||||
|
||||
ds = new HikariDataSource(config);
|
||||
|
||||
Reference in New Issue
Block a user