Major schedules & DB refactor

Refactored many calls for TimerManager's schedules throughout the source.
Switched all tables using MyISAM to InnoDB: on a multi-threaded environment such as this, table-locking is an instant no-no, and other gains MyISAM would have over InnoDB are minimal.
Altered getConnection() to properly throw an exception (good practice!) in case of no available connection instead of a mere null.
This commit is contained in:
ronancpl
2017-11-09 20:20:21 -02:00
parent 9677e6f3f5
commit c46ff82929
35 changed files with 600 additions and 374 deletions

View File

@@ -257,6 +257,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private Map<Integer, MapleCoolDownValueHolder> coolDowns = new LinkedHashMap<>();
private EnumMap<MapleDisease, MapleDiseaseValueHolder> diseases = new EnumMap<>(MapleDisease.class);
private Map<Integer, MapleDoor> doors = new LinkedHashMap<>();
private Map<MapleQuest, Long> questExpirations = new LinkedHashMap<>();
private ScheduledFuture<?> dragonBloodSchedule;
private ScheduledFuture<?> hpDecreaseTask;
private ScheduledFuture<?> beholderHealingSchedule, beholderBuffSchedule, berserkSchedule;
@@ -264,14 +265,14 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private ScheduledFuture<?> buffExpireTask = null;
private ScheduledFuture<?> itemExpireTask = null;
private ScheduledFuture<?> diseaseExpireTask = null;
private ScheduledFuture<?> questExpireTask = null;
private ScheduledFuture<?> recoveryTask = null;
private ScheduledFuture<?> extraRecoveryTask = null;
private ScheduledFuture<?> chairRecoveryTask = null;
private ScheduledFuture<?> pendantOfSpirit = null; //1122017
private List<ScheduledFuture<?>> timers = new ArrayList<>();
private Lock chrLock = new ReentrantLock(true);
private Lock effLock = new ReentrantLock(true);
private Lock petLock = new ReentrantLock(true);
private Lock petLock = new ReentrantLock(true); // for quest tasks as well
private Lock prtLock = new ReentrantLock();
private Map<Integer, Set<Integer>> excluded = new LinkedHashMap<>();
private Set<Integer> excludedItems = new LinkedHashSet<>();
@@ -2088,13 +2089,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
addHP(-getMap().getHPDec());
lastHpDec = System.currentTimeMillis();
}
hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() {
}
private void startHpDecreaseTask(long lastHpTask) {
hpDecreaseTask = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
doHurtHp();
}
}, 10000);
}, 10000, 10000 - lastHpTask);
}
public void resetHpDecreaseTask() {
@@ -2103,16 +2106,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
long lastHpTask = System.currentTimeMillis() - lastHpDec;
if(lastHpTask >= 10000) {
doHurtHp();
} else {
hpDecreaseTask = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
doHurtHp();
}
}, 10000 - lastHpTask);
}
startHpDecreaseTask((lastHpTask > 10000) ? 10000 : lastHpTask);
}
public void dropMessage(String message) {
@@ -2127,10 +2121,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return nf.format(MapleGuild.CHANGE_EMBLEM_COST);
}
public List<ScheduledFuture<?>> getTimers() {
return timers;
}
private void enforceMaxHpMp() {
List<Pair<MapleStat, Integer>> stats = new ArrayList<>(2);
if (getMp() > getCurrentMaxMp()) {
@@ -7221,7 +7211,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public void showNote() {
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM notes WHERE `to`=? AND `deleted` = 0", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) {
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM notes WHERE `to` = ? AND `deleted` = 0", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) {
ps.setString(1, this.getName());
try (ResultSet rs = ps.executeQuery()) {
rs.last();
@@ -7466,15 +7456,83 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
updateQuest(newStatus);
}
public void questTimeLimit(final MapleQuest quest, int seconds) {
ScheduledFuture<?> sf = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
expireQuest(quest);
public void cancelQuestExpirationTask() {
petLock.lock();
try {
if (questExpireTask != null) {
questExpireTask.cancel(false);
questExpireTask = null;
}
}, seconds * 1000);
} finally {
petLock.unlock();
}
}
public void questExpirationTask() {
petLock.lock();
try {
if(!questExpirations.isEmpty()) {
if(questExpireTask == null) {
questExpireTask = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
runQuestExpireTask();
}
}, 10 * 1000);
}
}
} finally {
petLock.unlock();
}
}
private void runQuestExpireTask() {
petLock.lock();
try {
long timeNow = System.currentTimeMillis();
List<MapleQuest> expireList = new LinkedList<>();
for(Entry<MapleQuest, Long> qe : questExpirations.entrySet()) {
if(qe.getValue() <= timeNow) expireList.add(qe.getKey());
}
if(!expireList.isEmpty()) {
for(MapleQuest quest : expireList) {
expireQuest(quest);
questExpirations.remove(quest);
}
if(questExpirations.isEmpty()) {
questExpireTask.cancel(false);
questExpireTask = null;
}
}
} finally {
petLock.unlock();
}
}
private void registerQuestExpire(MapleQuest quest, long time) {
petLock.lock();
try {
if(questExpireTask == null) {
questExpireTask = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
runQuestExpireTask();
}
}, 10 * 1000);
}
questExpirations.put(quest, System.currentTimeMillis() + time);
} finally {
petLock.unlock();
}
}
public void questTimeLimit(final MapleQuest quest, int seconds) {
registerQuestExpire(quest, seconds * 1000);
announce(MaplePacketCreator.addQuestTimeLimit(quest.getId(), seconds * 1000));
timers.add(sf);
}
public void questTimeLimit2(final MapleQuest quest, long expires) {
@@ -7483,14 +7541,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if(timeLeft <= 0) {
expireQuest(quest);
} else {
ScheduledFuture<?> sf = TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
expireQuest(quest);
}
}, timeLeft);
timers.add(sf);
registerQuestExpire(quest, timeLeft);
}
}
@@ -7903,10 +7954,19 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
cancelSkillCooldownTask();
cancelExpirationTask();
for (ScheduledFuture<?> sf : timers) {
sf.cancel(false);
petLock.lock();
try {
if (questExpireTask != null) {
questExpireTask.cancel(false);
questExpireTask = null;
questExpirations.clear();
questExpirations = null;
}
} finally {
petLock.unlock();
}
timers.clear();
if (maplemount != null) {
maplemount.empty();
maplemount = null;
@@ -7921,7 +7981,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
family = null;
client = null;
map = null;
timers = null;
}
}

