Dynamic World/Channel deployment + Channel scheduler update
Added "8-slot SETUP expand" item on the CashShop. Solved a concurrency issue on the fameGainByQuest method. Refactored many resource freeing modules throughout the source code. Implemented dynamic deployment of worlds and channels on the server system. Only creation of channels and worlds are available on this feature. Added a dedicated worker for schedules requested on EventManager. Fixed a potential cause for deadlocks on the channel schedulers' system. Refactored many schedules used by the EventManager and Channel, futher improving overall scheduling performance on the server.
This commit is contained in:
@@ -119,7 +119,7 @@ public class MapleStorage {
|
||||
return slots;
|
||||
}
|
||||
|
||||
public boolean gainSlots(int slots) {
|
||||
public synchronized boolean gainSlots(int slots) {
|
||||
slots += this.slots;
|
||||
|
||||
if (slots <= 48) {
|
||||
@@ -129,11 +129,7 @@ public class MapleStorage {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSlots(byte set) {
|
||||
this.slots = set;
|
||||
}
|
||||
|
||||
|
||||
public void saveToDB(Connection con) {
|
||||
try {
|
||||
try (PreparedStatement ps = con.prepareStatement("UPDATE storages SET slots = ?, meso = ? WHERE storageid = ?")) {
|
||||
|
||||
@@ -54,7 +54,6 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
@@ -95,10 +94,10 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
private int parentMobOid = 0;
|
||||
private final HashMap<Integer, AtomicInteger> takenDamage = new HashMap<>();
|
||||
|
||||
private Lock externalLock = new MonitoredReentrantLock(MonitoredLockType.MOB_EXT);
|
||||
private Lock monsterLock = new MonitoredReentrantLock(MonitoredLockType.MOB, true);
|
||||
private Lock statiLock = new MonitoredReentrantLock(MonitoredLockType.MOB_STATI);
|
||||
private Lock animationLock = new MonitoredReentrantLock(MonitoredLockType.MOB_ANI);
|
||||
private MonitoredReentrantLock externalLock = new MonitoredReentrantLock(MonitoredLockType.MOB_EXT);
|
||||
private MonitoredReentrantLock monsterLock = new MonitoredReentrantLock(MonitoredLockType.MOB, true);
|
||||
private MonitoredReentrantLock statiLock = new MonitoredReentrantLock(MonitoredLockType.MOB_STATI);
|
||||
private MonitoredReentrantLock animationLock = new MonitoredReentrantLock(MonitoredLockType.MOB_ANI);
|
||||
|
||||
public MapleMonster(int id, MapleMonsterStats stats) {
|
||||
super(id);
|
||||
@@ -1476,4 +1475,11 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
public final void changeDifficulty(final int difficulty, boolean pqMob) {
|
||||
changeLevelByDifficulty(difficulty, pqMob);
|
||||
}
|
||||
|
||||
public final void disposeLocks() {
|
||||
externalLock.dispose();
|
||||
monsterLock.dispose();
|
||||
statiLock.dispose();
|
||||
animationLock.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ public class MaplePlayerNPC extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
private static void getRunningWorldRanks(Connection con) throws SQLException {
|
||||
int numWorlds = Server.getInstance().getWorlds().size();
|
||||
int numWorlds = Server.getInstance().getWorldsSize();
|
||||
for(int i = 0; i < numWorlds; i++) {
|
||||
runningWorldRank.add(new AtomicInteger(1));
|
||||
}
|
||||
@@ -625,7 +625,7 @@ public class MaplePlayerNPC extends AbstractMapleMapObject {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT DISTINCT world, map FROM playernpcs");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
int wsize = Server.getInstance().getWorlds().size();
|
||||
int wsize = Server.getInstance().getWorldsSize();
|
||||
while(rs.next()) {
|
||||
int world = rs.getInt("world"), map = rs.getInt("map");
|
||||
if(world >= wsize) continue;
|
||||
|
||||
@@ -2103,6 +2103,10 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerMapSchedule(Runnable r, long delay) {
|
||||
this.getChannelServer().registerOverallAction(mapid, r, delay);
|
||||
}
|
||||
|
||||
private void activateItemReactors(final MapleMapItem drop, final MapleClient c) {
|
||||
final Item item = drop.getItem();
|
||||
|
||||
@@ -2113,7 +2117,7 @@ public class MapleMap {
|
||||
if (react.getReactItem(react.getEventState()).getLeft() == item.getItemId() && react.getReactItem(react.getEventState()).getRight() == item.getQuantity()) {
|
||||
|
||||
if (react.getArea().contains(drop.getPosition())) {
|
||||
TimerManager.getInstance().schedule(new ActivateItemReactor(drop, react, c), 5000);
|
||||
registerMapSchedule(new ActivateItemReactor(drop, react, c), 5000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2151,7 +2155,7 @@ public class MapleMap {
|
||||
if (reactArea.contains(drop.getPosition())) {
|
||||
MapleClient owner = drop.getOwnerClient();
|
||||
if(owner != null) {
|
||||
TimerManager.getInstance().schedule(new ActivateItemReactor(drop, react, owner), 5000);
|
||||
registerMapSchedule(new ActivateItemReactor(drop, react, owner), 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2173,13 +2177,16 @@ public class MapleMap {
|
||||
}
|
||||
mapEffect = new MapleMapEffect(msg, itemId);
|
||||
broadcastMessage(mapEffect.makeStartData());
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
broadcastMessage(mapEffect.makeDestroyData());
|
||||
mapEffect = null;
|
||||
}
|
||||
}, time);
|
||||
};
|
||||
|
||||
registerMapSchedule(r, time);
|
||||
}
|
||||
|
||||
public MapleCharacter getAnyCharacterFromParty(int partyid) {
|
||||
@@ -3807,4 +3814,37 @@ public class MapleMap {
|
||||
spawnMonsterOnGroundBelow(m, targetPoint);
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
for(MapleMonster mm : this.getMonsters()) {
|
||||
mm.disposeLocks();
|
||||
}
|
||||
|
||||
clearMapObjects();
|
||||
|
||||
event = null;
|
||||
footholds = null;
|
||||
portals.clear();
|
||||
mapEffect = null;
|
||||
|
||||
if(mapMonitor != null) {
|
||||
mapMonitor.cancel(false);
|
||||
mapMonitor = null;
|
||||
}
|
||||
|
||||
chrWLock.lock();
|
||||
try {
|
||||
if(itemMonitor != null) {
|
||||
itemMonitor.cancel(false);
|
||||
itemMonitor = null;
|
||||
}
|
||||
|
||||
if(expireItemsTask != null) {
|
||||
expireItemsTask.cancel(false);
|
||||
expireItemsTask = null;
|
||||
}
|
||||
} finally {
|
||||
chrWLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +437,10 @@ public class MapleMapFactory {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
|
||||
for(MapleMap map: mapValues) map.setEventInstance(null);
|
||||
for(MapleMap map: mapValues) {
|
||||
map.dispose();
|
||||
}
|
||||
|
||||
this.event = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import tools.MaplePacketCreator;
|
||||
*/
|
||||
public class MapleTVEffect {
|
||||
|
||||
private final static boolean ACTIVE[] = new boolean[Server.getInstance().getWorlds().size()];
|
||||
private final static boolean ACTIVE[] = new boolean[Server.getInstance().getWorldsSize()];
|
||||
|
||||
public static synchronized boolean broadcastMapleTVIfNotActive(MapleCharacter player, MapleCharacter victim, List<String> messages, int tvType){
|
||||
int w = player.getWorld();
|
||||
|
||||
Reference in New Issue
Block a user