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;

View File

@@ -85,6 +85,7 @@ public class ServerConstants {
//Dangling Items Configuration
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
public static final int ITEM_MONITOR_TIME = 5 * 60 * 1000; //Interval between item monitoring tasks on maps, which checks for dangling (null) item objects on the map item history.
public static final int ITEM_EXPIRE_CHECK = 10 * 1000; //Interval between item expiring tasks on maps, which checks and makes disappear expired items.
public static final int ITEM_LIMIT_ON_MAP = 200; //Max number of items allowed on a map.
//Some Gameplay Enhancing Configurations

View File

@@ -42,6 +42,15 @@ import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleClient;
import constants.ServerConstants;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.ScheduledFuture;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import server.TimerManager;
public class MapleServerHandler extends IoHandlerAdapter {
private PacketProcessor processor;
@@ -49,16 +58,26 @@ public class MapleServerHandler extends IoHandlerAdapter {
private static final SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
private static AtomicLong sessionId = new AtomicLong(7777);
private Lock idleLock = new ReentrantLock(true);
private Lock tempLock = new ReentrantLock(true);
private Map<MapleClient, Long> idleSessions = new HashMap<>(100);
private Map<MapleClient, Long> tempIdleSessions = new HashMap<>();
private ScheduledFuture<?> idleManager = null;
public MapleServerHandler() {
this.processor = PacketProcessor.getProcessor(-1, -1);
idleManagerTask();
}
public MapleServerHandler(int world, int channel) {
this.processor = PacketProcessor.getProcessor(world, channel);
this.world = world;
this.channel = channel;
idleManagerTask();
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
System.out.println("disconnect by exception");
@@ -155,8 +174,70 @@ public class MapleServerHandler extends IoHandlerAdapter {
public void sessionIdle(final IoSession session, final IdleStatus status) throws Exception {
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
if (client != null) {
client.sendPing();
registerIdleSession(client);
}
super.sessionIdle(session, status);
}
private void registerIdleSession(MapleClient c) {
if(idleLock.tryLock()) {
idleSessions.put(c, System.currentTimeMillis());
c.announce(MaplePacketCreator.getPing());
idleLock.unlock();
} else {
tempLock.lock();
try {
tempIdleSessions.put(c, System.currentTimeMillis());
c.announce(MaplePacketCreator.getPing());
} finally {
tempLock.unlock();
}
}
}
private void manageIdleSessions() {
long timeNow = System.currentTimeMillis();
long timeThen = timeNow - 15000;
idleLock.lock();
try {
for(Entry<MapleClient, Long> mc : idleSessions.entrySet()) {
if(timeNow - mc.getValue() >= 15000) {
mc.getKey().testPing(timeThen);
}
}
idleSessions.clear();
if(!tempIdleSessions.isEmpty()) {
tempLock.lock();
try {
for(Entry<MapleClient, Long> mc : tempIdleSessions.entrySet()) {
idleSessions.put(mc.getKey(), mc.getValue());
}
tempIdleSessions.clear();
} finally {
tempLock.unlock();
}
}
} finally {
idleLock.unlock();
}
}
private void idleManagerTask() {
this.idleManager = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
manageIdleSessions();
}
}, 10000);
}
private void cancelIdleManagerTask() {
this.idleManager.cancel(false);
this.idleManager = null;
}
}

View File

@@ -132,7 +132,7 @@ public enum SendOpcode {
NOTIFY_LEVELUP(0x69),
NOTIFY_MARRIAGE(0x6A),
NOTIFY_JOB_CHANGE(0x6B),
//SET_BUY_EQUIP_EXT(0x6C),//lol?
//SET_BUY_EQUIP_EXT(0x6C), //probably extra pendant slot for other versions?
MAPLE_TV_USE_RES(0x6D), //It's not blank, It's a popup nibs
AVATAR_MEGAPHONE_RESULT(0x6E),//bot useless..
SET_AVATAR_MEGAPHONE(0x6F),
@@ -145,7 +145,7 @@ public enum SendOpcode {
NEW_YEAR_CARD_RES(0x76),
RANDOM_MORPH_RES(0x77),
CANCEL_NAME_CHANGE_BY_OTHER(0x78),
SET_BUY_EQUIP_EXT(0x79),
SET_EXTRA_PENDANT_SLOT(0x79),
SCRIPT_PROGRESS_MESSAGE(0x7A),
DATA_CRC_CHECK_FAILED(0x7B),
MACRO_SYS_DATA_INIT(0x7C),

View File

@@ -37,6 +37,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
@@ -63,6 +64,7 @@ import server.TimerManager;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.Pair;
import client.MapleClient;
import client.MapleCharacter;
import client.SkillFactory;
import constants.ItemConstants;
@@ -82,7 +84,8 @@ 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 Map<MapleClient, Long> inLoginState = new LinkedHashMap<>();
private final Lock srvLock = new ReentrantLock();
private final PlayerBuffStorage buffStorage = new PlayerBuffStorage();
private final Map<Integer, MapleAlliance> alliances = new LinkedHashMap<>();
private boolean online = false;
@@ -279,6 +282,7 @@ public class Server implements Runnable {
TimerManager tMan = TimerManager.getInstance();
tMan.start();
tMan.register(tMan.purge(), ServerConstants.PURGING_INTERVAL);//Purging ftw...
disconnectIdlesOnLoginTask();
long timeLeft = getTimeLeftForNextHour();
tMan.register(new CouponWorker(), ServerConstants.COUPON_INTERVAL, timeLeft);
@@ -720,11 +724,64 @@ public class Server implements Runnable {
return worlds;
}
public void registerLoginState(MapleClient c) {
srvLock.lock();
try {
inLoginState.put(c, System.currentTimeMillis() + 600000);
} finally {
srvLock.unlock();
}
}
public void unregisterLoginState(MapleClient c) {
srvLock.lock();
try {
inLoginState.remove(c);
} finally {
srvLock.unlock();
}
}
private void disconnectIdlesOnLoginState() {
srvLock.lock();
try {
List<MapleClient> toDisconnect = new LinkedList<>();
long timeNow = System.currentTimeMillis();
for(Entry<MapleClient, Long> mc : inLoginState.entrySet()) {
if(timeNow > mc.getValue()) {
toDisconnect.add(mc.getKey());
}
}
for(MapleClient c : toDisconnect) {
if(c.isLoggedIn()) {
c.disconnect(false, false);
} else {
c.getSession().close(true);
}
inLoginState.remove(c);
}
} finally {
srvLock.unlock();
}
}
private void disconnectIdlesOnLoginTask() {
TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
disconnectIdlesOnLoginState();
}
}, 300000);
}
public final Runnable shutdown(final boolean restart) {//no player should be online when trying to shutdown!
return new Runnable() {
@Override
public void run() {
shutdownLock.lock();
srvLock.lock();
try {
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
@@ -788,7 +845,7 @@ public class Server implements Runnable {
getInstance().run();//DID I DO EVERYTHING?! D:
}
} finally {
shutdownLock.unlock();
srvLock.unlock();
}
}
};

View File

@@ -297,7 +297,7 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
if (mc.getGuildId() <= 0) {
return;
}
Connection con = null;
Connection con;
try {
con = DatabaseConnection.getConnection();
PreparedStatement ps2;

View File

@@ -65,6 +65,7 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
mc.cancelDiseaseExpireTask();
mc.cancelSkillCooldownTask();
mc.cancelExpirationTask();
mc.cancelQuestExpirationTask();
c.announce(MaplePacketCreator.openCashShop(c, false));
c.announce(MaplePacketCreator.showCashInventory(c));

View File

@@ -74,6 +74,7 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
chr.cancelDiseaseExpireTask();
chr.cancelSkillCooldownTask();
chr.cancelExpirationTask();
chr.cancelQuestExpirationTask();
chr.saveToDB();
chr.getMap().removePlayer(c.getPlayer());

View File

@@ -343,15 +343,15 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
}
} else if (op == 9) { //add to cart
int id = slea.readInt(); //id of the item
Connection con = null;
Connection con;
try {
con = DatabaseConnection.getConnection();
try (PreparedStatement ps1 = con.prepareStatement("SELECT * FROM mts_items WHERE id = ? AND seller <> ?")) {
ps1.setInt(1, id);//Previene que agregues al cart tus propios items
try (PreparedStatement ps1 = con.prepareStatement("SELECT id FROM mts_items WHERE id = ? AND seller <> ?")) {
ps1.setInt(1, id); //Dummy query, prevents adding to cart self owned items
ps1.setInt(2, c.getPlayer().getId());
try (ResultSet rs1 = ps1.executeQuery()) {
if (rs1.next()) {
PreparedStatement ps = con.prepareStatement("SELECT * FROM mts_cart WHERE cid = ? AND itemid = ?");
PreparedStatement ps = con.prepareStatement("SELECT cid FROM mts_cart WHERE cid = ? AND itemid = ?");
ps.setInt(1, c.getPlayer().getId());
ps.setInt(2, id);
try (ResultSet rs = ps.executeQuery()) {

View File

@@ -267,6 +267,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
player.diseaseExpireTask();
player.skillCooldownTask();
player.expirationTask();
player.questExpirationTask();
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
player.createDragon();
}

View File

@@ -208,7 +208,7 @@ public class MapleAlliance {
ps.close();
rs.close();
ps = con.prepareStatement("SELECT * FROM allianceguilds WHERE allianceid = ?");
ps = con.prepareStatement("SELECT guildid FROM allianceguilds WHERE allianceid = ?");
ps.setInt(1, id);
rs = ps.executeQuery();

View File

@@ -26,10 +26,12 @@ import net.MaplePacketHandler;
import tools.data.input.SeekableLittleEndianAccessor;
public class KeepAliveHandler implements MaplePacketHandler {
@Override
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
c.pongReceived();
}
@Override
public boolean validateState(MapleClient c) {
return true;
}

View File

@@ -41,9 +41,7 @@ public final class CharSelectedHandler extends AbstractMaplePacketHandler {
return;
}
if (c.getIdleTask() != null) {
c.getIdleTask().cancel(true);
}
Server.getInstance().unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
String[] socket = Server.getInstance().getIP(c.getWorld(), c.getChannel()).split(":");
try {

View File

@@ -26,9 +26,7 @@ public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
return;
}
if (c.checkPic(pic)) {
if (c.getIdleTask() != null) {
c.getIdleTask().cancel(true);
}
Server.getInstance().unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
String[] socket = Server.getInstance().getIP(c.getWorld(), c.getChannel()).split(":");

View File

@@ -24,6 +24,7 @@ package net.server.handlers.login;
import java.util.Calendar;
import net.MaplePacketHandler;
import net.server.Server;
import server.TimerManager;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
@@ -73,12 +74,7 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
private static void login(MapleClient c){
c.announce(MaplePacketCreator.getAuthSuccess(c));//why the fk did I do c.getAccountName()?
final MapleClient client = c;
c.setIdleTask(TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
client.disconnect(false, false);
}
}, 600000));
Server.getInstance().registerLoginState(c);
}
}

View File

@@ -49,9 +49,7 @@ public final class PickCharHandler extends AbstractMaplePacketHandler {
e.printStackTrace();
c.setChannel(1);
}
if (c.getIdleTask() != null) {
c.getIdleTask().cancel(true);
}
Server.getInstance().unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
String[] socket = Server.getInstance().getIP(c.getWorld(), c.getChannel()).split(":");
try {

View File

@@ -29,9 +29,7 @@ public final class RegisterPicHandler extends AbstractMaplePacketHandler {
String pic = slea.readMapleAsciiString();
if (c.getPic() == null || c.getPic().equals("")) {
c.setPic(pic);
if (c.getIdleTask() != null) {
c.getIdleTask().cancel(true);
}
Server.getInstance().unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
String[] socket = Server.getInstance().getIP(c.getWorld(), c.getChannel()).split(":");
try {

View File

@@ -24,7 +24,7 @@ package net.server.handlers.login;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import server.TimerManager;
import net.server.Server;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
@@ -40,12 +40,8 @@ public class SetGenderHandler extends AbstractMaplePacketHandler {
c.setGender(slea.readByte());
c.announce(MaplePacketCreator.getAuthSuccess(c));
final MapleClient client = c;
c.setIdleTask(TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
client.getSession().close(true);
}
}, 600000));
Server.getInstance().registerLoginState(c);
}
}

View File

@@ -29,9 +29,7 @@ public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandle
return;
}
if (c.checkPic(pic)) {
if (c.getIdleTask() != null) {
c.getIdleTask().cancel(true);
}
Server.getInstance().unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
String[] socket = Server.getInstance().getIP(c.getWorld(), c.getChannel()).split(":");

View File

@@ -28,9 +28,7 @@ public final class ViewAllPicRegisterHandler extends AbstractMaplePacketHandler
slea.readMapleAsciiString();
String pic = slea.readMapleAsciiString();
c.setPic(pic);
if (c.getIdleTask() != null) {
c.getIdleTask().cancel(true);
}
Server.getInstance().unregisterLoginState(c);
c.updateLoginState(MapleClient.LOGIN_SERVER_TRANSITION);
String[] socket = Server.getInstance().getIP(c.getWorld(), channel).split(":");
try {

View File

@@ -1508,7 +1508,7 @@ public class MapleItemInformationProvider {
Connection con = null;
try {
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, itemId);
ResultSet rs = ps.executeQuery();
while(rs.next()) {

View File

@@ -236,7 +236,7 @@ public class MapleShop {
con.close();
return null;
}
ps = con.prepareStatement("SELECT * FROM shopitems WHERE shopid = ? ORDER BY position DESC");
ps = con.prepareStatement("SELECT itemid, price, pitch FROM shopitems WHERE shopid = ? ORDER BY position DESC");
ps.setInt(1, shopId);
rs = ps.executeQuery();
List<Integer> recharges = new ArrayList<>(rechargeableItems);

View File

@@ -111,7 +111,7 @@ public class MapleMonsterInformationProvider {
Connection con = null;
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT * FROM drop_data WHERE dropperid = ?");
ps = con.prepareStatement("SELECT itemid, chance, minimum_quantity, maximum_quantity, questid FROM drop_data WHERE dropperid = ?");
ps.setInt(1, monsterId);
rs = ps.executeQuery();

View File

@@ -98,6 +98,7 @@ public class MapleMap {
private Map<Integer, MaplePortal> portals = new HashMap<>();
private Map<Integer, Integer> backgroundTypes = new HashMap<>();
private Map<String, Integer> environment = new LinkedHashMap<>();
private Map<MapleMapItem, Long> droppedItems = new LinkedHashMap<>();
private LinkedList<WeakReference<MapleMapObject>> registeredDrops = new LinkedList<>();
private List<Rectangle> areas = new ArrayList<>();
private MapleFootholdTree footholds = null;
@@ -130,6 +131,7 @@ public class MapleMap {
private int mobCapacity = -1;
private ScheduledFuture<?> mapMonitor = null;
private ScheduledFuture<?> itemMonitor = null;
private ScheduledFuture<?> expireItemsTask = null;
private short itemMonitorTimeout;
private Pair<Integer, String> timeMob = null;
private short mobInterval = 5000;
@@ -368,7 +370,6 @@ public class MapleMap {
private void spawnRangedMapObject(MapleMapObject mapobject, DelayedPacketCreation packetbakery, SpawnCondition condition) {
chrRLock.lock();
try {
int curOID = getUsableOID();
mapobject.setObjectId(curOID);
@@ -585,6 +586,9 @@ public class MapleMap {
try {
itemMonitor.cancel(false);
itemMonitor = null;
expireItemsTask.cancel(false);
expireItemsTask = null;
} finally {
chrWLock.unlock();
}
@@ -621,6 +625,13 @@ public class MapleMap {
if(!registeredDrops.isEmpty()) cleanItemMonitor();
}
}, ServerConstants.ITEM_MONITOR_TIME, ServerConstants.ITEM_MONITOR_TIME);
expireItemsTask = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
makeDisappearExpiredItemDrops();
}
}, ServerConstants.ITEM_EXPIRE_CHECK, ServerConstants.ITEM_EXPIRE_CHECK);
itemMonitorTimeout = 1;
} finally {
@@ -637,7 +648,7 @@ public class MapleMap {
}
}
private void registerItemDrop(MapleMapItem mdrop) {
private void instantiateItemDrop(MapleMapItem mdrop) {
if(droppedItemCount.get() >= ServerConstants.ITEM_LIMIT_ON_MAP) {
MapleMapObject mapobj;
@@ -654,10 +665,9 @@ public class MapleMap {
makeDisappearItemFromMap(mapobj);
}
if(!everlast) TimerManager.getInstance().schedule(new ExpireMapItemJob(mdrop), ServerConstants.ITEM_EXPIRE_TIME);
objectWLock.lock();
try {
if(!everlast) registerItemDrop(mdrop);
registeredDrops.add(new WeakReference<>((MapleMapObject) mdrop));
} finally {
objectWLock.unlock();
@@ -666,6 +676,31 @@ public class MapleMap {
droppedItemCount.incrementAndGet();
}
private void registerItemDrop(MapleMapItem mdrop) {
droppedItems.put(mdrop, System.currentTimeMillis() + ServerConstants.ITEM_EXPIRE_TIME);
}
private void makeDisappearExpiredItemDrops() {
objectWLock.lock();
try {
List<MapleMapItem> toDisappear = new LinkedList<>();
long timeNow = System.currentTimeMillis();
for(Entry<MapleMapItem, Long> it : droppedItems.entrySet()) {
if(it.getValue() < timeNow) {
toDisappear.add(it.getKey());
}
}
for(MapleMapItem mmi : toDisappear) {
makeDisappearItemFromMap(mmi);
droppedItems.remove(mmi);
}
} finally {
objectWLock.unlock();
}
}
public void pickItemDrop(byte[] pickupPacket, MapleMapItem mdrop) {
broadcastMessage(pickupPacket, mdrop.getPosition());
@@ -686,7 +721,7 @@ public class MapleMap {
}
}, null);
registerItemDrop(mdrop);
instantiateItemDrop(mdrop);
activateItemReactors(mdrop, chr.getClient());
}
@@ -702,7 +737,7 @@ public class MapleMap {
}
}, null);
registerItemDrop(mdrop);
instantiateItemDrop(mdrop);
}
public final void disappearingItemDrop(final MapleMapObject dropper, final MapleCharacter owner, final Item item, final Point pos) {
@@ -1719,7 +1754,7 @@ public class MapleMap {
}, null);
broadcastMessage(MaplePacketCreator.dropItemFromMapObject(mdrop, dropper.getPosition(), droppos, (byte) 0));
registerItemDrop(mdrop);
instantiateItemDrop(mdrop);
activateItemReactors(mdrop, owner.getClient());
}
@@ -2694,20 +2729,6 @@ public class MapleMap {
}
}
private class ExpireMapItemJob implements Runnable {
private MapleMapItem mapitem;
public ExpireMapItemJob(MapleMapItem mapitem) {
this.mapitem = mapitem;
}
@Override
public void run() {
makeDisappearItemFromMap(mapitem);
}
}
private class ActivateItemReactor implements Runnable {
private MapleMapItem mapitem;

View File

@@ -69,6 +69,222 @@ public class MapleMapFactory {
this.mapsWLock = rrwl.writeLock();
}
public MapleMap resetMap(int mapid) {
mapsWLock.lock();
try {
maps.remove(Integer.valueOf(mapid));
} finally {
mapsWLock.unlock();
}
return getMap(mapid);
}
private synchronized MapleMap loadMapFromWz(int mapid, Integer omapid) {
MapleMap map;
mapsRLock.lock();
try {
map = maps.get(omapid);
} finally {
mapsRLock.unlock();
}
if (map != null) {
return map;
}
String mapName = getMapName(mapid);
MapleData mapData = source.getData(mapName);
MapleData infoData = mapData.getChildByPath("info");
String link = MapleDataTool.getString(infoData.getChildByPath("link"), "");
if (!link.equals("")) { //nexon made hundreds of dojo maps so to reduce the size they added links.
mapName = getMapName(Integer.parseInt(link));
mapData = source.getData(mapName);
}
float monsterRate = 0;
MapleData mobRate = infoData.getChildByPath("mobRate");
if (mobRate != null) {
monsterRate = ((Float) mobRate.getData()).floatValue();
}
map = new MapleMap(mapid, world, channel, MapleDataTool.getInt("returnMap", infoData), monsterRate);
map.setEventInstance(event);
String onFirstEnter = MapleDataTool.getString(infoData.getChildByPath("onFirstUserEnter"), String.valueOf(mapid));
map.setOnFirstUserEnter(onFirstEnter.equals("") ? String.valueOf(mapid) : onFirstEnter);
String onEnter = MapleDataTool.getString(infoData.getChildByPath("onUserEnter"), String.valueOf(mapid));
map.setOnUserEnter(onEnter.equals("") ? String.valueOf(mapid) : onEnter);
map.setFieldLimit(MapleDataTool.getInt(infoData.getChildByPath("fieldLimit"), 0));
map.setMobInterval((short) MapleDataTool.getInt(infoData.getChildByPath("createMobInterval"), 5000));
PortalFactory portalFactory = new PortalFactory();
for (MapleData portal : mapData.getChildByPath("portal")) {
map.addPortal(portalFactory.makePortal(MapleDataTool.getInt(portal.getChildByPath("pt")), portal));
}
MapleData timeMob = infoData.getChildByPath("timeMob");
if (timeMob != null) {
map.timeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")),
MapleDataTool.getString(timeMob.getChildByPath("message")));
}
int bounds[] = new int[4];
bounds[0] = MapleDataTool.getInt(infoData.getChildByPath("VRTop"));
bounds[1] = MapleDataTool.getInt(infoData.getChildByPath("VRBottom"));
if(bounds[0] == bounds[1]) { // old-style baked map
MapleData minimapData = mapData.getChildByPath("miniMap");
if(minimapData != null) {
bounds[0] = MapleDataTool.getInt(minimapData.getChildByPath("centerX")) * -1;
bounds[1] = MapleDataTool.getInt(minimapData.getChildByPath("centerY")) * -1;
bounds[2] = MapleDataTool.getInt(minimapData.getChildByPath("height"));
bounds[3] = MapleDataTool.getInt(minimapData.getChildByPath("width"));
map.setMapPointBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
}
} else {
bounds[2] = MapleDataTool.getInt(infoData.getChildByPath("VRLeft"));
bounds[3] = MapleDataTool.getInt(infoData.getChildByPath("VRRight"));
map.setMapLineBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
}
List<MapleFoothold> allFootholds = new LinkedList<>();
Point lBound = new Point();
Point uBound = new Point();
for (MapleData footRoot : mapData.getChildByPath("foothold")) {
for (MapleData footCat : footRoot) {
for (MapleData footHold : footCat) {
int x1 = MapleDataTool.getInt(footHold.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(footHold.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(footHold.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(footHold.getChildByPath("y2"));
MapleFoothold fh = new MapleFoothold(new Point(x1, y1), new Point(x2, y2), Integer.parseInt(footHold.getName()));
fh.setPrev(MapleDataTool.getInt(footHold.getChildByPath("prev")));
fh.setNext(MapleDataTool.getInt(footHold.getChildByPath("next")));
if (fh.getX1() < lBound.x) {
lBound.x = fh.getX1();
}
if (fh.getX2() > uBound.x) {
uBound.x = fh.getX2();
}
if (fh.getY1() < lBound.y) {
lBound.y = fh.getY1();
}
if (fh.getY2() > uBound.y) {
uBound.y = fh.getY2();
}
allFootholds.add(fh);
}
}
}
MapleFootholdTree fTree = new MapleFootholdTree(lBound, uBound);
for (MapleFoothold fh : allFootholds) {
fTree.insert(fh);
}
map.setFootholds(fTree);
if (mapData.getChildByPath("area") != null) {
for (MapleData area : mapData.getChildByPath("area")) {
int x1 = MapleDataTool.getInt(area.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(area.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(area.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(area.getChildByPath("y2"));
map.addMapleArea(new Rectangle(x1, y1, (x2 - x1), (y2 - y1)));
}
}
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM playernpcs WHERE map = ?")) {
ps.setInt(1, omapid);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
map.addMapObject(new PlayerNPCs(rs));
}
}
}
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
for (MapleData life : mapData.getChildByPath("life")) {
String id = MapleDataTool.getString(life.getChildByPath("id"));
String type = MapleDataTool.getString(life.getChildByPath("type"));
AbstractLoadedMapleLife myLife = loadLife(life, id, type);
if (myLife instanceof MapleMonster) {
MapleMonster monster = (MapleMonster) myLife;
int mobTime = MapleDataTool.getInt("mobTime", life, 0);
int team = MapleDataTool.getInt("team", life, -1);
if (mobTime == -1) { //does not respawn, force spawn once
map.spawnMonster(monster);
} else {
map.addMonsterSpawn(monster, mobTime, team);
}
//should the map be reseted, use allMonsterSpawn list of monsters to spawn them again
map.addAllMonsterSpawn(monster, mobTime, team);
} else {
map.addMapObject(myLife);
}
}
if (mapData.getChildByPath("reactor") != null) {
for (MapleData reactor : mapData.getChildByPath("reactor")) {
String id = MapleDataTool.getString(reactor.getChildByPath("id"));
if (id != null) {
MapleReactor newReactor = loadReactor(reactor, id);
map.spawnReactor(newReactor);
}
}
}
try {
map.setMapName(MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(omapid)), ""));
map.setStreetName(MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(omapid)), ""));
} catch (Exception e) {
e.printStackTrace();
System.err.println("Not found mapid " + omapid);
map.setMapName("");
map.setStreetName("");
}
map.setClock(mapData.getChildByPath("clock") != null);
map.setEverlast(infoData.getChildByPath("everlast") != null);
map.setTown(infoData.getChildByPath("town") != null);
map.setHPDec(MapleDataTool.getIntConvert("decHP", infoData, 0));
map.setHPDecProtect(MapleDataTool.getIntConvert("protectItem", infoData, 0));
map.setForcedReturnMap(MapleDataTool.getInt(infoData.getChildByPath("forcedReturn"), 999999999));
map.setBoat(mapData.getChildByPath("shipObj") != null);
map.setTimeLimit(MapleDataTool.getIntConvert("timeLimit", infoData, -1));
map.setFieldType(MapleDataTool.getIntConvert("fieldType", infoData, 0));
map.setMobCapacity(MapleDataTool.getIntConvert("fixedMobCapacity", infoData, 500));//Is there a map that contains more than 500 mobs?
HashMap<Integer, Integer> backTypes = new HashMap<>();
try {
for (MapleData layer : mapData.getChildByPath("back")) { // yolo
int layerNum = Integer.parseInt(layer.getName());
int type = MapleDataTool.getInt(layer.getChildByPath("type"), 0);
backTypes.put(layerNum, type);
}
} catch (Exception e) {
e.printStackTrace();
// swallow cause I'm cool
}
map.setBackgroundTypes(backTypes);
mapsWLock.lock();
try {
maps.put(omapid, map);
} finally {
mapsWLock.unlock();
}
return map;
}
public MapleMap getMap(int mapid) {
Integer omapid = Integer.valueOf(mapid);
MapleMap map;
@@ -80,211 +296,7 @@ public class MapleMapFactory {
mapsRLock.unlock();
}
if (map == null) {
synchronized (this) {
mapsRLock.lock();
try {
map = maps.get(omapid);
} finally {
mapsRLock.unlock();
}
if (map != null) {
return map;
}
String mapName = getMapName(mapid);
MapleData mapData = source.getData(mapName);
MapleData infoData = mapData.getChildByPath("info");
String link = MapleDataTool.getString(infoData.getChildByPath("link"), "");
if (!link.equals("")) { //nexon made hundreds of dojo maps so to reduce the size they added links.
mapName = getMapName(Integer.parseInt(link));
mapData = source.getData(mapName);
}
float monsterRate = 0;
MapleData mobRate = infoData.getChildByPath("mobRate");
if (mobRate != null) {
monsterRate = ((Float) mobRate.getData()).floatValue();
}
map = new MapleMap(mapid, world, channel, MapleDataTool.getInt("returnMap", infoData), monsterRate);
map.setEventInstance(event);
String onFirstEnter = MapleDataTool.getString(infoData.getChildByPath("onFirstUserEnter"), String.valueOf(mapid));
map.setOnFirstUserEnter(onFirstEnter.equals("") ? String.valueOf(mapid) : onFirstEnter);
String onEnter = MapleDataTool.getString(infoData.getChildByPath("onUserEnter"), String.valueOf(mapid));
map.setOnUserEnter(onEnter.equals("") ? String.valueOf(mapid) : onEnter);
map.setFieldLimit(MapleDataTool.getInt(infoData.getChildByPath("fieldLimit"), 0));
map.setMobInterval((short) MapleDataTool.getInt(infoData.getChildByPath("createMobInterval"), 5000));
PortalFactory portalFactory = new PortalFactory();
for (MapleData portal : mapData.getChildByPath("portal")) {
map.addPortal(portalFactory.makePortal(MapleDataTool.getInt(portal.getChildByPath("pt")), portal));
}
MapleData timeMob = infoData.getChildByPath("timeMob");
if (timeMob != null) {
map.timeMob(MapleDataTool.getInt(timeMob.getChildByPath("id")),
MapleDataTool.getString(timeMob.getChildByPath("message")));
}
int bounds[] = new int[4];
bounds[0] = MapleDataTool.getInt(infoData.getChildByPath("VRTop"));
bounds[1] = MapleDataTool.getInt(infoData.getChildByPath("VRBottom"));
if(bounds[0] == bounds[1]) { // old-style baked map
MapleData minimapData = mapData.getChildByPath("miniMap");
if(minimapData != null) {
bounds[0] = MapleDataTool.getInt(minimapData.getChildByPath("centerX")) * -1;
bounds[1] = MapleDataTool.getInt(minimapData.getChildByPath("centerY")) * -1;
bounds[2] = MapleDataTool.getInt(minimapData.getChildByPath("height"));
bounds[3] = MapleDataTool.getInt(minimapData.getChildByPath("width"));
map.setMapPointBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
}
} else {
bounds[2] = MapleDataTool.getInt(infoData.getChildByPath("VRLeft"));
bounds[3] = MapleDataTool.getInt(infoData.getChildByPath("VRRight"));
map.setMapLineBoundings(bounds[0], bounds[1], bounds[2], bounds[3]);
}
List<MapleFoothold> allFootholds = new LinkedList<>();
Point lBound = new Point();
Point uBound = new Point();
for (MapleData footRoot : mapData.getChildByPath("foothold")) {
for (MapleData footCat : footRoot) {
for (MapleData footHold : footCat) {
int x1 = MapleDataTool.getInt(footHold.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(footHold.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(footHold.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(footHold.getChildByPath("y2"));
MapleFoothold fh = new MapleFoothold(new Point(x1, y1), new Point(x2, y2), Integer.parseInt(footHold.getName()));
fh.setPrev(MapleDataTool.getInt(footHold.getChildByPath("prev")));
fh.setNext(MapleDataTool.getInt(footHold.getChildByPath("next")));
if (fh.getX1() < lBound.x) {
lBound.x = fh.getX1();
}
if (fh.getX2() > uBound.x) {
uBound.x = fh.getX2();
}
if (fh.getY1() < lBound.y) {
lBound.y = fh.getY1();
}
if (fh.getY2() > uBound.y) {
uBound.y = fh.getY2();
}
allFootholds.add(fh);
}
}
}
MapleFootholdTree fTree = new MapleFootholdTree(lBound, uBound);
for (MapleFoothold fh : allFootholds) {
fTree.insert(fh);
}
map.setFootholds(fTree);
if (mapData.getChildByPath("area") != null) {
for (MapleData area : mapData.getChildByPath("area")) {
int x1 = MapleDataTool.getInt(area.getChildByPath("x1"));
int y1 = MapleDataTool.getInt(area.getChildByPath("y1"));
int x2 = MapleDataTool.getInt(area.getChildByPath("x2"));
int y2 = MapleDataTool.getInt(area.getChildByPath("y2"));
map.addMapleArea(new Rectangle(x1, y1, (x2 - x1), (y2 - y1)));
}
}
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM playernpcs WHERE map = ?")) {
ps.setInt(1, omapid);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
map.addMapObject(new PlayerNPCs(rs));
}
}
}
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
for (MapleData life : mapData.getChildByPath("life")) {
String id = MapleDataTool.getString(life.getChildByPath("id"));
String type = MapleDataTool.getString(life.getChildByPath("type"));
if (id.equals("9001105")) {
id = "9001108";//soz
}
AbstractLoadedMapleLife myLife = loadLife(life, id, type);
if (myLife instanceof MapleMonster) {
MapleMonster monster = (MapleMonster) myLife;
int mobTime = MapleDataTool.getInt("mobTime", life, 0);
int team = MapleDataTool.getInt("team", life, -1);
if (mobTime == -1) { //does not respawn, force spawn once
map.spawnMonster(monster);
} else {
map.addMonsterSpawn(monster, mobTime, team);
}
//should the map be reseted, use allMonsterSpawn list of monsters to spawn them again
map.addAllMonsterSpawn(monster, mobTime, team);
} else {
map.addMapObject(myLife);
}
}
if (mapData.getChildByPath("reactor") != null) {
for (MapleData reactor : mapData.getChildByPath("reactor")) {
String id = MapleDataTool.getString(reactor.getChildByPath("id"));
if (id != null) {
MapleReactor newReactor = loadReactor(reactor, id);
map.spawnReactor(newReactor);
}
}
}
try {
map.setMapName(MapleDataTool.getString("mapName", nameData.getChildByPath(getMapStringName(omapid)), ""));
map.setStreetName(MapleDataTool.getString("streetName", nameData.getChildByPath(getMapStringName(omapid)), ""));
} catch (Exception e) {
e.printStackTrace();
System.err.println("Not found mapid " + omapid);
map.setMapName("");
map.setStreetName("");
}
map.setClock(mapData.getChildByPath("clock") != null);
map.setEverlast(infoData.getChildByPath("everlast") != null);
map.setTown(infoData.getChildByPath("town") != null);
map.setHPDec(MapleDataTool.getIntConvert("decHP", infoData, 0));
map.setHPDecProtect(MapleDataTool.getIntConvert("protectItem", infoData, 0));
map.setForcedReturnMap(MapleDataTool.getInt(infoData.getChildByPath("forcedReturn"), 999999999));
map.setBoat(mapData.getChildByPath("shipObj") != null);
map.setTimeLimit(MapleDataTool.getIntConvert("timeLimit", infoData, -1));
map.setFieldType(MapleDataTool.getIntConvert("fieldType", infoData, 0));
map.setMobCapacity(MapleDataTool.getIntConvert("fixedMobCapacity", infoData, 500));//Is there a map that contains more than 500 mobs?
HashMap<Integer, Integer> backTypes = new HashMap<>();
try {
for (MapleData layer : mapData.getChildByPath("back")) { // yolo
int layerNum = Integer.parseInt(layer.getName());
int type = MapleDataTool.getInt(layer.getChildByPath("type"), 0);
backTypes.put(layerNum, type);
}
} catch (Exception e) {
e.printStackTrace();
// swallow cause I'm cool
}
map.setBackgroundTypes(backTypes);
mapsWLock.lock();
try {
maps.put(omapid, map);
} finally {
mapsWLock.unlock();
}
}
}
return map;
return (map != null) ? map : loadMapFromWz(mapid, omapid);
}
public boolean isMapLoaded(int mapId) {

View File

@@ -26,16 +26,16 @@ public class DatabaseConnection {
}
int denies = 0;
while(true) { // There is no way it can pass with a null out of here
while(true) { // There is no way it can pass with a null out of here?
try {
return DriverManager.getConnection(ServerConstants.DB_URL, ServerConstants.DB_USER, ServerConstants.DB_PASS);
} catch (SQLException sqle) {
denies++;
if(denies == 3) {
// Give up, return null :3
FilePrinter.printError(FilePrinter.SQL_EXCEPTION, "SQL Driver refused to give a connection after " + denies + " tries.");
return null;
// Give up, throw exception. Nothing good will come from this.
FilePrinter.printError(FilePrinter.SQL_EXCEPTION, "SQL Driver refused to give a connection after " + denies + " tries. Problem: " + sqle.getMessage());
throw sqle;
}
}
}

View File

@@ -313,6 +313,13 @@ public class MaplePacketCreator {
}
}
}
public static byte[] setExtraPendantSlot(boolean toggleExtraSlot) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.SET_EXTRA_PENDANT_SLOT.getValue());
mplew.writeBool(toggleExtraSlot);
return mplew.getPacket();
}
private static void addCharEntry(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean viewall) {
addCharStats(mplew, chr);