View File

@@ -41,7 +41,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -70,7 +69,6 @@ import scripting.quest.QuestActionManager;
import scripting.quest.QuestScriptManager;
import server.life.MapleMonster;
import server.MapleTrade;
import server.TimerManager;
import server.maps.*;
import server.quest.MapleQuest;
import tools.LogHelper;
@@ -101,7 +99,6 @@ public class MapleClient {
private int gmlevel;
private Set<String> macs = new HashSet<>();
private Map<String, ScriptEngine> engines = new HashMap<>();
private ScheduledFuture<?> idleTask = null;
private byte characterSlots = 3;
private byte loginattempt = 0;
private String pin = null;
@@ -941,15 +938,13 @@ public class MapleClient {
}
private void clear() { //usable when defining client = null shortly after
Server.getInstance().unregisterLoginState(this);
this.accountName = null;
this.macs = null;
this.hwid = null;
this.birthday = null;
//this.engines = null;
if (this.idleTask != null) {
this.idleTask.cancel(true);
this.idleTask = null;
}
this.player = null;
this.receive = null;
this.send = null;
@@ -1005,25 +1000,17 @@ public class MapleClient {
lastPong = System.currentTimeMillis();
}
public void sendPing() {
final long then = System.currentTimeMillis();
announce(MaplePacketCreator.getPing());
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
try {
if (lastPong < then) {
if (session != null && session.isConnected()) {
session.close(false);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}, 15000);
}
public void testPing(long timeThen) {
try {
if (lastPong < timeThen) {
if (session != null && session.isConnected()) {
session.close(false);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public String getHWID() {
return hwid;
@@ -1053,14 +1040,6 @@ public class MapleClient {
engines.remove(name);
}
public ScheduledFuture<?> getIdleTask() {
return idleTask;
}
public void setIdleTask(ScheduledFuture<?> idleTask) {
this.idleTask = idleTask;
}
public NPCConversationManager getCM() {
return NPCScriptManager.getInstance().getCM(this);
}
@@ -1321,6 +1300,7 @@ public class MapleClient {
player.cancelBuffExpireTask();
player.cancelDiseaseExpireTask();
player.cancelSkillCooldownTask();
player.cancelQuestExpirationTask();
//Cancelling magicdoor? Nope
//Cancelling mounts? Noty
if (player.getBuffedValue(MapleBuffStat.PUPPET) != null) {

View File

@@ -349,6 +349,10 @@ public class Commands {
break;
case "staff":
player.yellowMessage("MapleSolaxiaV2 Staff");
player.yellowMessage("Ronan - Developer");
player.yellowMessage("Vcoc - Freelance Developer");
player.yellowMessage("");
player.yellowMessage("MapleSolaxia Staff");
player.yellowMessage("Aria - Administrator");
player.yellowMessage("Twdtwd - Administrator");
@@ -358,9 +362,6 @@ public class Commands {
player.yellowMessage("SourMjolk - Game Master");
player.yellowMessage("Kanade - Game Master");
player.yellowMessage("Kitsune - Game Master");
player.yellowMessage("MapleSolaxiaV2 Staff");
player.yellowMessage("Ronan - Freelance Developer");
player.yellowMessage("Vcoc - Freelance Developer");
break;
case "lastrestart":
@@ -451,7 +452,7 @@ public class Commands {
output += "#b" + data.getRight() + "#k is dropped by:\r\n";
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM drop_data WHERE itemid = ? LIMIT 50");
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE itemid = ? LIMIT 50");
ps.setInt(1, data.getLeft());
ResultSet rs = ps.executeQuery();
while(rs.next()) {
@@ -1513,11 +1514,13 @@ public class Commands {
case "reloadmap":
MapleMap oldMap = c.getPlayer().getMap();
MapleMap newMap = c.getChannelServer().getMapFactory().getMap(player.getMapId());
MapleMap newMap = c.getChannelServer().getMapFactory().resetMap(player.getMapId());
int callerid = c.getPlayer().getId();
for (MapleCharacter ch : oldMap.getCharacters()) {
ch.changeMap(newMap);
if(ch.getId() != callerid) ch.dropMessage("You have been relocated due to map reloading. Sorry for the inconvenience.");
}
oldMap = null;
newMap.respawn();
break;