From e322b05707f5da171da4cd2b258bfe1bc612e08c Mon Sep 17 00:00:00 2001 From: P0nk Date: Sun, 4 Apr 2021 15:35:17 +0200 Subject: [PATCH] refactor: use try-with-resources for various server db operations --- src/main/java/net/server/Server.java | 1042 +++++++++++++------------- 1 file changed, 511 insertions(+), 531 deletions(-) diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index 27b8025f26..96c5577383 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -21,28 +21,22 @@ */ package net.server; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.security.Security; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashSet; -import java.util.HashMap; -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.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; - +import client.MapleCharacter; +import client.MapleClient; +import client.MapleFamily; +import client.SkillFactory; +import client.command.CommandsExecutor; +import client.inventory.Item; +import client.inventory.ItemFactory; +import client.inventory.manipulator.MapleCashidGenerator; +import client.newyear.NewYearCardRecord; import config.YamlConfig; +import constants.game.GameConstants; +import constants.inventory.ItemConstants; +import constants.net.OpcodeConstants; +import constants.net.ServerConstants; +import net.MapleServerHandler; +import net.mina.MapleCodecFactory; import net.server.audit.ThreadTracker; import net.server.audit.locks.MonitoredLockType; import net.server.audit.locks.MonitoredReadLock; @@ -51,28 +45,13 @@ import net.server.audit.locks.MonitoredWriteLock; import net.server.audit.locks.factory.MonitoredReadLockFactory; import net.server.audit.locks.factory.MonitoredReentrantLockFactory; import net.server.audit.locks.factory.MonitoredWriteLockFactory; - -import net.MapleServerHandler; -import net.mina.MapleCodecFactory; import net.server.channel.Channel; import net.server.coordinator.session.MapleSessionCoordinator; import net.server.guild.MapleAlliance; import net.server.guild.MapleGuild; import net.server.guild.MapleGuildCharacter; -import net.server.task.BossLogTask; -import net.server.task.CharacterDiseaseTask; -import net.server.task.CouponTask; -import net.server.task.EventRecallCoordinatorTask; -import net.server.task.DueyFredrickTask; -import net.server.task.InvitationTask; -import net.server.task.LoginCoordinatorTask; -import net.server.task.LoginStorageTask; -import net.server.task.RankingCommandTask; -import net.server.task.RankingLoginTask; -import net.server.task.ReleaseLockTask; -import net.server.task.RespawnTask; +import net.server.task.*; import net.server.world.World; - import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.buffer.SimpleBufferAllocator; import org.apache.mina.core.filterchain.IoFilter; @@ -80,21 +59,6 @@ import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; - -import client.MapleClient; -import client.MapleFamily; -import client.MapleCharacter; -import client.SkillFactory; -import client.command.CommandsExecutor; -import client.inventory.Item; -import client.inventory.ItemFactory; -import client.inventory.manipulator.MapleCashidGenerator; -import client.newyear.NewYearCardRecord; -import constants.inventory.ItemConstants; -import constants.game.GameConstants; -import constants.net.OpcodeConstants; -import constants.net.ServerConstants; -import java.util.TimeZone; import server.CashShop.CashItemFactory; import server.MapleSkillbookInformationProvider; import server.ThreadManager; @@ -107,21 +71,33 @@ import tools.DatabaseConnection; import tools.FilePrinter; import tools.Pair; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.security.Security; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; + public class Server { - + private static Server instance = null; - + public static Server getInstance() { if (instance == null) { instance = new Server(); } return instance; } - + private static final Set activeFly = new HashSet<>(); private static final Map couponRates = new HashMap<>(30); private static final List activeCoupons = new LinkedList<>(); - + private IoAcceptor acceptor; private List> channels = new LinkedList<>(); private List worlds = new ArrayList<>(); @@ -133,53 +109,53 @@ public class Server { private List> worldRecommendedList = new LinkedList<>(); private final Map guilds = new HashMap<>(100); private final Map inLoginState = new HashMap<>(100); - + private final PlayerBuffStorage buffStorage = new PlayerBuffStorage(); private final Map alliances = new HashMap<>(100); private final Map newyears = new HashMap<>(); private final List processDiseaseAnnouncePlayers = new LinkedList<>(); private final List registeredDiseaseAnnouncePlayers = new LinkedList<>(); - + private final List>> playerRanking = new LinkedList<>(); - + private final Lock srvLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER); private final Lock disLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_DISEASES); - + private final MonitoredReentrantReadWriteLock wldLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_WORLDS, true); private final MonitoredReadLock wldRLock = MonitoredReadLockFactory.createLock(wldLock); private final MonitoredWriteLock wldWLock = MonitoredWriteLockFactory.createLock(wldLock); - + private final MonitoredReentrantReadWriteLock lgnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.SERVER_LOGIN, true); private final MonitoredReadLock lgnRLock = MonitoredReadLockFactory.createLock(lgnLock); private final MonitoredWriteLock lgnWLock = MonitoredWriteLockFactory.createLock(lgnLock); - + private final AtomicLong currentTime = new AtomicLong(0); private long serverCurrentTime = 0; - + private boolean availableDeveloperRoom = false; private boolean online = false; public static long uptime = System.currentTimeMillis(); - + public int getCurrentTimestamp() { return (int) (Server.getInstance().getCurrentTime() - Server.uptime); } - + public long getCurrentTime() { // returns a slightly delayed time value, under frequency of UPDATE_INTERVAL return serverCurrentTime; } - + public void updateCurrentTime() { serverCurrentTime = currentTime.addAndGet(YamlConfig.config.server.UPDATE_INTERVAL); } - + public long forceUpdateCurrentTime() { long timeNow = System.currentTimeMillis(); serverCurrentTime = timeNow; currentTime.set(timeNow); - + return timeNow; } - + public boolean isOnline() { return online; } @@ -187,50 +163,50 @@ public class Server { public List> worldRecommendedList() { return worldRecommendedList; } - + public void setNewYearCard(NewYearCardRecord nyc) { newyears.put(nyc.getId(), nyc); } - + public NewYearCardRecord getNewYearCard(int cardid) { return newyears.get(cardid); } - + public NewYearCardRecord removeNewYearCard(int cardid) { return newyears.remove(cardid); } - + public void setAvailableDeveloperRoom() { availableDeveloperRoom = true; } - + public boolean canEnterDeveloperRoom() { return availableDeveloperRoom; } private void loadPlayerNpcMapStepFromDb() { - try { - List wlist = this.getWorlds(); - - Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT * FROM playernpcs_field"); - - ResultSet rs = ps.executeQuery(); - while(rs.next()) { - int world = rs.getInt("world"), map = rs.getInt("map"), step = rs.getInt("step"), podium = rs.getInt("podium"); - + final List wlist = this.getWorlds(); + + try (Connection con = DatabaseConnection.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM playernpcs_field"); + ResultSet rs = ps.executeQuery()) { + + while (rs.next()) { + int world = rs.getInt("world"); + int map = rs.getInt("map"); + int step = rs.getInt("step"); + int podium = rs.getInt("podium"); + World w = wlist.get(world); - if(w != null) w.setPlayerNpcMapData(map, step, podium); + if (w != null) { + w.setPlayerNpcMapData(map, step, podium); + } } - - rs.close(); - ps.close(); - con.close(); } catch (SQLException e) { e.printStackTrace(); } } - + public World getWorld(int id) { wldRLock.lock(); try { @@ -252,7 +228,7 @@ public class Server { wldRLock.unlock(); } } - + public int getWorldsSize() { wldRLock.lock(); try { @@ -261,11 +237,11 @@ public class Server { wldRLock.unlock(); } } - + public Channel getChannel(int world, int channel) { try { return this.getWorld(world).getChannel(channel); - } catch(NullPointerException npe) { + } catch (NullPointerException npe) { return null; } } @@ -273,11 +249,11 @@ public class Server { public List getChannelsFromWorld(int world) { try { return this.getWorld(world).getChannels(); - } catch(NullPointerException npe) { + } catch (NullPointerException npe) { return new ArrayList<>(0); } } - + public List getAllChannels() { try { List channelz = new ArrayList<>(); @@ -287,11 +263,11 @@ public class Server { } } return channelz; - } catch(NullPointerException npe) { + } catch (NullPointerException npe) { return new ArrayList<>(0); } } - + public Set getOpenChannels(int world) { wldRLock.lock(); try { @@ -300,7 +276,7 @@ public class Server { wldRLock.unlock(); } } - + private String getIP(int world, int channel) { wldRLock.lock(); try { @@ -309,7 +285,7 @@ public class Server { wldRLock.unlock(); } } - + public String[] getInetSocket(int world, int channel) { try { return getIP(world, channel).split(":"); @@ -317,8 +293,8 @@ public class Server { return null; } } - - + + private void dumpData() { wldRLock.lock(); try { @@ -331,31 +307,37 @@ public class Server { wldRLock.unlock(); } } - + public int addChannel(int worldid) { World world; Map channelInfo; int channelid; - + wldRLock.lock(); try { - if(worldid >= worlds.size()) return -3; - + if (worldid >= worlds.size()) { + return -3; + } + channelInfo = channels.get(worldid); - if(channelInfo == null) return -3; - + if (channelInfo == null) { + return -3; + } + channelid = channelInfo.size(); - if(channelid >= YamlConfig.config.server.CHANNEL_SIZE) return -2; - + if (channelid >= YamlConfig.config.server.CHANNEL_SIZE) { + return -2; + } + channelid++; world = this.getWorld(worldid); } finally { wldRLock.unlock(); } - + Channel channel = new Channel(worldid, channelid, getCurrentTime()); channel.setServerMessage(YamlConfig.config.worlds.get(worldid).why_am_i_recommended); - + if (world.addChannel(channel)) { wldWLock.lock(); try { @@ -364,15 +346,15 @@ public class Server { wldWLock.unlock(); } } - + return channelid; } - + public int addWorld() { int newWorld = initWorld(); - if(newWorld > -1) { + if (newWorld > -1) { installWorldPlayerRanking(newWorld); - + Set accounts; lgnRLock.lock(); try { @@ -380,29 +362,29 @@ public class Server { } finally { lgnRLock.unlock(); } - - for(Integer accId : accounts) { + + for (Integer accId : accounts) { loadAccountCharactersView(accId, 0, newWorld); } } - + return newWorld; } - + private int initWorld() { int i; - + wldRLock.lock(); try { i = worlds.size(); - - if(i >= YamlConfig.config.server.WLDLIST_SIZE) { + + if (i >= YamlConfig.config.server.WLDLIST_SIZE) { return -1; } } finally { wldRLock.unlock(); } - + System.out.println("Starting world " + i); int exprate = YamlConfig.config.worlds.get(i).exp_rate; @@ -421,7 +403,7 @@ public class Server { flag, event_message, exprate, droprate, bossdroprate, mesorate, questrate, travelrate, fishingrate); - + Map channelInfo = new HashMap<>(); long bootTime = getCurrentTime(); for (int j = 1; j <= YamlConfig.config.worlds.get(i).channels; j++) { @@ -431,10 +413,10 @@ public class Server { world.addChannel(channel); channelInfo.put(channelid, channel.getIP()); } - + boolean canDeploy; - - wldWLock.lock(); // thanks Ashen for noticing a deadlock issue when trying to deploy a channel + + wldWLock.lock(); // thanks Ashen for noticing a deadlock issue when trying to deploy a channel try { canDeploy = world.getId() == worlds.size(); if (canDeploy) { @@ -445,10 +427,10 @@ public class Server { } finally { wldWLock.unlock(); } - + if (canDeploy) { world.setServerMessage(YamlConfig.config.worlds.get(i).server_message); - + System.out.println("Finished loading world " + i + "\r\n"); return i; } else { @@ -457,57 +439,61 @@ public class Server { return -2; } } - + public boolean removeChannel(int worldid) { //lol don't! World world; - + wldRLock.lock(); try { - if(worldid >= worlds.size()) return false; + if (worldid >= worlds.size()) { + return false; + } world = worlds.get(worldid); } finally { wldRLock.unlock(); } - + if (world != null) { int channel = world.removeChannel(); wldWLock.lock(); try { Map m = channels.get(worldid); - if(m != null) m.remove(channel); + if (m != null) { + m.remove(channel); + } } finally { wldWLock.unlock(); } return channel > -1; } - + return false; } - + public boolean removeWorld() { //lol don't! World w; int worldid; - + wldRLock.lock(); try { worldid = worlds.size() - 1; - if(worldid < 0) { + if (worldid < 0) { return false; } - + w = worlds.get(worldid); } finally { wldRLock.unlock(); } - - if(w == null || !w.canUninstall()) { + + if (w == null || !w.canUninstall()) { return false; } - + removeWorldPlayerRanking(); w.shutdown(); - + wldWLock.lock(); try { if (worldid == worlds.size() - 1) { @@ -518,10 +504,10 @@ public class Server { } finally { wldWLock.unlock(); } - + return true; } - + private void resetServerWorlds() { // thanks maple006 for noticing proprietary lists assigned to null wldWLock.lock(); try { @@ -532,96 +518,96 @@ public class Server { wldWLock.unlock(); } } - + private static long getTimeLeftForNextHour() { Calendar nextHour = Calendar.getInstance(); nextHour.add(Calendar.HOUR, 1); nextHour.set(Calendar.MINUTE, 0); nextHour.set(Calendar.SECOND, 0); - + return Math.max(0, nextHour.getTimeInMillis() - System.currentTimeMillis()); } - + public static long getTimeLeftForNextDay() { Calendar nextDay = Calendar.getInstance(); nextDay.add(Calendar.DAY_OF_MONTH, 1); nextDay.set(Calendar.HOUR_OF_DAY, 0); nextDay.set(Calendar.MINUTE, 0); nextDay.set(Calendar.SECOND, 0); - + return Math.max(0, nextDay.getTimeInMillis() - System.currentTimeMillis()); } - + public Map getCouponRates() { return couponRates; } - - public static void cleanNxcodeCoupons(Connection con) throws SQLException { - if (!YamlConfig.config.server.USE_CLEAR_OUTDATED_COUPONS) return; - - long timeClear = System.currentTimeMillis() - 14 * 24 * 60 * 60 * 1000; - - PreparedStatement ps = con.prepareStatement("SELECT * FROM nxcode WHERE expiration <= ?"); - ps.setLong(1, timeClear); - ResultSet rs = ps.executeQuery(); - if (!rs.isLast()) { - PreparedStatement ps2 = con.prepareStatement("DELETE FROM nxcode_items WHERE codeid = ?"); - while (rs.next()) { - ps2.setInt(1, rs.getInt("id")); - ps2.addBatch(); + public static void cleanNxcodeCoupons(Connection con) throws SQLException { + if (!YamlConfig.config.server.USE_CLEAR_OUTDATED_COUPONS) { + return; + } + + long timeClear = System.currentTimeMillis() - 14 * 24 * 60 * 60 * 1000; + + try (PreparedStatement ps = con.prepareStatement("SELECT * FROM nxcode WHERE expiration <= ?")) { + ps.setLong(1, timeClear); + + try (ResultSet rs = ps.executeQuery()) { + if (!rs.isLast()) { + try (PreparedStatement ps2 = con.prepareStatement("DELETE FROM nxcode_items WHERE codeid = ?")) { + while (rs.next()) { + ps2.setInt(1, rs.getInt("id")); + ps2.addBatch(); + } + ps2.executeBatch(); + } + + try (PreparedStatement ps2 = con.prepareStatement("DELETE FROM nxcode WHERE expiration <= ?")) { + ps2.setLong(1, timeClear); + ps2.executeUpdate(); + } + } } - ps2.executeBatch(); - ps2.close(); - - ps2 = con.prepareStatement("DELETE FROM nxcode WHERE expiration <= ?"); - ps2.setLong(1, timeClear); - ps2.executeUpdate(); - ps2.close(); } - - rs.close(); - ps.close(); } - + private void loadCouponRates(Connection c) throws SQLException { - PreparedStatement ps = c.prepareStatement("SELECT couponid, rate FROM nxcoupons"); - ResultSet rs = ps.executeQuery(); - - while(rs.next()) { - int cid = rs.getInt("couponid"); - int rate = rs.getInt("rate"); - - couponRates.put(cid, rate); + try (PreparedStatement ps = c.prepareStatement("SELECT couponid, rate FROM nxcoupons"); + ResultSet rs = ps.executeQuery()) { + + while (rs.next()) { + int cid = rs.getInt("couponid"); + int rate = rs.getInt("rate"); + + couponRates.put(cid, rate); + } } - - rs.close(); - ps.close(); } - + public List getActiveCoupons() { synchronized (activeCoupons) { return activeCoupons; } } - + public void commitActiveCoupons() { - for(World world: getWorlds()) { - for(MapleCharacter chr: world.getPlayerStorage().getAllCharacters()) { - if(!chr.isLoggedin()) continue; + for (World world : getWorlds()) { + for (MapleCharacter chr : world.getPlayerStorage().getAllCharacters()) { + if (!chr.isLoggedin()) { + continue; + } chr.updateCouponRates(); } } } - + public void toggleCoupon(Integer couponId) { - if(ItemConstants.isRateCoupon(couponId)) { + if (ItemConstants.isRateCoupon(couponId)) { synchronized (activeCoupons) { - if(activeCoupons.contains(couponId)) { + if (activeCoupons.contains(couponId)) { activeCoupons.remove(couponId); - } - else { + } else { activeCoupons.add(couponId); } @@ -629,7 +615,7 @@ public class Server { } } } - + public void updateActiveCoupons() throws SQLException { synchronized (activeCoupons) { activeCoupons.clear(); @@ -638,9 +624,7 @@ public class Server { int weekDay = c.get(Calendar.DAY_OF_WEEK); int hourDay = c.get(Calendar.HOUR_OF_DAY); - Connection con = null; - try { - con = DatabaseConnection.getConnection(); + try (Connection con = DatabaseConnection.getConnection()) { int weekdayMask = (1 << weekDay); PreparedStatement ps = con.prepareStatement("SELECT couponid FROM nxcoupons WHERE (activeday & ?) = ? AND starthour <= ? AND endhour > ?"); @@ -649,29 +633,17 @@ public class Server { ps.setInt(3, hourDay); ps.setInt(4, hourDay); - ResultSet rs = ps.executeQuery(); - while(rs.next()) { - activeCoupons.add(rs.getInt("couponid")); + try (ResultSet rs = ps.executeQuery()) { + while (rs.next()) { + activeCoupons.add(rs.getInt("couponid")); + } } - - rs.close(); - ps.close(); - - con.close(); } catch (SQLException ex) { ex.printStackTrace(); - - try { - if(con != null && !con.isClosed()) { - con.close(); - } - } catch (SQLException ex2) { - ex2.printStackTrace(); - } } } } - + public void runAnnouncePlayerDiseasesSchedule() { List processDiseaseAnnounceClients; disLock.lock(); @@ -681,20 +653,20 @@ public class Server { } finally { disLock.unlock(); } - - while(!processDiseaseAnnounceClients.isEmpty()) { + + while (!processDiseaseAnnounceClients.isEmpty()) { MapleClient c = processDiseaseAnnounceClients.remove(0); MapleCharacter player = c.getPlayer(); - if(player != null && player.isLoggedinWorld()) { + if (player != null && player.isLoggedinWorld()) { player.announceDiseases(); player.collectDiseases(); } } - + disLock.lock(); try { // this is to force the system to wait for at least one complete tick before releasing disease info for the registered clients - while(!registeredDiseaseAnnouncePlayers.isEmpty()) { + while (!registeredDiseaseAnnouncePlayers.isEmpty()) { MapleClient c = registeredDiseaseAnnouncePlayers.remove(0); processDiseaseAnnouncePlayers.add(c); } @@ -702,7 +674,7 @@ public class Server { disLock.unlock(); } } - + public void registerAnnouncePlayerDiseases(MapleClient c) { disLock.lock(); try { @@ -711,7 +683,7 @@ public class Server { disLock.unlock(); } } - + public List> getWorldPlayerRanking(int worldid) { wldRLock.lock(); try { @@ -720,17 +692,17 @@ public class Server { wldRLock.unlock(); } } - + private void installWorldPlayerRanking(int worldid) { List>>> ranking = updatePlayerRankingFromDB(worldid); - if(!ranking.isEmpty()) { + if (!ranking.isEmpty()) { wldWLock.lock(); try { if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { - for(int i = playerRanking.size(); i <= worldid; i++) { + for (int i = playerRanking.size(); i <= worldid; i++) { playerRanking.add(new ArrayList>(0)); } - + playerRanking.add(worldid, ranking.get(0).getRight()); } else { playerRanking.add(0, ranking.get(0).getRight()); @@ -740,22 +712,22 @@ public class Server { } } } - + private void removeWorldPlayerRanking() { if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { wldWLock.lock(); try { - if(playerRanking.size() < worlds.size()) { + if (playerRanking.size() < worlds.size()) { return; } - + playerRanking.remove(playerRanking.size() - 1); } finally { wldWLock.unlock(); } } else { List>>> ranking = updatePlayerRankingFromDB(-1 * (this.getWorldsSize() - 2)); // update ranking list - + wldWLock.lock(); try { playerRanking.add(0, ranking.get(0).getRight()); @@ -764,18 +736,18 @@ public class Server { } } } - + public void updateWorldPlayerRanking() { List>>> rankUpdates = updatePlayerRankingFromDB(-1 * (this.getWorldsSize() - 1)); - if(!rankUpdates.isEmpty()) { + if (!rankUpdates.isEmpty()) { wldWLock.lock(); try { if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { - for(int i = playerRanking.size(); i <= rankUpdates.get(rankUpdates.size() - 1).getLeft(); i++) { + for (int i = playerRanking.size(); i <= rankUpdates.get(rankUpdates.size() - 1).getLeft(); i++) { playerRanking.add(new ArrayList>(0)); } - - for(Pair>> wranks : rankUpdates) { + + for (Pair>> wranks : rankUpdates) { playerRanking.set(wranks.getLeft(), wranks.getRight()); } } else { @@ -786,27 +758,23 @@ public class Server { } } } - + private void initWorldPlayerRanking() { if (YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { playerRanking.add(new ArrayList>(0)); - } + } updateWorldPlayerRanking(); } - + private static List>>> updatePlayerRankingFromDB(int worldid) { List>>> rankSystem = new ArrayList<>(); List> rankUpdate = new ArrayList<>(0); - - PreparedStatement ps = null; - ResultSet rs = null; - Connection con = null; - try { - con = DatabaseConnection.getConnection(); - + + try (Connection con = DatabaseConnection.getConnection()) { + String worldQuery; if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { - if(worldid >= 0) { + if (worldid >= 0) { worldQuery = (" AND `characters`.`world` = " + worldid); } else { worldQuery = (" AND `characters`.`world` >= 0 AND `characters`.`world` <= " + -worldid); @@ -814,119 +782,102 @@ public class Server { } else { worldQuery = (" AND `characters`.`world` >= 0 AND `characters`.`world` <= " + Math.abs(worldid)); } - - ps = con.prepareStatement("SELECT `characters`.`name`, `characters`.`level`, `characters`.`world` FROM `characters` LEFT JOIN accounts ON accounts.id = characters.accountid WHERE `characters`.`gm` < 2 AND `accounts`.`banned` = '0'" + worldQuery + " ORDER BY " + (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING ? "world, " : "") + "level DESC, exp DESC, lastExpGainTime ASC LIMIT 50"); - rs = ps.executeQuery(); - - if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { - int currentWorld = -1; - while(rs.next()) { - int rsWorld = rs.getInt("world"); - if(currentWorld < rsWorld) { - currentWorld = rsWorld; - rankUpdate = new ArrayList<>(50); - rankSystem.add(new Pair<>(rsWorld, rankUpdate)); - } - rankUpdate.add(new Pair<>(rs.getString("name"), rs.getInt("level"))); - } - } else { - rankUpdate = new ArrayList<>(50); - rankSystem.add(new Pair<>(0, rankUpdate)); - - while(rs.next()) { - rankUpdate.add(new Pair<>(rs.getString("name"), rs.getInt("level"))); + try (PreparedStatement ps = con.prepareStatement("SELECT `characters`.`name`, `characters`.`level`, `characters`.`world` FROM `characters` LEFT JOIN accounts ON accounts.id = characters.accountid WHERE `characters`.`gm` < 2 AND `accounts`.`banned` = '0'" + worldQuery + " ORDER BY " + (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING ? "world, " : "") + "level DESC, exp DESC, lastExpGainTime ASC LIMIT 50"); + ResultSet rs = ps.executeQuery()) { + + if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) { + int currentWorld = -1; + while (rs.next()) { + int rsWorld = rs.getInt("world"); + if (currentWorld < rsWorld) { + currentWorld = rsWorld; + rankUpdate = new ArrayList<>(50); + rankSystem.add(new Pair<>(rsWorld, rankUpdate)); + } + + rankUpdate.add(new Pair<>(rs.getString("name"), rs.getInt("level"))); + } + } else { + rankUpdate = new ArrayList<>(50); + rankSystem.add(new Pair<>(0, rankUpdate)); + + while (rs.next()) { + rankUpdate.add(new Pair<>(rs.getString("name"), rs.getInt("level"))); + } } } - - ps.close(); - rs.close(); - con.close(); - } catch(SQLException ex) { + } catch (SQLException ex) { ex.printStackTrace(); - } finally { - try { - if(ps != null && !ps.isClosed()) { - ps.close(); - } - if(rs != null && !rs.isClosed()) { - rs.close(); - } - if(con != null && !con.isClosed()) { - con.close(); - } - } catch (SQLException e) { - e.printStackTrace(); - } } - + return rankSystem; } - + public void init() { System.out.println("Cosmic v" + ServerConstants.VERSION + " starting up.\r\n"); - - if(YamlConfig.config.server.SHUTDOWNHOOK) { + + if (YamlConfig.config.server.SHUTDOWNHOOK) { Runtime.getRuntime().addShutdownHook(new Thread(shutdown(false))); } if (!DatabaseConnection.initializeConnectionPool()) { throw new IllegalStateException("Failed to initiate a connection to the database"); } - + TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE)); - - Connection c = null; - try { - c = DatabaseConnection.getConnection(); - PreparedStatement ps = c.prepareStatement("UPDATE accounts SET loggedin = 0"); - ps.executeUpdate(); - ps.close(); - ps = c.prepareStatement("UPDATE characters SET HasMerchant = 0"); - ps.executeUpdate(); - ps.close(); - - cleanNxcodeCoupons(c); - loadCouponRates(c); + + try (Connection con = DatabaseConnection.getConnection()) { + try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0")) { + ps.executeUpdate(); + } + + try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0")) { + ps.executeUpdate(); + } + + cleanNxcodeCoupons(con); + loadCouponRates(con); updateActiveCoupons(); - - c.close(); } catch (SQLException sqle) { sqle.printStackTrace(); } + applyAllNameChanges(); // -- name changes can be missed by INSTANT_NAME_CHANGE -- applyAllWorldTransfers(); //MaplePet.clearMissingPetsFromDb(); // thanks Optimist for noticing this taking too long to run MapleCashidGenerator.loadExistentCashIdsFromDb(); - + ThreadManager.getInstance().start(); initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan - + long timeToTake = System.currentTimeMillis(); SkillFactory.loadAllSkills(); System.out.println("Skills loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds"); timeToTake = System.currentTimeMillis(); - + CashItemFactory.getSpecialCashItems(); System.out.println("Items loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds"); - - timeToTake = System.currentTimeMillis(); - MapleQuest.loadAllQuest(); - System.out.println("Quest loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds\r\n"); - + + timeToTake = System.currentTimeMillis(); + MapleQuest.loadAllQuest(); + System.out.println("Quest loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds\r\n"); + NewYearCardRecord.startPendingNewYearCardRequests(); - - if(YamlConfig.config.server.USE_THREAD_TRACKER) ThreadTracker.getInstance().registerThreadTrackerTask(); - + + if (YamlConfig.config.server.USE_THREAD_TRACKER) { + ThreadTracker.getInstance().registerThreadTrackerTask(); + } + try { Integer worldCount = Math.min(GameConstants.WORLD_NAMES.length, YamlConfig.config.server.WORLDS); - + for (int i = 0; i < worldCount; i++) { initWorld(); } initWorldPlayerRanking(); - + MaplePlayerNPCFactory.loadFactoryMetadata(); loadPlayerNpcMapStepFromDb(); } catch (Exception e) { @@ -934,17 +885,17 @@ public class Server { System.out.println("[SEVERE] Syntax error in 'world.ini'."); System.exit(0); } - + System.out.println(); - - if(YamlConfig.config.server.USE_FAMILY_SYSTEM) { + + if (YamlConfig.config.server.USE_FAMILY_SYSTEM) { timeToTake = System.currentTimeMillis(); MapleFamily.loadAllFamilies(); System.out.println("Families loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds\r\n"); } - + System.out.println(); - + IoBuffer.setUseDirectBuffer(false); // join IO operations performed by lxconan IoBuffer.setAllocator(new SimpleBufferAllocator()); acceptor = new NioSocketAcceptor(); @@ -956,27 +907,27 @@ public class Server { } catch (IOException ex) { ex.printStackTrace(); } - + System.out.println("Listening on port 8484\r\n\r\n"); - + System.out.println("Cosmic is now online.\r\n"); online = true; - + MapleSkillbookInformationProvider.getInstance(); OpcodeConstants.generateOpcodeNames(); CommandsExecutor.getInstance(); - + for (Channel ch : this.getAllChannels()) { ch.reloadEventScriptManager(); } } - + private void initializeTimelyTasks() { TimerManager tMan = TimerManager.getInstance(); tMan.start(); tMan.register(tMan.purge(), YamlConfig.config.server.PURGING_INTERVAL);//Purging ftw... disconnectIdlesOnLoginTask(); - + long timeLeft = getTimeLeftForNextHour(); tMan.register(new CharacterDiseaseTask(), YamlConfig.config.server.UPDATE_INTERVAL, YamlConfig.config.server.UPDATE_INTERVAL); tMan.register(new ReleaseLockTask(), 2 * 60 * 1000, 2 * 60 * 1000); @@ -989,7 +940,7 @@ public class Server { tMan.register(new DueyFredrickTask(), 60 * 60 * 1000, timeLeft); tMan.register(new InvitationTask(), 30 * 1000, 30 * 1000); tMan.register(new RespawnTask(), YamlConfig.config.server.RESPAWN_INTERVAL, YamlConfig.config.server.RESPAWN_INTERVAL); - + timeLeft = getTimeLeftForNextDay(); MapleExpeditionBossLog.resetBossLogTable(); tMan.register(new BossLogTask(), 24 * 60 * 60 * 1000, timeLeft); @@ -1096,50 +1047,50 @@ public class Server { } return false; } - + public int createGuild(int leaderId, String name) { return MapleGuild.createGuild(leaderId, name); } - + public MapleGuild getGuildByName(String name) { synchronized (guilds) { - for(MapleGuild mg: guilds.values()) { - if(mg.getName().equalsIgnoreCase(name)) { + for (MapleGuild mg : guilds.values()) { + if (mg.getName().equalsIgnoreCase(name)) { return mg; } } - + return null; } } - + public MapleGuild getGuild(int id) { synchronized (guilds) { if (guilds.get(id) != null) { return guilds.get(id); } - + return null; } } public MapleGuild getGuild(int id, int world) { - return getGuild(id, world, null); + return getGuild(id, world, null); } - + public MapleGuild getGuild(int id, int world, MapleCharacter mc) { synchronized (guilds) { MapleGuild g = guilds.get(id); if (g != null) { return g; } - + g = new MapleGuild(id, world); if (g.getId() == -1) { return null; } - - if(mc != null) { + + if (mc != null) { MapleGuildCharacter mgc = g.getMGC(mc.getId()); if (mgc != null) { mc.setMGC(mgc); @@ -1147,15 +1098,15 @@ public class Server { } else { FilePrinter.printError(FilePrinter.GUILD_CHAR_ERROR, "Could not find " + mc.getName() + " when loading guild " + id + "."); } - + g.setOnline(mc.getId(), true, mc.getClient().getChannel()); } - + guilds.put(id, g); return g; } } - + public void setGuildMemberOnline(MapleCharacter mc, boolean bOnline, int channel) { MapleGuild g = getGuild(mc.getGuildId(), mc.getWorld(), mc); g.setOnline(mc.getId(), bOnline, channel); @@ -1177,7 +1128,7 @@ public class Server { } return false; } - + public void resetAllianceGuildPlayersRank(int gId) { guilds.get(gId).resetAllianceGuildPlayersRank(); } @@ -1260,14 +1211,14 @@ public class Server { g.gainGP(amount); } } - + public void guildMessage(int gid, byte[] packet) { guildMessage(gid, packet, -1); } - + public void guildMessage(int gid, byte[] packet, int exception) { MapleGuild g = guilds.get(gid); - if(g != null) { + if (g != null) { g.broadcast(packet, exception); } } @@ -1284,9 +1235,11 @@ public class Server { disbandGuild(mc.getMGC().getGuildId()); } } - + public void deleteGuildCharacter(MapleGuildCharacter mgc) { - if(mgc.getCharacter() != null) setGuildMemberOnline(mgc.getCharacter(), false, (byte) -1); + if (mgc.getCharacter() != null) { + setGuildMemberOnline(mgc.getCharacter(), false, (byte) -1); + } if (mgc.getGuildRank() > 1) { leaveGuild(mgc); } else { @@ -1316,30 +1269,30 @@ public class Server { ch.broadcastGMPacket(packet); } } - + public boolean isGmOnline(int world) { for (Channel ch : getChannelsFromWorld(world)) { - for (MapleCharacter player : ch.getPlayerStorage().getAllCharacters()) { - if (player.isGM()){ - return true; - } - } + for (MapleCharacter player : ch.getPlayerStorage().getAllCharacters()) { + if (player.isGM()) { + return true; + } + } } return false; } - + public void changeFly(Integer accountid, boolean canFly) { - if(canFly) { + if (canFly) { activeFly.add(accountid); } else { activeFly.remove(accountid); } } - + public boolean canFly(Integer accountid) { return activeFly.contains(accountid); } - + public int getCharacterWorld(Integer chrid) { lgnRLock.lock(); try { @@ -1349,7 +1302,7 @@ public class Server { lgnRLock.unlock(); } } - + public boolean haveCharacterEntry(Integer accountid, Integer chrid) { lgnRLock.lock(); try { @@ -1359,7 +1312,7 @@ public class Server { lgnRLock.unlock(); } } - + public short getAccountCharacterCount(Integer accountid) { lgnRLock.lock(); try { @@ -1368,24 +1321,24 @@ public class Server { lgnRLock.unlock(); } } - + public short getAccountWorldCharacterCount(Integer accountid, Integer worldid) { lgnRLock.lock(); try { short count = 0; - - for(Integer chr : accountChars.get(accountid)) { - if(worldChars.get(chr).equals(worldid)) { + + for (Integer chr : accountChars.get(accountid)) { + if (worldChars.get(chr).equals(worldid)) { count++; } } - + return count; } finally { lgnRLock.unlock(); } } - + private Set getAccountCharacterEntries(Integer accountid) { lgnRLock.lock(); try { @@ -1394,73 +1347,83 @@ public class Server { lgnRLock.unlock(); } } - + public void updateCharacterEntry(MapleCharacter chr) { MapleCharacter chrView = chr.generateCharacterEntry(); - + lgnWLock.lock(); try { World wserv = this.getWorld(chrView.getWorld()); - if(wserv != null) wserv.registerAccountCharacterView(chrView.getAccountID(), chrView); - } finally { - lgnWLock.unlock(); - } - } - - public void createCharacterEntry(MapleCharacter chr) { - Integer accountid = chr.getAccountID(), chrid = chr.getId(), world = chr.getWorld(); - - lgnWLock.lock(); - try { - accountCharacterCount.put(accountid, (short)(accountCharacterCount.get(accountid) + 1)); - - Set accChars = accountChars.get(accountid); - accChars.add(chrid); - - worldChars.put(chrid, world); - - MapleCharacter chrView = chr.generateCharacterEntry(); - - World wserv = this.getWorld(chrView.getWorld()); - if(wserv != null) wserv.registerAccountCharacterView(chrView.getAccountID(), chrView); - } finally { - lgnWLock.unlock(); - } - } - - public void deleteCharacterEntry(Integer accountid, Integer chrid) { - lgnWLock.lock(); - try { - accountCharacterCount.put(accountid, (short)(accountCharacterCount.get(accountid) - 1)); - - Set accChars = accountChars.get(accountid); - accChars.remove(chrid); - - Integer world = worldChars.remove(chrid); - if(world != null) { - World wserv = this.getWorld(world); - if(wserv != null) wserv.unregisterAccountCharacterView(accountid, chrid); + if (wserv != null) { + wserv.registerAccountCharacterView(chrView.getAccountID(), chrView); } } finally { lgnWLock.unlock(); } } - + + public void createCharacterEntry(MapleCharacter chr) { + Integer accountid = chr.getAccountID(), chrid = chr.getId(), world = chr.getWorld(); + + lgnWLock.lock(); + try { + accountCharacterCount.put(accountid, (short) (accountCharacterCount.get(accountid) + 1)); + + Set accChars = accountChars.get(accountid); + accChars.add(chrid); + + worldChars.put(chrid, world); + + MapleCharacter chrView = chr.generateCharacterEntry(); + + World wserv = this.getWorld(chrView.getWorld()); + if (wserv != null) { + wserv.registerAccountCharacterView(chrView.getAccountID(), chrView); + } + } finally { + lgnWLock.unlock(); + } + } + + public void deleteCharacterEntry(Integer accountid, Integer chrid) { + lgnWLock.lock(); + try { + accountCharacterCount.put(accountid, (short) (accountCharacterCount.get(accountid) - 1)); + + Set accChars = accountChars.get(accountid); + accChars.remove(chrid); + + Integer world = worldChars.remove(chrid); + if (world != null) { + World wserv = this.getWorld(world); + if (wserv != null) { + wserv.unregisterAccountCharacterView(accountid, chrid); + } + } + } finally { + lgnWLock.unlock(); + } + } + public void transferWorldCharacterEntry(MapleCharacter chr, Integer toWorld) { // used before setting the new worldid on the character object lgnWLock.lock(); try { Integer chrid = chr.getId(), accountid = chr.getAccountID(), world = worldChars.get(chr.getId()); - if(world != null) { + if (world != null) { World wserv = this.getWorld(world); - if(wserv != null) wserv.unregisterAccountCharacterView(accountid, chrid); + if (wserv != null) { + wserv.unregisterAccountCharacterView(accountid, chrid); + } } - + worldChars.put(chrid, toWorld); - + MapleCharacter chrView = chr.generateCharacterEntry(); - + World wserv = this.getWorld(toWorld); - if(wserv != null) wserv.registerAccountCharacterView(chrView.getAccountID(), chrView); + if (wserv != null) { + wserv.registerAccountCharacterView(chrView.getAccountID(), chrView); + } } finally { lgnWLock.unlock(); } @@ -1482,25 +1445,27 @@ public class Server { } } */ - + public Pair>, List>>> loadAccountCharlist(Integer accountId, int visibleWorlds) { List wlist = this.getWorlds(); - if(wlist.size() > visibleWorlds) wlist = wlist.subList(0, visibleWorlds); - + if (wlist.size() > visibleWorlds) { + wlist = wlist.subList(0, visibleWorlds); + } + List>> accChars = new ArrayList<>(wlist.size() + 1); int chrTotal = 0; List lastwchars = null; - + lgnRLock.lock(); try { - for(World w : wlist) { + for (World w : wlist) { List wchars = w.getAccountCharactersView(accountId); - if(wchars == null) { - if(!accountChars.containsKey(accountId)) { + if (wchars == null) { + if (!accountChars.containsKey(accountId)) { accountCharacterCount.put(accountId, (short) 0); accountChars.put(accountId, new HashSet()); // not advisable at all to write on the map on a read-protected environment } // yet it's known there's no problem since no other point in the source does - } else if(!wchars.isEmpty()) { // this action. + } else if (!wchars.isEmpty()) { // this action. lastwchars = wchars; accChars.add(new Pair<>(w.getId(), wchars)); @@ -1510,84 +1475,83 @@ public class Server { } finally { lgnRLock.unlock(); } - + return new Pair<>(new Pair<>(chrTotal, lastwchars), accChars); } - + private static Pair>> loadAccountCharactersViewFromDb(int accId, int wlen) { short characterCount = 0; List> wchars = new ArrayList<>(wlen); - for(int i = 0; i < wlen; i++) wchars.add(i, new LinkedList()); - + for (int i = 0; i < wlen; i++) { + wchars.add(i, new LinkedList()); + } + List chars = new LinkedList<>(); int curWorld = 0; try { List> accEquips = ItemFactory.loadEquippedItems(accId, true, true); Map> accPlayerEquips = new HashMap<>(); - - for(Pair ae : accEquips) { + + for (Pair ae : accEquips) { List playerEquips = accPlayerEquips.get(ae.getRight()); - if(playerEquips == null) { + if (playerEquips == null) { playerEquips = new LinkedList<>(); accPlayerEquips.put(ae.getRight(), playerEquips); } - + playerEquips.add(ae.getLeft()); } - - Connection con = DatabaseConnection.getConnection(); - try (PreparedStatement ps = con.prepareStatement("SELECT * FROM characters WHERE accountid = ? ORDER BY world, id")) { + + + try (Connection con = DatabaseConnection.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM characters WHERE accountid = ? ORDER BY world, id")) { ps.setInt(1, accId); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { characterCount++; - - int cworld = rs.getByte("world"); - if(cworld >= wlen) continue; - if(cworld > curWorld) { + int cworld = rs.getByte("world"); + if (cworld >= wlen) { + continue; + } + + if (cworld > curWorld) { wchars.add(curWorld, chars); curWorld = cworld; chars = new LinkedList<>(); } - + Integer cid = rs.getInt("id"); chars.add(MapleCharacter.loadCharacterEntryFromDB(rs, accPlayerEquips.get(cid))); } } } - con.close(); - + wchars.add(curWorld, chars); } catch (SQLException sqle) { sqle.printStackTrace(); } - + return new Pair<>(characterCount, wchars); } - + public void loadAllAccountsCharactersView() { - try { - Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT id FROM accounts"); - ResultSet rs = ps.executeQuery(); - + try (Connection con = DatabaseConnection.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT id FROM accounts"); + ResultSet rs = ps.executeQuery()) { + while (rs.next()) { int accountId = rs.getInt("id"); if (isFirstAccountLogin(accountId)) { loadAccountCharactersView(accountId, 0, 0); } } - - rs.close(); - ps.close(); - con.close(); } catch (SQLException se) { se.printStackTrace(); } } - + private boolean isFirstAccountLogin(Integer accId) { lgnRLock.lock(); try { @@ -1596,52 +1560,55 @@ public class Server { lgnRLock.unlock(); } } - + private static void applyAllNameChanges() { try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL")) { - ResultSet rs = ps.executeQuery(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL"); + ResultSet rs = ps.executeQuery()) { List> changedNames = new LinkedList>(); //logging only - while(rs.next()) { + while (rs.next()) { con.setAutoCommit(false); int nameChangeId = rs.getInt("id"); int characterId = rs.getInt("characterId"); String oldName = rs.getString("old"); String newName = rs.getString("new"); - boolean success = MapleCharacter.doNameChange(con, characterId, oldName, newName, nameChangeId); - if(!success) con.rollback(); //discard changes - else changedNames.add(new Pair(oldName, newName)); + boolean success = MapleCharacter.doNameChange(con, characterId, oldName, newName, nameChangeId); + if (!success) { + con.rollback(); //discard changes + } else { + changedNames.add(new Pair(oldName, newName)); + } con.setAutoCommit(true); } //log - for(Pair namePair : changedNames) { + for (Pair namePair : changedNames) { FilePrinter.print(FilePrinter.CHANGE_CHARACTER_NAME, "Name change applied : from \"" + namePair.getLeft() + "\" to \"" + namePair.getRight() + "\" at " + Calendar.getInstance().getTime().toString()); } - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); FilePrinter.printError(FilePrinter.CHANGE_CHARACTER_NAME, e, "Failed to retrieve list of pending name changes."); } } - + private static void applyAllWorldTransfers() { try (Connection con = DatabaseConnection.getConnection(); - PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL", - ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)) { - ResultSet rs = ps.executeQuery(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL", + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + ResultSet rs = ps.executeQuery()) { List removedTransfers = new LinkedList(); - while(rs.next()) { + while (rs.next()) { int nameChangeId = rs.getInt("id"); int characterId = rs.getInt("characterId"); int oldWorld = rs.getInt("from"); int newWorld = rs.getInt("to"); String reason = MapleCharacter.checkWorldTransferEligibility(con, characterId, oldWorld, newWorld); //check if character is still eligible - if(reason != null) { + if (reason != null) { removedTransfers.add(nameChangeId); FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer cancelled : Character ID " + characterId + " at " + Calendar.getInstance().getTime().toString() + ", Reason : " + reason); try (PreparedStatement delPs = con.prepareStatement("DELETE FROM worldtransfers WHERE id = ?")) { delPs.setInt(1, nameChangeId); delPs.executeUpdate(); - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); FilePrinter.printError(FilePrinter.WORLD_TRANSFER, e, "Failed to delete world transfer for character ID " + characterId); } @@ -1649,36 +1616,41 @@ public class Server { } rs.beforeFirst(); List>> worldTransfers = new LinkedList>>(); //logging only > - while(rs.next()) { + while (rs.next()) { con.setAutoCommit(false); int nameChangeId = rs.getInt("id"); - if(removedTransfers.contains(nameChangeId)) continue; + if (removedTransfers.contains(nameChangeId)) { + continue; + } int characterId = rs.getInt("characterId"); int oldWorld = rs.getInt("from"); int newWorld = rs.getInt("to"); boolean success = MapleCharacter.doWorldTransfer(con, characterId, oldWorld, newWorld, nameChangeId); - if(!success) con.rollback(); - else worldTransfers.add(new Pair>(characterId, new Pair(oldWorld, newWorld))); + if (!success) { + con.rollback(); + } else { + worldTransfers.add(new Pair>(characterId, new Pair(oldWorld, newWorld))); + } con.setAutoCommit(true); } //log - for(Pair> worldTransferPair : worldTransfers) { + for (Pair> worldTransferPair : worldTransfers) { int charId = worldTransferPair.getLeft(); int oldWorld = worldTransferPair.getRight().getLeft(); int newWorld = worldTransferPair.getRight().getRight(); FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer applied : Character ID " + charId + " from World " + oldWorld + " to World " + newWorld + " at " + Calendar.getInstance().getTime().toString()); } - } catch(SQLException e) { + } catch (SQLException e) { e.printStackTrace(); FilePrinter.printError(FilePrinter.WORLD_TRANSFER, e, "Failed to retrieve list of pending world transfers."); } } - + public void loadAccountCharacters(MapleClient c) { Integer accId = c.getAccID(); if (!isFirstAccountLogin(accId)) { Set accWorlds = new HashSet<>(); - + lgnRLock.lock(); try { for (Integer chrid : getAccountCharacterEntries(accId)) { @@ -1687,69 +1659,73 @@ public class Server { } finally { lgnRLock.unlock(); } - + int gmLevel = 0; for (Integer aw : accWorlds) { World wserv = this.getWorld(aw); - + if (wserv != null) { for (MapleCharacter chr : wserv.getAllCharactersView()) { - if (gmLevel < chr.gmLevel()) gmLevel = chr.gmLevel(); + if (gmLevel < chr.gmLevel()) { + gmLevel = chr.gmLevel(); + } } } } - + c.setGMLevel(gmLevel); return; } - + int gmLevel = loadAccountCharactersView(c.getAccID(), 0, 0); c.setGMLevel(gmLevel); } - + private int loadAccountCharactersView(Integer accId, int gmLevel, int fromWorldid) { // returns the maximum gmLevel found List wlist = this.getWorlds(); Pair>> accCharacters = loadAccountCharactersViewFromDb(accId, wlist.size()); - + lgnWLock.lock(); try { List> accChars = accCharacters.getRight(); accountCharacterCount.put(accId, accCharacters.getLeft()); - + Set chars = accountChars.get(accId); - if(chars == null) { + if (chars == null) { chars = new HashSet<>(5); } - + for (int wid = fromWorldid; wid < wlist.size(); wid++) { World w = wlist.get(wid); List wchars = accChars.get(wid); w.loadAccountCharactersView(accId, wchars); - + for (MapleCharacter chr : wchars) { int cid = chr.getId(); - if (gmLevel < chr.gmLevel()) gmLevel = chr.gmLevel(); - + if (gmLevel < chr.gmLevel()) { + gmLevel = chr.gmLevel(); + } + chars.add(cid); worldChars.put(cid, wid); } } - + accountChars.put(accId, chars); } finally { lgnWLock.unlock(); } - + return gmLevel; } - + public void loadAccountStorages(MapleClient c) { int accountId = c.getAccID(); Set accWorlds = new HashSet<>(); lgnWLock.lock(); try { Set chars = accountChars.get(accountId); - + for (Integer cid : chars) { Integer worldid = worldChars.get(cid); if (worldid != null) { @@ -1759,7 +1735,7 @@ public class Server { } finally { lgnWLock.unlock(); } - + List worldList = this.getWorlds(); for (Integer worldid : accWorlds) { if (worldid < worldList.size()) { @@ -1768,14 +1744,14 @@ public class Server { } } } - + private static String getRemoteHost(MapleClient client) { return MapleSessionCoordinator.getSessionRemoteHost(client.getSession()); } - + public void setCharacteridInTransition(MapleClient client, int charId) { String remoteIp = getRemoteHost(client); - + lgnWLock.lock(); try { transitioningChars.put(remoteIp, charId); @@ -1783,14 +1759,14 @@ public class Server { lgnWLock.unlock(); } } - + public boolean validateCharacteridInTransition(MapleClient client, int charId) { if (!YamlConfig.config.server.USE_IP_VALIDATION) { return true; } - + String remoteIp = getRemoteHost(client); - + lgnWLock.lock(); try { Integer cid = transitioningChars.remove(remoteIp); @@ -1799,14 +1775,14 @@ public class Server { lgnWLock.unlock(); } } - + public Integer freeCharacteridInTransition(MapleClient client) { if (!YamlConfig.config.server.USE_IP_VALIDATION) { return null; } - + String remoteIp = getRemoteHost(client); - + lgnWLock.lock(); try { return transitioningChars.remove(remoteIp); @@ -1814,14 +1790,14 @@ public class Server { lgnWLock.unlock(); } } - + public boolean hasCharacteridInTransition(MapleClient client) { if (!YamlConfig.config.server.USE_IP_VALIDATION) { return true; } - + String remoteIp = getRemoteHost(client); - + lgnRLock.lock(); try { return transitioningChars.containsKey(remoteIp); @@ -1829,7 +1805,7 @@ public class Server { lgnRLock.unlock(); } } - + public void registerLoginState(MapleClient c) { srvLock.lock(); try { @@ -1838,7 +1814,7 @@ public class Server { srvLock.unlock(); } } - + public void unregisterLoginState(MapleClient c) { srvLock.lock(); try { @@ -1847,36 +1823,36 @@ public class Server { srvLock.unlock(); } } - + private void disconnectIdlesOnLoginState() { List toDisconnect = new LinkedList<>(); - + srvLock.lock(); try { long timeNow = System.currentTimeMillis(); - - for(Entry mc : inLoginState.entrySet()) { - if(timeNow > mc.getValue()) { + + for (Entry mc : inLoginState.entrySet()) { + if (timeNow > mc.getValue()) { toDisconnect.add(mc.getKey()); } } - - for(MapleClient c : toDisconnect) { + + for (MapleClient c : toDisconnect) { inLoginState.remove(c); } } finally { srvLock.unlock(); } - + for (MapleClient c : toDisconnect) { // thanks Lei for pointing a deadlock issue with srvLock - if(c.isLoggedIn()) { + if (c.isLoggedIn()) { c.disconnect(false, false); } else { MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true); } } } - + private void disconnectIdlesOnLoginTask() { TimerManager.getInstance().register(new Runnable() { @Override @@ -1885,7 +1861,7 @@ public class Server { } }, 300000); } - + public final Runnable shutdown(final boolean restart) {//no player should be online when trying to shutdown! return new Runnable() { @Override @@ -1894,10 +1870,12 @@ public class Server { } }; } - + private synchronized void shutdownInternal(boolean restart) { System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n"); - if (getWorlds() == null) return;//already shutdown + if (getWorlds() == null) { + return;//already shutdown + } for (World w : getWorlds()) { w.shutdown(); } @@ -1923,7 +1901,9 @@ public class Server { List allChannels = getAllChannels(); - if(YamlConfig.config.server.USE_THREAD_TRACKER) ThreadTracker.getInstance().cancelThreadTrackerTask(); + if (YamlConfig.config.server.USE_THREAD_TRACKER) { + ThreadTracker.getInstance().cancelThreadTrackerTask(); + } for (Channel ch : allChannels) { while (!ch.finishedShutdown()) { @@ -1935,13 +1915,13 @@ public class Server { } } } - + resetServerWorlds(); - + ThreadManager.getInstance().stop(); TimerManager.getInstance().purge(); TimerManager.getInstance().stop(); - + System.out.println("Worlds + Channels are offline."); acceptor.unbind(); acceptor = null;