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:
ronancpl
2018-07-23 20:45:41 -03:00
parent bee8b5259b
commit 8aadf7c369
48 changed files with 1152 additions and 260 deletions
+2 -6
View File
@@ -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 = ?")) {
+11 -5
View File
@@ -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();
}
}
+2 -2
View File
@@ -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;
+44 -4
View File
@@ -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();
}
}
}
+4 -1
View File
@@ -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;
}
}
+1 -1
View File
@@ -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();