Merge pull request #20 from P0nk/faster-startup
Improve the startup sequence
This commit is contained in:
@@ -182,97 +182,95 @@ public class MapleFamily {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadAllFamilies() {
|
public static void loadAllFamilies(Connection con) {
|
||||||
try(Connection con = DatabaseConnection.getConnection()) {
|
List<Pair<Pair<Integer, Integer>, MapleFamilyEntry>> unmatchedJuniors = new ArrayList<>(200); // <<world, seniorid> familyEntry>
|
||||||
List<Pair<Pair<Integer, Integer>, MapleFamilyEntry>> unmatchedJuniors = new ArrayList<>(200); // <<world, seniorid> familyEntry>
|
try (PreparedStatement psEntries = con.prepareStatement("SELECT * FROM family_character")) {
|
||||||
try(PreparedStatement psEntries = con.prepareStatement("SELECT * FROM family_character")) {
|
ResultSet rsEntries = psEntries.executeQuery();
|
||||||
ResultSet rsEntries = psEntries.executeQuery();
|
while (rsEntries.next()) { // can be optimized
|
||||||
while(rsEntries.next()) { // can be optimized
|
int cid = rsEntries.getInt("cid");
|
||||||
int cid = rsEntries.getInt("cid");
|
String name = null;
|
||||||
String name = null;
|
int level = -1;
|
||||||
int level = -1;
|
int jobID = -1;
|
||||||
int jobID = -1;
|
int world = -1;
|
||||||
int world = -1;
|
try (PreparedStatement ps = con.prepareStatement("SELECT world, name, level, job FROM characters WHERE id = ?")) {
|
||||||
try(PreparedStatement ps = con.prepareStatement("SELECT world, name, level, job FROM characters WHERE id = ?")) {
|
ps.setInt(1, cid);
|
||||||
ps.setInt(1, cid);
|
ResultSet rs = ps.executeQuery();
|
||||||
ResultSet rs = ps.executeQuery();
|
if (rs.next()) {
|
||||||
if(rs.next()) {
|
world = rs.getInt("world");
|
||||||
world = rs.getInt("world");
|
name = rs.getString("name");
|
||||||
name = rs.getString("name");
|
level = rs.getInt("level");
|
||||||
level = rs.getInt("level");
|
jobID = rs.getInt("job");
|
||||||
jobID = rs.getInt("job");
|
|
||||||
} else {
|
|
||||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not load character information of " + cid + " in loadAllFamilies(). (RECORD DOES NOT EXIST)");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} catch(SQLException e) {
|
|
||||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not load character information of " + cid + " in loadAllFamilies(). (SQL ERROR)");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int familyid = rsEntries.getInt("familyid");
|
|
||||||
int seniorid = rsEntries.getInt("seniorid");
|
|
||||||
int reputation = rsEntries.getInt("reputation");
|
|
||||||
int todaysRep = rsEntries.getInt("todaysrep");
|
|
||||||
int totalRep = rsEntries.getInt("totalreputation");
|
|
||||||
int repsToSenior = rsEntries.getInt("reptosenior");
|
|
||||||
String precepts = rsEntries.getString("precepts");
|
|
||||||
//Timestamp lastResetTime = rsEntries.getTimestamp("lastresettime"); //taken care of by FamilyDailyResetTask
|
|
||||||
World wserv = Server.getInstance().getWorld(world);
|
|
||||||
if (wserv == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MapleFamily family = wserv.getFamily(familyid);
|
|
||||||
if(family == null) {
|
|
||||||
family = new MapleFamily(familyid, world);
|
|
||||||
Server.getInstance().getWorld(world).addFamily(familyid, family);
|
|
||||||
}
|
|
||||||
MapleFamilyEntry familyEntry = new MapleFamilyEntry(family, cid, name, level, MapleJob.getById(jobID));
|
|
||||||
family.addEntry(familyEntry);
|
|
||||||
if(seniorid <= 0) {
|
|
||||||
family.setLeader(familyEntry);
|
|
||||||
family.setMessage(precepts, false);
|
|
||||||
}
|
|
||||||
MapleFamilyEntry senior = family.getEntryByID(seniorid);
|
|
||||||
if(senior != null) {
|
|
||||||
familyEntry.setSenior(family.getEntryByID(seniorid), false);
|
|
||||||
} else {
|
} else {
|
||||||
if(seniorid > 0) unmatchedJuniors.add(new Pair<>(new Pair<>(world, seniorid), familyEntry));
|
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not load character information of " + cid + " in loadAllFamilies(). (RECORD DOES NOT EXIST)");
|
||||||
}
|
continue;
|
||||||
familyEntry.setReputation(reputation);
|
|
||||||
familyEntry.setTodaysRep(todaysRep);
|
|
||||||
familyEntry.setTotalReputation(totalRep);
|
|
||||||
familyEntry.setRepsToSenior(repsToSenior);
|
|
||||||
//load used entitlements
|
|
||||||
try (PreparedStatement ps = con.prepareStatement("SELECT entitlementid FROM family_entitlement WHERE charid = ?")) {
|
|
||||||
ps.setInt(1, familyEntry.getChrId());
|
|
||||||
ResultSet rs = ps.executeQuery();
|
|
||||||
while(rs.next()) {
|
|
||||||
familyEntry.setEntitlementUsed(rs.getInt("entitlementid"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not load character information of " + cid + " in loadAllFamilies(). (SQL ERROR)");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
} catch(SQLException e) {
|
int familyid = rsEntries.getInt("familyid");
|
||||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get family_character entries.");
|
int seniorid = rsEntries.getInt("seniorid");
|
||||||
e.printStackTrace();
|
int reputation = rsEntries.getInt("reputation");
|
||||||
}
|
int todaysRep = rsEntries.getInt("todaysrep");
|
||||||
// link missing ones (out of order)
|
int totalRep = rsEntries.getInt("totalreputation");
|
||||||
for(Pair<Pair<Integer, Integer>, MapleFamilyEntry> unmatchedJunior : unmatchedJuniors) {
|
int repsToSenior = rsEntries.getInt("reptosenior");
|
||||||
int world = unmatchedJunior.getLeft().getLeft();
|
String precepts = rsEntries.getString("precepts");
|
||||||
int seniorid = unmatchedJunior.getLeft().getRight();
|
//Timestamp lastResetTime = rsEntries.getTimestamp("lastresettime"); //taken care of by FamilyDailyResetTask
|
||||||
MapleFamilyEntry junior = unmatchedJunior.getRight();
|
World wserv = Server.getInstance().getWorld(world);
|
||||||
MapleFamilyEntry senior = Server.getInstance().getWorld(world).getFamily(junior.getFamily().getID()).getEntryByID(seniorid);
|
if (wserv == null) {
|
||||||
if(senior != null) {
|
continue;
|
||||||
junior.setSenior(senior, false);
|
}
|
||||||
|
MapleFamily family = wserv.getFamily(familyid);
|
||||||
|
if (family == null) {
|
||||||
|
family = new MapleFamily(familyid, world);
|
||||||
|
Server.getInstance().getWorld(world).addFamily(familyid, family);
|
||||||
|
}
|
||||||
|
MapleFamilyEntry familyEntry = new MapleFamilyEntry(family, cid, name, level, MapleJob.getById(jobID));
|
||||||
|
family.addEntry(familyEntry);
|
||||||
|
if (seniorid <= 0) {
|
||||||
|
family.setLeader(familyEntry);
|
||||||
|
family.setMessage(precepts, false);
|
||||||
|
}
|
||||||
|
MapleFamilyEntry senior = family.getEntryByID(seniorid);
|
||||||
|
if (senior != null) {
|
||||||
|
familyEntry.setSenior(family.getEntryByID(seniorid), false);
|
||||||
} else {
|
} else {
|
||||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Missing senior for character " + junior.getName() + " in world " + world);
|
if (seniorid > 0) {
|
||||||
|
unmatchedJuniors.add(new Pair<>(new Pair<>(world, seniorid), familyEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
familyEntry.setReputation(reputation);
|
||||||
|
familyEntry.setTodaysRep(todaysRep);
|
||||||
|
familyEntry.setTotalReputation(totalRep);
|
||||||
|
familyEntry.setRepsToSenior(repsToSenior);
|
||||||
|
//load used entitlements
|
||||||
|
try (PreparedStatement ps = con.prepareStatement("SELECT entitlementid FROM family_entitlement WHERE charid = ?")) {
|
||||||
|
ps.setInt(1, familyEntry.getChrId());
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
familyEntry.setEntitlementUsed(rs.getInt("entitlementid"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(SQLException e) {
|
} catch (SQLException e) {
|
||||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get DB connection.");
|
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get family_character entries.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
for(World world : Server.getInstance().getWorlds()) {
|
// link missing ones (out of order)
|
||||||
for(MapleFamily family : world.getFamilies()) {
|
for (Pair<Pair<Integer, Integer>, MapleFamilyEntry> unmatchedJunior : unmatchedJuniors) {
|
||||||
|
int world = unmatchedJunior.getLeft().getLeft();
|
||||||
|
int seniorid = unmatchedJunior.getLeft().getRight();
|
||||||
|
MapleFamilyEntry junior = unmatchedJunior.getRight();
|
||||||
|
MapleFamilyEntry senior = Server.getInstance().getWorld(world).getFamily(junior.getFamily().getID()).getEntryByID(seniorid);
|
||||||
|
if (senior != null) {
|
||||||
|
junior.setSenior(senior, false);
|
||||||
|
} else {
|
||||||
|
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Missing senior for character " + junior.getName() + " in world " + world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (World world : Server.getInstance().getWorlds()) {
|
||||||
|
for (MapleFamily family : world.getFamilies()) {
|
||||||
family.getLeader().doFullCount();
|
family.getLeader().doFullCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,33 +31,32 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SkillFactory {
|
public class SkillFactory {
|
||||||
private static Map<Integer, Skill> skills = new HashMap<>();
|
private static volatile Map<Integer, Skill> skills = new HashMap<>();
|
||||||
private static MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz"));
|
private static final MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz"));
|
||||||
|
|
||||||
public static Skill getSkill(int id) {
|
public static Skill getSkill(int id) {
|
||||||
if (!skills.isEmpty()) {
|
return skills.get(id);
|
||||||
return skills.get(id);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadAllSkills() {
|
public static void loadAllSkills() {
|
||||||
|
final Map<Integer, Skill> loadedSkills = new HashMap<>();
|
||||||
final MapleDataDirectoryEntry root = datasource.getRoot();
|
final MapleDataDirectoryEntry root = datasource.getRoot();
|
||||||
int skillid;
|
|
||||||
for (MapleDataFileEntry topDir : root.getFiles()) { // Loop thru jobs
|
for (MapleDataFileEntry topDir : root.getFiles()) { // Loop thru jobs
|
||||||
if (topDir.getName().length() <= 8) {
|
if (topDir.getName().length() <= 8) {
|
||||||
for (MapleData data : datasource.getData(topDir.getName())) { // Loop thru each jobs
|
for (MapleData data : datasource.getData(topDir.getName())) { // Loop thru each jobs
|
||||||
if (data.getName().equals("skill")) {
|
if (data.getName().equals("skill")) {
|
||||||
for (MapleData data2 : data) { // Loop thru each jobs
|
for (MapleData data2 : data) { // Loop thru each jobs
|
||||||
if (data2 != null) {
|
if (data2 != null) {
|
||||||
skillid = Integer.parseInt(data2.getName());
|
int skillId = Integer.parseInt(data2.getName());
|
||||||
skills.put(skillid, loadFromData(skillid, data2));
|
loadedSkills.put(skillId, loadFromData(skillId, data2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skills = loadedSkills;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Skill loadFromData(int id, MapleData data) {
|
private static Skill loadFromData(int id, MapleData data) {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
package client.inventory.manipulator;
|
package client.inventory.manipulator;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import tools.DatabaseConnection;
|
import tools.DatabaseConnection;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@@ -32,7 +34,7 @@ import java.util.Set;
|
|||||||
* @author RonanLana
|
* @author RonanLana
|
||||||
*/
|
*/
|
||||||
public class MapleCashidGenerator {
|
public class MapleCashidGenerator {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(MapleCashidGenerator.class);
|
||||||
private final static Set<Integer> existentCashids = new HashSet<>(10000);
|
private final static Set<Integer> existentCashids = new HashSet<>(10000);
|
||||||
private static Integer runningCashid = 0;
|
private static Integer runningCashid = 0;
|
||||||
|
|
||||||
@@ -49,13 +51,9 @@ public class MapleCashidGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void loadExistentCashIdsFromDb() {
|
public static synchronized void loadExistentCashIdsFromDb(Connection con) throws SQLException {
|
||||||
try (Connection con = DatabaseConnection.getConnection()) {
|
loadExistentCashIdsFromQuery(con, "SELECT id FROM rings");
|
||||||
loadExistentCashIdsFromQuery(con, "SELECT id FROM rings");
|
loadExistentCashIdsFromQuery(con, "SELECT petid FROM pets");
|
||||||
loadExistentCashIdsFromQuery(con, "SELECT petid FROM pets");
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
runningCashid = 0;
|
runningCashid = 0;
|
||||||
do {
|
do {
|
||||||
@@ -67,7 +65,11 @@ public class MapleCashidGenerator {
|
|||||||
runningCashid++;
|
runningCashid++;
|
||||||
if (runningCashid >= 777000000) {
|
if (runningCashid >= 777000000) {
|
||||||
existentCashids.clear();
|
existentCashids.clear();
|
||||||
loadExistentCashIdsFromDb();
|
try (Connection con = DatabaseConnection.getConnection()) {
|
||||||
|
loadExistentCashIdsFromDb(con);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.warn("Failed to reset overflowing cash ids", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -339,22 +339,18 @@ public class NewYearCardRecord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startPendingNewYearCardRequests() {
|
public static void startPendingNewYearCardRequests(Connection con) throws SQLException {
|
||||||
try (Connection con = DatabaseConnection.getConnection()) {
|
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE timereceived = 0 AND senderdiscard = 0")) {
|
||||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE timereceived = 0 AND senderdiscard = 0")) {
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
while (rs.next()) {
|
||||||
while (rs.next()) {
|
NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message"));
|
||||||
NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message"));
|
newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived"));
|
||||||
newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived"));
|
|
||||||
|
Server.getInstance().setNewYearCard(newyear);
|
||||||
Server.getInstance().setNewYearCard(newyear);
|
newyear.startNewYearCardTask();
|
||||||
newyear.startNewYearCardTask();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(SQLException sqle) {
|
|
||||||
sqle.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,8 +80,13 @@ import java.sql.Connection;
|
|||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
@@ -134,7 +139,7 @@ public class Server {
|
|||||||
private final AtomicLong currentTime = new AtomicLong(0);
|
private final AtomicLong currentTime = new AtomicLong(0);
|
||||||
private long serverCurrentTime = 0;
|
private long serverCurrentTime = 0;
|
||||||
|
|
||||||
private boolean availableDeveloperRoom = false;
|
private volatile boolean availableDeveloperRoom = false;
|
||||||
private boolean online = false;
|
private boolean online = false;
|
||||||
public static long uptime = System.currentTimeMillis();
|
public static long uptime = System.currentTimeMillis();
|
||||||
|
|
||||||
@@ -625,7 +630,7 @@ public class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateActiveCoupons() throws SQLException {
|
public void updateActiveCoupons(Connection con) throws SQLException {
|
||||||
synchronized (activeCoupons) {
|
synchronized (activeCoupons) {
|
||||||
activeCoupons.clear();
|
activeCoupons.clear();
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
@@ -633,23 +638,19 @@ public class Server {
|
|||||||
int weekDay = c.get(Calendar.DAY_OF_WEEK);
|
int weekDay = c.get(Calendar.DAY_OF_WEEK);
|
||||||
int hourDay = c.get(Calendar.HOUR_OF_DAY);
|
int hourDay = c.get(Calendar.HOUR_OF_DAY);
|
||||||
|
|
||||||
try (Connection con = DatabaseConnection.getConnection()) {
|
int weekdayMask = (1 << weekDay);
|
||||||
|
PreparedStatement ps = con.prepareStatement("SELECT couponid FROM nxcoupons WHERE (activeday & ?) = ? AND starthour <= ? AND endhour > ?");
|
||||||
|
ps.setInt(1, weekdayMask);
|
||||||
|
ps.setInt(2, weekdayMask);
|
||||||
|
ps.setInt(3, hourDay);
|
||||||
|
ps.setInt(4, hourDay);
|
||||||
|
|
||||||
int weekdayMask = (1 << weekDay);
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT couponid FROM nxcoupons WHERE (activeday & ?) = ? AND starthour <= ? AND endhour > ?");
|
while (rs.next()) {
|
||||||
ps.setInt(1, weekdayMask);
|
activeCoupons.add(rs.getInt("couponid"));
|
||||||
ps.setInt(2, weekdayMask);
|
|
||||||
ps.setInt(3, hourDay);
|
|
||||||
ps.setInt(4, hourDay);
|
|
||||||
|
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
|
||||||
while (rs.next()) {
|
|
||||||
activeCoupons.add(rs.getInt("couponid"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,7 +704,7 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void installWorldPlayerRanking(int worldid) {
|
private void installWorldPlayerRanking(int worldid) {
|
||||||
List<Pair<Integer, List<Pair<String, Integer>>>> ranking = updatePlayerRankingFromDB(worldid);
|
List<Pair<Integer, List<Pair<String, Integer>>>> ranking = loadPlayerRankingFromDB(worldid);
|
||||||
if (!ranking.isEmpty()) {
|
if (!ranking.isEmpty()) {
|
||||||
wldWLock.lock();
|
wldWLock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -735,7 +736,7 @@ public class Server {
|
|||||||
wldWLock.unlock();
|
wldWLock.unlock();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List<Pair<Integer, List<Pair<String, Integer>>>> ranking = updatePlayerRankingFromDB(-1 * (this.getWorldsSize() - 2)); // update ranking list
|
List<Pair<Integer, List<Pair<String, Integer>>>> ranking = loadPlayerRankingFromDB(-1 * (this.getWorldsSize() - 2)); // update ranking list
|
||||||
|
|
||||||
wldWLock.lock();
|
wldWLock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -747,40 +748,47 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateWorldPlayerRanking() {
|
public void updateWorldPlayerRanking() {
|
||||||
List<Pair<Integer, List<Pair<String, Integer>>>> rankUpdates = updatePlayerRankingFromDB(-1 * (this.getWorldsSize() - 1));
|
List<Pair<Integer, List<Pair<String, Integer>>>> rankUpdates = loadPlayerRankingFromDB(-1 * (this.getWorldsSize() - 1));
|
||||||
if (!rankUpdates.isEmpty()) {
|
if (rankUpdates.isEmpty()) {
|
||||||
wldWLock.lock();
|
return;
|
||||||
try {
|
|
||||||
if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) {
|
|
||||||
for (int i = playerRanking.size(); i <= rankUpdates.get(rankUpdates.size() - 1).getLeft(); i++) {
|
|
||||||
playerRanking.add(new ArrayList<>(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Pair<Integer, List<Pair<String, Integer>>> wranks : rankUpdates) {
|
|
||||||
playerRanking.set(wranks.getLeft(), wranks.getRight());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
playerRanking.set(0, rankUpdates.get(0).getRight());
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
wldWLock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wldWLock.lock();
|
||||||
|
try {
|
||||||
|
if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) {
|
||||||
|
for (int i = playerRanking.size(); i <= rankUpdates.get(rankUpdates.size() - 1).getLeft(); i++) {
|
||||||
|
playerRanking.add(new ArrayList<>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Pair<Integer, List<Pair<String, Integer>>> wranks : rankUpdates) {
|
||||||
|
playerRanking.set(wranks.getLeft(), wranks.getRight());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
playerRanking.set(0, rankUpdates.get(0).getRight());
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
wldWLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initWorldPlayerRanking() {
|
private void initWorldPlayerRanking() {
|
||||||
if (YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) {
|
if (YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) {
|
||||||
playerRanking.add(new ArrayList<>(0));
|
wldWLock.lock();
|
||||||
|
try {
|
||||||
|
playerRanking.add(new ArrayList<>(0));
|
||||||
|
} finally {
|
||||||
|
wldWLock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateWorldPlayerRanking();
|
updateWorldPlayerRanking();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Pair<Integer, List<Pair<String, Integer>>>> updatePlayerRankingFromDB(int worldid) {
|
private static List<Pair<Integer, List<Pair<String, Integer>>>> loadPlayerRankingFromDB(int worldid) {
|
||||||
List<Pair<Integer, List<Pair<String, Integer>>>> rankSystem = new ArrayList<>();
|
List<Pair<Integer, List<Pair<String, Integer>>>> rankSystem = new ArrayList<>();
|
||||||
List<Pair<String, Integer>> rankUpdate = new ArrayList<>(0);
|
|
||||||
|
|
||||||
try (Connection con = DatabaseConnection.getConnection()) {
|
try (Connection con = DatabaseConnection.getConnection()) {
|
||||||
|
|
||||||
String worldQuery;
|
String worldQuery;
|
||||||
if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) {
|
if (!YamlConfig.config.server.USE_WHOLE_SERVER_RANKING) {
|
||||||
if (worldid >= 0) {
|
if (worldid >= 0) {
|
||||||
@@ -792,6 +800,7 @@ public class Server {
|
|||||||
worldQuery = (" AND `characters`.`world` >= 0 AND `characters`.`world` <= " + Math.abs(worldid));
|
worldQuery = (" AND `characters`.`world` >= 0 AND `characters`.`world` <= " + Math.abs(worldid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Pair<String, Integer>> rankUpdate = new ArrayList<>(0);
|
||||||
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");
|
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()) {
|
ResultSet rs = ps.executeQuery()) {
|
||||||
|
|
||||||
@@ -824,6 +833,7 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
|
Instant beforeInit = Instant.now();
|
||||||
log.info("Cosmic v{} starting up.", ServerConstants.VERSION);
|
log.info("Cosmic v{} starting up.", ServerConstants.VERSION);
|
||||||
|
|
||||||
if (YamlConfig.config.server.SHUTDOWNHOOK) {
|
if (YamlConfig.config.server.SHUTDOWNHOOK) {
|
||||||
@@ -834,50 +844,39 @@ public class Server {
|
|||||||
throw new IllegalStateException("Failed to initiate a connection to the database");
|
throw new IllegalStateException("Failed to initiate a connection to the database");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ExecutorService initExecutor = Executors.newFixedThreadPool(10);
|
||||||
|
// Run slow operations asynchronously to make startup faster
|
||||||
|
final List<Future<?>> futures = new ArrayList<>();
|
||||||
|
futures.add(initExecutor.submit(() -> SkillFactory.loadAllSkills()));
|
||||||
|
futures.add(initExecutor.submit(() -> CashItemFactory.loadAllCashItems()));
|
||||||
|
futures.add(initExecutor.submit(() -> MapleQuest.loadAllQuests()));
|
||||||
|
futures.add(initExecutor.submit(() -> MapleSkillbookInformationProvider.loadAllSkillbookInformation()));
|
||||||
|
futures.add(initExecutor.submit(() -> MaplePlayerNPCFactory.loadFactoryMetadata()));
|
||||||
|
|
||||||
TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE));
|
TimeZone.setDefault(TimeZone.getTimeZone(YamlConfig.config.server.TIMEZONE));
|
||||||
|
|
||||||
try (Connection con = DatabaseConnection.getConnection()) {
|
try (Connection con = DatabaseConnection.getConnection()) {
|
||||||
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0")) {
|
setAllLoggedOut(con);
|
||||||
ps.executeUpdate();
|
setAllMerchantsInactive(con);
|
||||||
}
|
|
||||||
|
|
||||||
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0")) {
|
|
||||||
ps.executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanNxcodeCoupons(con);
|
cleanNxcodeCoupons(con);
|
||||||
loadCouponRates(con);
|
loadCouponRates(con);
|
||||||
updateActiveCoupons();
|
updateActiveCoupons(con);
|
||||||
} catch (SQLException sqle) {
|
NewYearCardRecord.startPendingNewYearCardRequests(con);
|
||||||
sqle.printStackTrace();
|
MapleCashidGenerator.loadExistentCashIdsFromDb(con);
|
||||||
}
|
applyAllNameChanges(con); // -- name changes can be missed by INSTANT_NAME_CHANGE --
|
||||||
|
applyAllWorldTransfers(con);
|
||||||
|
|
||||||
applyAllNameChanges(); // -- name changes can be missed by INSTANT_NAME_CHANGE --
|
if (YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||||
applyAllWorldTransfers();
|
MapleFamily.loadAllFamilies(con);
|
||||||
//MaplePet.clearMissingPetsFromDb(); // thanks Optimist for noticing this taking too long to run
|
}
|
||||||
MapleCashidGenerator.loadExistentCashIdsFromDb();
|
} catch (SQLException sqle) {
|
||||||
|
log.error("Failed to run all startup-bound database tasks", sqle);
|
||||||
|
throw new IllegalStateException(sqle);
|
||||||
|
}
|
||||||
|
|
||||||
ThreadManager.getInstance().start();
|
ThreadManager.getInstance().start();
|
||||||
initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan
|
initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan
|
||||||
|
|
||||||
long timeToTake = System.currentTimeMillis();
|
|
||||||
SkillFactory.loadAllSkills();
|
|
||||||
final double skillLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0;
|
|
||||||
log.info("Skills loaded in {} seconds", skillLoadTime);
|
|
||||||
|
|
||||||
timeToTake = System.currentTimeMillis();
|
|
||||||
|
|
||||||
CashItemFactory.getSpecialCashItems();
|
|
||||||
final double itemLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0;
|
|
||||||
log.info("Items loaded in {} seconds", itemLoadTime);
|
|
||||||
|
|
||||||
timeToTake = System.currentTimeMillis();
|
|
||||||
MapleQuest.loadAllQuest();
|
|
||||||
final double questLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0;
|
|
||||||
log.info("Quest loaded in {} seconds", questLoadTime);
|
|
||||||
|
|
||||||
NewYearCardRecord.startPendingNewYearCardRequests();
|
|
||||||
|
|
||||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||||
ThreadTracker.getInstance().registerThreadTrackerTask();
|
ThreadTracker.getInstance().registerThreadTrackerTask();
|
||||||
}
|
}
|
||||||
@@ -890,7 +889,6 @@ public class Server {
|
|||||||
}
|
}
|
||||||
initWorldPlayerRanking();
|
initWorldPlayerRanking();
|
||||||
|
|
||||||
MaplePlayerNPCFactory.loadFactoryMetadata();
|
|
||||||
loadPlayerNpcMapStepFromDb();
|
loadPlayerNpcMapStepFromDb();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();//For those who get errors
|
e.printStackTrace();//For those who get errors
|
||||||
@@ -898,11 +896,14 @@ public class Server {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
// Wait on all async tasks to complete
|
||||||
timeToTake = System.currentTimeMillis();
|
for (Future<?> future : futures) {
|
||||||
MapleFamily.loadAllFamilies();
|
try {
|
||||||
final double familyLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0;
|
future.get();
|
||||||
log.info("Families loaded in {} seconds", familyLoadTime);
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to run all startup-bound loading tasks", e);
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IoBuffer.setUseDirectBuffer(false); // join IO operations performed by lxconan
|
IoBuffer.setUseDirectBuffer(false); // join IO operations performed by lxconan
|
||||||
@@ -919,10 +920,10 @@ public class Server {
|
|||||||
|
|
||||||
log.info("Listening on port 8484");
|
log.info("Listening on port 8484");
|
||||||
|
|
||||||
log.info("Cosmic is now online.");
|
|
||||||
online = true;
|
online = true;
|
||||||
|
Duration initDuration = Duration.between(beforeInit, Instant.now());
|
||||||
|
log.info("Cosmic is now online after {} ms.", initDuration.toMillis());
|
||||||
|
|
||||||
MapleSkillbookInformationProvider.getInstance();
|
|
||||||
OpcodeConstants.generateOpcodeNames();
|
OpcodeConstants.generateOpcodeNames();
|
||||||
CommandsExecutor.getInstance();
|
CommandsExecutor.getInstance();
|
||||||
|
|
||||||
@@ -931,6 +932,18 @@ public class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void setAllLoggedOut(Connection con) throws SQLException {
|
||||||
|
try (PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = 0")) {
|
||||||
|
ps.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setAllMerchantsInactive(Connection con) throws SQLException {
|
||||||
|
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET HasMerchant = 0")) {
|
||||||
|
ps.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeTimelyTasks() {
|
private void initializeTimelyTasks() {
|
||||||
TimerManager tMan = TimerManager.getInstance();
|
TimerManager tMan = TimerManager.getInstance();
|
||||||
tMan.start();
|
tMan.start();
|
||||||
@@ -1570,39 +1583,42 @@ public class Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyAllNameChanges() {
|
private static void applyAllNameChanges(Connection con) throws SQLException {
|
||||||
try (Connection con = DatabaseConnection.getConnection();
|
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL");
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL");
|
|
||||||
ResultSet rs = ps.executeQuery()) {
|
ResultSet rs = ps.executeQuery()) {
|
||||||
List<Pair<String, String>> changedNames = new LinkedList<>(); //logging only
|
List<Pair<String, String>> changedNames = new LinkedList<>(); //logging only
|
||||||
while (rs.next()) {
|
|
||||||
con.setAutoCommit(false);
|
con.setAutoCommit(false);
|
||||||
int nameChangeId = rs.getInt("id");
|
try {
|
||||||
int characterId = rs.getInt("characterId");
|
while (rs.next()) {
|
||||||
String oldName = rs.getString("old");
|
int nameChangeId = rs.getInt("id");
|
||||||
String newName = rs.getString("new");
|
int characterId = rs.getInt("characterId");
|
||||||
boolean success = MapleCharacter.doNameChange(con, characterId, oldName, newName, nameChangeId);
|
String oldName = rs.getString("old");
|
||||||
if (!success) {
|
String newName = rs.getString("new");
|
||||||
con.rollback(); //discard changes
|
boolean success = MapleCharacter.doNameChange(con, characterId, oldName, newName, nameChangeId);
|
||||||
} else {
|
if (!success) {
|
||||||
changedNames.add(new Pair<>(oldName, newName));
|
con.rollback(); //discard changes
|
||||||
|
} else {
|
||||||
|
con.commit();
|
||||||
|
changedNames.add(new Pair<>(oldName, newName));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
con.setAutoCommit(true);
|
con.setAutoCommit(true);
|
||||||
}
|
}
|
||||||
//log
|
//log
|
||||||
for (Pair<String, String> namePair : changedNames) {
|
for (Pair<String, String> namePair : changedNames) {
|
||||||
FilePrinter.print(FilePrinter.CHANGE_CHARACTER_NAME, "Name change applied : from \"" + namePair.getLeft() + "\" to \"" + namePair.getRight() + "\" at " + Calendar.getInstance().getTime().toString());
|
log.info("Name change applied - from: \"{}\" to \"{}\" at {}", namePair.getLeft(), namePair.getRight(), Instant.now());
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
log.warn("Failed to retrieve list of pending name changes", e);
|
||||||
FilePrinter.printError(FilePrinter.CHANGE_CHARACTER_NAME, e, "Failed to retrieve list of pending name changes.");
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void applyAllWorldTransfers() {
|
private static void applyAllWorldTransfers(Connection con) throws SQLException {
|
||||||
try (Connection con = DatabaseConnection.getConnection();
|
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL",
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL",
|
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
|
||||||
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
|
|
||||||
ResultSet rs = ps.executeQuery()) {
|
ResultSet rs = ps.executeQuery()) {
|
||||||
List<Integer> removedTransfers = new LinkedList<>();
|
List<Integer> removedTransfers = new LinkedList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
@@ -1625,33 +1641,39 @@ public class Server {
|
|||||||
}
|
}
|
||||||
rs.beforeFirst();
|
rs.beforeFirst();
|
||||||
List<Pair<Integer, Pair<Integer, Integer>>> worldTransfers = new LinkedList<>(); //logging only <charid, <oldWorld, newWorld>>
|
List<Pair<Integer, Pair<Integer, Integer>>> worldTransfers = new LinkedList<>(); //logging only <charid, <oldWorld, newWorld>>
|
||||||
while (rs.next()) {
|
|
||||||
con.setAutoCommit(false);
|
con.setAutoCommit(false);
|
||||||
int nameChangeId = rs.getInt("id");
|
try {
|
||||||
if (removedTransfers.contains(nameChangeId)) {
|
while (rs.next()) {
|
||||||
continue;
|
int nameChangeId = rs.getInt("id");
|
||||||
}
|
if (removedTransfers.contains(nameChangeId)) {
|
||||||
int characterId = rs.getInt("characterId");
|
continue;
|
||||||
int oldWorld = rs.getInt("from");
|
}
|
||||||
int newWorld = rs.getInt("to");
|
int characterId = rs.getInt("characterId");
|
||||||
boolean success = MapleCharacter.doWorldTransfer(con, characterId, oldWorld, newWorld, nameChangeId);
|
int oldWorld = rs.getInt("from");
|
||||||
if (!success) {
|
int newWorld = rs.getInt("to");
|
||||||
con.rollback();
|
boolean success = MapleCharacter.doWorldTransfer(con, characterId, oldWorld, newWorld, nameChangeId);
|
||||||
} else {
|
if (!success) {
|
||||||
worldTransfers.add(new Pair<>(characterId, new Pair<>(oldWorld, newWorld)));
|
con.rollback();
|
||||||
|
} else {
|
||||||
|
con.commit();
|
||||||
|
worldTransfers.add(new Pair<>(characterId, new Pair<>(oldWorld, newWorld)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
con.setAutoCommit(true);
|
con.setAutoCommit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//log
|
//log
|
||||||
for (Pair<Integer, Pair<Integer, Integer>> worldTransferPair : worldTransfers) {
|
for (Pair<Integer, Pair<Integer, Integer>> worldTransferPair : worldTransfers) {
|
||||||
int charId = worldTransferPair.getLeft();
|
int charId = worldTransferPair.getLeft();
|
||||||
int oldWorld = worldTransferPair.getRight().getLeft();
|
int oldWorld = worldTransferPair.getRight().getLeft();
|
||||||
int newWorld = worldTransferPair.getRight().getRight();
|
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());
|
log.info("World transfer applied - character id {} from world {} to world {} at {}", charId, oldWorld, newWorld, Instant.now());
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
log.warn("Failed to retrieve list of pending world transfers", e);
|
||||||
FilePrinter.printError(FilePrinter.WORLD_TRANSFER, e, "Failed to retrieve list of pending world transfers.");
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,12 @@
|
|||||||
*/
|
*/
|
||||||
package net.server.task;
|
package net.server.task;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import net.server.Server;
|
import net.server.Server;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import tools.DatabaseConnection;
|
||||||
import tools.FilePrinter;
|
import tools.FilePrinter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,13 +32,17 @@ import tools.FilePrinter;
|
|||||||
* @info Thread responsible for maintaining coupons EXP & DROP effects active
|
* @info Thread responsible for maintaining coupons EXP & DROP effects active
|
||||||
*/
|
*/
|
||||||
public class CouponTask implements Runnable {
|
public class CouponTask implements Runnable {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CouponTask.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
Server.getInstance().updateActiveCoupons();
|
try (Connection con = DatabaseConnection.getConnection()) {
|
||||||
|
Server.getInstance().updateActiveCoupons(con);
|
||||||
|
}
|
||||||
Server.getInstance().commitActiveCoupons();
|
Server.getInstance().commitActiveCoupons();
|
||||||
} catch(SQLException sqle) {
|
} catch (SQLException sqle) {
|
||||||
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Unexpected SQL error: " + sqle.getMessage());
|
log.error("Error updating coupon effects", sqle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -570,7 +570,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
|
|
||||||
public Object[] getAvailableSkillBooks() {
|
public Object[] getAvailableSkillBooks() {
|
||||||
List<Integer> ret = MapleItemInformationProvider.getInstance().usableSkillBooks(this.getPlayer());
|
List<Integer> ret = MapleItemInformationProvider.getInstance().usableSkillBooks(this.getPlayer());
|
||||||
ret.addAll(MapleSkillbookInformationProvider.getInstance().getTeachableSkills(this.getPlayer()));
|
ret.addAll(MapleSkillbookInformationProvider.getTeachableSkills(this.getPlayer()));
|
||||||
|
|
||||||
return ret.toArray();
|
return ret.toArray();
|
||||||
}
|
}
|
||||||
@@ -580,7 +580,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getSkillBookInfo(int itemid) {
|
public String getSkillBookInfo(int itemid) {
|
||||||
SkillBookEntry sbe = MapleSkillbookInformationProvider.getInstance().getSkillbookAvailability(itemid);
|
SkillBookEntry sbe = MapleSkillbookInformationProvider.getSkillbookAvailability(itemid);
|
||||||
switch (sbe) {
|
switch (sbe) {
|
||||||
case UNAVAILABLE:
|
case UNAVAILABLE:
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import java.sql.PreparedStatement;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -144,15 +143,16 @@ public class CashShop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class CashItemFactory {
|
public static class CashItemFactory {
|
||||||
|
private static volatile Map<Integer, CashItem> items = new HashMap<>();
|
||||||
|
private static volatile List<Integer> randomitemsns = new ArrayList<>();
|
||||||
|
private static volatile Map<Integer, List<Integer>> packages = new HashMap<>();
|
||||||
|
private static volatile List<SpecialCashItem> specialcashitems = new ArrayList<>();
|
||||||
|
|
||||||
private static final Map<Integer, CashItem> items = new HashMap<>();
|
public static void loadAllCashItems() {
|
||||||
private static final Map<Integer, List<Integer>> packages = new HashMap<>();
|
|
||||||
private static final List<SpecialCashItem> specialcashitems = new ArrayList<>();
|
|
||||||
private static final List<Integer> randomitemsns = new ArrayList<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
|
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
|
||||||
|
|
||||||
|
Map<Integer, CashItem> loadedItems = new HashMap<>();
|
||||||
|
List<Integer> onSaleItems = new ArrayList<>();
|
||||||
for (MapleData item : etc.getData("Commodity.img").getChildren()) {
|
for (MapleData item : etc.getData("Commodity.img").getChildren()) {
|
||||||
int sn = MapleDataTool.getIntConvert("SN", item);
|
int sn = MapleDataTool.getIntConvert("SN", item);
|
||||||
int itemId = MapleDataTool.getIntConvert("ItemId", item);
|
int itemId = MapleDataTool.getIntConvert("ItemId", item);
|
||||||
@@ -160,9 +160,16 @@ public class CashShop {
|
|||||||
long period = MapleDataTool.getIntConvert("Period", item, 1);
|
long period = MapleDataTool.getIntConvert("Period", item, 1);
|
||||||
short count = (short) MapleDataTool.getIntConvert("Count", item, 1);
|
short count = (short) MapleDataTool.getIntConvert("Count", item, 1);
|
||||||
boolean onSale = MapleDataTool.getIntConvert("OnSale", item, 0) == 1;
|
boolean onSale = MapleDataTool.getIntConvert("OnSale", item, 0) == 1;
|
||||||
items.put(sn, new CashItem(sn, itemId, price, period, count, onSale));
|
loadedItems.put(sn, new CashItem(sn, itemId, price, period, count, onSale));
|
||||||
}
|
|
||||||
|
|
||||||
|
if (onSale) {
|
||||||
|
onSaleItems.add(sn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CashItemFactory.items = loadedItems;
|
||||||
|
CashItemFactory.randomitemsns = onSaleItems;
|
||||||
|
|
||||||
|
Map<Integer, List<Integer>> loadedPackages = new HashMap<>();
|
||||||
for (MapleData cashPackage : etc.getData("CashPackage.img").getChildren()) {
|
for (MapleData cashPackage : etc.getData("CashPackage.img").getChildren()) {
|
||||||
List<Integer> cPackage = new ArrayList<>();
|
List<Integer> cPackage = new ArrayList<>();
|
||||||
|
|
||||||
@@ -170,24 +177,21 @@ public class CashShop {
|
|||||||
cPackage.add(Integer.parseInt(item.getData().toString()));
|
cPackage.add(Integer.parseInt(item.getData().toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
packages.put(Integer.parseInt(cashPackage.getName()), cPackage);
|
loadedPackages.put(Integer.parseInt(cashPackage.getName()), cPackage);
|
||||||
}
|
|
||||||
|
|
||||||
for (Entry<Integer, CashItem> e : items.entrySet()) {
|
|
||||||
if (e.getValue().isOnSale()) {
|
|
||||||
randomitemsns.add(e.getKey());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
CashItemFactory.packages = loadedPackages;
|
||||||
|
|
||||||
|
List<SpecialCashItem> loadedSpecialItems = new ArrayList<>();
|
||||||
try (Connection con = DatabaseConnection.getConnection();
|
try (Connection con = DatabaseConnection.getConnection();
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM specialcashitems");
|
PreparedStatement ps = con.prepareStatement("SELECT * FROM specialcashitems");
|
||||||
ResultSet rs = ps.executeQuery()) {
|
ResultSet rs = ps.executeQuery()) {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
specialcashitems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
|
loadedSpecialItems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
CashItemFactory.specialcashitems = loadedSpecialItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CashItem getRandomCashItem() {
|
public static CashItem getRandomCashItem() {
|
||||||
@@ -222,16 +226,17 @@ public class CashShop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void reloadSpecialCashItems() {//Yay?
|
public static void reloadSpecialCashItems() {//Yay?
|
||||||
specialcashitems.clear();
|
List<SpecialCashItem> loadedSpecialItems = new ArrayList<>();
|
||||||
try (Connection con = DatabaseConnection.getConnection();
|
try (Connection con = DatabaseConnection.getConnection();
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM specialcashitems");
|
PreparedStatement ps = con.prepareStatement("SELECT * FROM specialcashitems");
|
||||||
ResultSet rs = ps.executeQuery()) {
|
ResultSet rs = ps.executeQuery()) {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
specialcashitems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
|
loadedSpecialItems.add(new SpecialCashItem(rs.getInt("sn"), rs.getInt("modifier"), rs.getByte("info")));
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
CashItemFactory.specialcashitems = loadedSpecialItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,15 +40,12 @@ import java.util.regex.Pattern;
|
|||||||
*
|
*
|
||||||
* @author RonanLana
|
* @author RonanLana
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only used in 1 script that gives players information about where skillbooks can be found
|
||||||
|
*/
|
||||||
public class MapleSkillbookInformationProvider {
|
public class MapleSkillbookInformationProvider {
|
||||||
|
private static volatile Map<Integer, SkillBookEntry> foundSkillbooks = new HashMap<>();
|
||||||
private final static MapleSkillbookInformationProvider instance = new MapleSkillbookInformationProvider();
|
|
||||||
|
|
||||||
public static MapleSkillbookInformationProvider getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static Map<Integer, SkillBookEntry> foundSkillbooks = new HashMap<>();
|
|
||||||
|
|
||||||
public enum SkillBookEntry {
|
public enum SkillBookEntry {
|
||||||
UNAVAILABLE,
|
UNAVAILABLE,
|
||||||
@@ -59,13 +56,15 @@ public class MapleSkillbookInformationProvider {
|
|||||||
SCRIPT
|
SCRIPT
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String rootDirectory = ".";
|
private static final int SKILLBOOK_MIN_ITEMID = 2280000;
|
||||||
|
private static final int SKILLBOOK_MAX_ITEMID = 2300000; // exclusively
|
||||||
private static int skillbookMinItemid = 2280000;
|
|
||||||
private static int skillbookMaxItemid = 2300000; // exclusively
|
public static void loadAllSkillbookInformation() {
|
||||||
|
Map<Integer, SkillBookEntry> loadedSkillbooks = new HashMap<>();
|
||||||
static {
|
loadedSkillbooks.putAll(fetchSkillbooksFromQuests());
|
||||||
loadSkillbooks();
|
loadedSkillbooks.putAll(fetchSkillbooksFromReactors());
|
||||||
|
loadedSkillbooks.putAll(fetchSkillbooksFromScripts());
|
||||||
|
MapleSkillbookInformationProvider.foundSkillbooks = loadedSkillbooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean is4thJobSkill(int itemid) {
|
private static boolean is4thJobSkill(int itemid) {
|
||||||
@@ -73,7 +72,7 @@ public class MapleSkillbookInformationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isSkillBook(int itemid) {
|
private static boolean isSkillBook(int itemid) {
|
||||||
return itemid >= skillbookMinItemid && itemid < skillbookMaxItemid;
|
return itemid >= SKILLBOOK_MIN_ITEMID && itemid < SKILLBOOK_MAX_ITEMID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isQuestBook(int itemid) {
|
private static boolean isQuestBook(int itemid) {
|
||||||
@@ -86,9 +85,9 @@ public class MapleSkillbookInformationProvider {
|
|||||||
MapleData startReqItemData = questStartData.getChildByPath("item");
|
MapleData startReqItemData = questStartData.getChildByPath("item");
|
||||||
if (startReqItemData != null) {
|
if (startReqItemData != null) {
|
||||||
for (MapleData itemData : startReqItemData.getChildren()) {
|
for (MapleData itemData : startReqItemData.getChildren()) {
|
||||||
int itemid = MapleDataTool.getInt("id", itemData, 0);
|
int itemId = MapleDataTool.getInt("id", itemData, 0);
|
||||||
if (isQuestBook(itemid)) {
|
if (isQuestBook(itemId)) {
|
||||||
return itemid;
|
return itemId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,40 +114,41 @@ public class MapleSkillbookInformationProvider {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fetchSkillbooksFromQuests() {
|
private static Map<Integer, SkillBookEntry> fetchSkillbooksFromQuests() {
|
||||||
MapleDataProvider questDataProvider = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "Quest.wz"));
|
MapleDataProvider questDataProvider = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "Quest.wz"));
|
||||||
MapleData actData = questDataProvider.getData("Act.img");
|
MapleData actData = questDataProvider.getData("Act.img");
|
||||||
MapleData checkData = questDataProvider.getData("Check.img");
|
MapleData checkData = questDataProvider.getData("Check.img");
|
||||||
|
|
||||||
|
final Map<Integer, SkillBookEntry> loadedSkillbooks = new HashMap<>();
|
||||||
for (MapleData questData : actData.getChildren()) {
|
for (MapleData questData : actData.getChildren()) {
|
||||||
for (MapleData questStatusData : questData.getChildren()) {
|
for (MapleData questStatusData : questData.getChildren()) {
|
||||||
for (MapleData questNodeData : questStatusData.getChildren()) {
|
for (MapleData questNodeData : questStatusData.getChildren()) {
|
||||||
String actNodeName = questNodeData.getName();
|
String actNodeName = questNodeData.getName();
|
||||||
if (actNodeName.contentEquals("item")) {
|
if (actNodeName.contentEquals("item")) {
|
||||||
for (MapleData questItemData : questNodeData.getChildren()) {
|
for (MapleData questItemData : questNodeData.getChildren()) {
|
||||||
int itemid = MapleDataTool.getInt("id", questItemData, 0);
|
int itemId = MapleDataTool.getInt("id", questItemData, 0);
|
||||||
int itemcount = MapleDataTool.getInt("count", questItemData, 0);
|
int itemCount = MapleDataTool.getInt("count", questItemData, 0);
|
||||||
|
|
||||||
if (isSkillBook(itemid) && itemcount > 0) {
|
if (isSkillBook(itemId) && itemCount > 0) {
|
||||||
int questbook = fetchQuestbook(checkData, questData.getName());
|
int questbook = fetchQuestbook(checkData, questData.getName());
|
||||||
if (questbook < 0) {
|
if (questbook < 0) {
|
||||||
foundSkillbooks.put(itemid, SkillBookEntry.QUEST);
|
loadedSkillbooks.put(itemId, SkillBookEntry.QUEST);
|
||||||
} else {
|
} else {
|
||||||
foundSkillbooks.put(itemid, SkillBookEntry.QUEST_BOOK);
|
loadedSkillbooks.put(itemId, SkillBookEntry.QUEST_BOOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (actNodeName.contentEquals("skill")) {
|
} else if (actNodeName.contentEquals("skill")) {
|
||||||
for (MapleData questSkillData : questNodeData.getChildren()) {
|
for (MapleData questSkillData : questNodeData.getChildren()) {
|
||||||
int skillid = MapleDataTool.getInt("id", questSkillData, 0);
|
int skillId = MapleDataTool.getInt("id", questSkillData, 0);
|
||||||
if (is4thJobSkill(skillid)) {
|
if (is4thJobSkill(skillId)) {
|
||||||
// negative itemids are skill rewards
|
// negative itemids are skill rewards
|
||||||
|
|
||||||
int questbook = fetchQuestbook(checkData, questData.getName());
|
int questbook = fetchQuestbook(checkData, questData.getName());
|
||||||
if (questbook < 0) {
|
if (questbook < 0) {
|
||||||
foundSkillbooks.put(-skillid, SkillBookEntry.QUEST_REWARD);
|
loadedSkillbooks.put(-skillId, SkillBookEntry.QUEST_REWARD);
|
||||||
} else {
|
} else {
|
||||||
foundSkillbooks.put(-skillid, SkillBookEntry.QUEST_BOOK);
|
loadedSkillbooks.put(-skillId, SkillBookEntry.QUEST_BOOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,24 +156,30 @@ public class MapleSkillbookInformationProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return loadedSkillbooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fetchSkillbooksFromReactors() {
|
private static Map<Integer, SkillBookEntry> fetchSkillbooksFromReactors() {
|
||||||
|
Map<Integer, SkillBookEntry> loadedSkillbooks = new HashMap<>();
|
||||||
|
|
||||||
try (Connection con = DatabaseConnection.getConnection();
|
try (Connection con = DatabaseConnection.getConnection();
|
||||||
PreparedStatement ps = con.prepareStatement("SELECT itemid FROM reactordrops WHERE itemid >= ? AND itemid < ?;")) {
|
PreparedStatement ps = con.prepareStatement("SELECT itemid FROM reactordrops WHERE itemid >= ? AND itemid < ?;")) {
|
||||||
ps.setInt(1, skillbookMinItemid);
|
ps.setInt(1, SKILLBOOK_MIN_ITEMID);
|
||||||
ps.setInt(2, skillbookMaxItemid);
|
ps.setInt(2, SKILLBOOK_MAX_ITEMID);
|
||||||
|
|
||||||
try (ResultSet rs = ps.executeQuery()) {
|
try (ResultSet rs = ps.executeQuery()) {
|
||||||
if (rs.isBeforeFirst()) {
|
if (rs.isBeforeFirst()) {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
foundSkillbooks.put(rs.getInt("itemid"), SkillBookEntry.REACTOR);
|
loadedSkillbooks.put(rs.getInt("itemid"), SkillBookEntry.REACTOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException sqle) {
|
} catch (SQLException sqle) {
|
||||||
sqle.printStackTrace();
|
sqle.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return loadedSkillbooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||||
@@ -197,28 +203,20 @@ public class MapleSkillbookInformationProvider {
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void filterScriptDirectorySearchMatchingData(String path) {
|
private static Set<Integer> findMatchingSkillbookIdsOnFile(String fileContent) {
|
||||||
for (File file : listFilesFromDirectoryRecursively(rootDirectory + "/" + path)) {
|
Set<Integer> skillbookIds = new HashSet<>(4);
|
||||||
if (file.getName().endsWith(".js")) {
|
|
||||||
fileSearchMatchingData(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Set<Integer> foundMatchingDataOnFile(String fileContent) {
|
|
||||||
Set<Integer> matches = new HashSet<>(4);
|
|
||||||
|
|
||||||
Matcher searchM = Pattern.compile("22(8|9)[0-9]{4}").matcher(fileContent);
|
Matcher searchM = Pattern.compile("22(8|9)[0-9]{4}").matcher(fileContent);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while (searchM.find(idx)) {
|
while (searchM.find(idx)) {
|
||||||
idx = searchM.end();
|
idx = searchM.end();
|
||||||
matches.add(Integer.valueOf(fileContent.substring(searchM.start(), idx)));
|
skillbookIds.add(Integer.valueOf(fileContent.substring(searchM.start(), idx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return matches;
|
return skillbookIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String readFileToString(File file, String encoding) throws IOException {
|
private static String readFileToString(File file, String encoding) throws IOException {
|
||||||
Scanner scanner = new Scanner(file, encoding);
|
Scanner scanner = new Scanner(file, encoding);
|
||||||
String text = "";
|
String text = "";
|
||||||
try {
|
try {
|
||||||
@@ -232,36 +230,42 @@ public class MapleSkillbookInformationProvider {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fileSearchMatchingData(File file) {
|
private static Map<Integer, SkillBookEntry> fileSearchMatchingData(File file) {
|
||||||
|
Map<Integer, SkillBookEntry> scriptFileSkillbooks = new HashMap<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String fileContent = readFileToString(file, "UTF-8");
|
String fileContent = readFileToString(file, "UTF-8");
|
||||||
|
|
||||||
Set<Integer> books = foundMatchingDataOnFile(fileContent);
|
Set<Integer> skillbookIds = findMatchingSkillbookIdsOnFile(fileContent);
|
||||||
for (Integer i : books) {
|
for (Integer skillbookId : skillbookIds) {
|
||||||
foundSkillbooks.put(i, SkillBookEntry.SCRIPT);
|
scriptFileSkillbooks.put(skillbookId, SkillBookEntry.SCRIPT);
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
System.out.println("Failed to read " + file.getName() + ".");
|
System.out.println("Failed to read " + file.getName() + ".");
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return scriptFileSkillbooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fetchSkillbooksFromScripts() {
|
private static Map<Integer, SkillBookEntry> fetchSkillbooksFromScripts() {
|
||||||
filterScriptDirectorySearchMatchingData("scripts");
|
Map<Integer, SkillBookEntry> scriptSkillbooks = new HashMap<>();
|
||||||
|
|
||||||
|
for (File file : listFilesFromDirectoryRecursively("./scripts")) {
|
||||||
|
if (file.getName().endsWith(".js")) {
|
||||||
|
scriptSkillbooks.putAll(fileSearchMatchingData(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scriptSkillbooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadSkillbooks() {
|
public static SkillBookEntry getSkillbookAvailability(int itemId) {
|
||||||
fetchSkillbooksFromQuests();
|
SkillBookEntry sbe = foundSkillbooks.get(itemId);
|
||||||
fetchSkillbooksFromReactors();
|
|
||||||
fetchSkillbooksFromScripts();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SkillBookEntry getSkillbookAvailability(int itemid) {
|
|
||||||
SkillBookEntry sbe = foundSkillbooks.get(itemid);
|
|
||||||
return sbe != null ? sbe : SkillBookEntry.UNAVAILABLE;
|
return sbe != null ? sbe : SkillBookEntry.UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Integer> getTeachableSkills(MapleCharacter chr) {
|
public static List<Integer> getTeachableSkills(MapleCharacter chr) {
|
||||||
List<Integer> list = new ArrayList<>();
|
List<Integer> list = new ArrayList<>();
|
||||||
|
|
||||||
for (Integer book : foundSkillbooks.keySet()) {
|
for (Integer book : foundSkillbooks.keySet()) {
|
||||||
|
|||||||
@@ -19,17 +19,18 @@
|
|||||||
*/
|
*/
|
||||||
package server.life;
|
package server.life;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import net.server.Server;
|
import net.server.Server;
|
||||||
import provider.MapleData;
|
import provider.MapleData;
|
||||||
import provider.MapleDataProvider;
|
import provider.MapleDataProvider;
|
||||||
import provider.MapleDataProviderFactory;
|
import provider.MapleDataProviderFactory;
|
||||||
import provider.MapleDataTool;
|
import provider.MapleDataTool;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author RonanLana
|
* @author RonanLana
|
||||||
@@ -41,11 +42,11 @@ public class MaplePlayerNPCFactory {
|
|||||||
private static final Map<Integer, List<MaplePlayerNPC>> dnpcMaps = new HashMap<>();
|
private static final Map<Integer, List<MaplePlayerNPC>> dnpcMaps = new HashMap<>();
|
||||||
private static Integer runningDeveloperOid = 2147483000; // 647 slots, long enough
|
private static Integer runningDeveloperOid = 2147483000; // 647 slots, long enough
|
||||||
|
|
||||||
public static boolean isExistentScriptid(int scriptid) {
|
public synchronized static boolean isExistentScriptid(int scriptid) {
|
||||||
return npcData.getData(scriptid + ".img") != null;
|
return npcData.getData(scriptid + ".img") != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadDeveloperRoomMetadata(MapleDataProvider npc) {
|
private static void loadDeveloperRoomMetadata(MapleDataProvider npc) {
|
||||||
MapleData thisData = npc.getData("9977777.img");
|
MapleData thisData = npc.getData("9977777.img");
|
||||||
if(thisData != null) {
|
if(thisData != null) {
|
||||||
MapleDataProvider map = MapleDataProviderFactory.getDataProvider(new File("wz/Map.wz"));
|
MapleDataProvider map = MapleDataProviderFactory.getDataProvider(new File("wz/Map.wz"));
|
||||||
@@ -65,7 +66,7 @@ public class MaplePlayerNPCFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadFactoryMetadata() {
|
public synchronized static void loadFactoryMetadata() {
|
||||||
MapleDataProvider npc = npcData;
|
MapleDataProvider npc = npcData;
|
||||||
loadDeveloperRoomMetadata(npc);
|
loadDeveloperRoomMetadata(npc);
|
||||||
|
|
||||||
@@ -134,7 +135,7 @@ public class MaplePlayerNPCFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<MaplePlayerNPC> getDeveloperNpcsFromMapid(int mapid) {
|
public synchronized static List<MaplePlayerNPC> getDeveloperNpcsFromMapid(int mapid) {
|
||||||
return dnpcMaps.get(mapid);
|
return dnpcMaps.get(mapid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,20 +21,10 @@
|
|||||||
*/
|
*/
|
||||||
package server.quest;
|
package server.quest;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import client.MapleCharacter;
|
import client.MapleCharacter;
|
||||||
import client.MapleQuestStatus;
|
import client.MapleQuestStatus;
|
||||||
import client.MapleQuestStatus.Status;
|
import client.MapleQuestStatus.Status;
|
||||||
import config.YamlConfig;
|
import config.YamlConfig;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
|
||||||
import provider.MapleData;
|
import provider.MapleData;
|
||||||
import provider.MapleDataProvider;
|
import provider.MapleDataProvider;
|
||||||
import provider.MapleDataProviderFactory;
|
import provider.MapleDataProviderFactory;
|
||||||
@@ -44,6 +34,10 @@ import server.quest.requirements.*;
|
|||||||
import tools.MaplePacketCreator;
|
import tools.MaplePacketCreator;
|
||||||
import tools.StringUtil;
|
import tools.StringUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Matze
|
* @author Matze
|
||||||
@@ -51,8 +45,8 @@ import tools.StringUtil;
|
|||||||
*/
|
*/
|
||||||
public class MapleQuest {
|
public class MapleQuest {
|
||||||
|
|
||||||
private static Map<Integer, MapleQuest> quests = new HashMap<>();
|
private static volatile Map<Integer, MapleQuest> quests = new HashMap<>();
|
||||||
private static Map<Integer, Integer> infoNumberQuests = new HashMap<>();
|
private static volatile Map<Integer, Integer> infoNumberQuests = new HashMap<>();
|
||||||
private static Map<Short, Integer> medals = new HashMap<>();
|
private static Map<Short, Integer> medals = new HashMap<>();
|
||||||
|
|
||||||
private static final Set<Short> exploitableQuests = new HashSet<>();
|
private static final Set<Short> exploitableQuests = new HashSet<>();
|
||||||
@@ -459,9 +453,7 @@ public class MapleQuest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void clearCache(int quest) {
|
public static void clearCache(int quest) {
|
||||||
if(quests.containsKey(quest)){
|
quests.remove(quest);
|
||||||
quests.remove(quest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearCache() {
|
public static void clearCache() {
|
||||||
@@ -656,29 +648,31 @@ public class MapleQuest {
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadAllQuest() {
|
public static void loadAllQuests() {
|
||||||
try {
|
final Map<Integer, MapleQuest> loadedQuests = new HashMap<>();
|
||||||
for(MapleData quest : questInfo.getChildren()) {
|
final Map<Integer, Integer> loadedInfoNumberQuests = new HashMap<>();
|
||||||
int questID = Integer.parseInt(quest.getName());
|
|
||||||
|
for (MapleData quest : questInfo.getChildren()) {
|
||||||
MapleQuest q = new MapleQuest(questID);
|
int questID = Integer.parseInt(quest.getName());
|
||||||
quests.put(questID, q);
|
|
||||||
|
MapleQuest q = new MapleQuest(questID);
|
||||||
int infoNumber;
|
loadedQuests.put(questID, q);
|
||||||
|
|
||||||
infoNumber = q.getInfoNumber(Status.STARTED);
|
int infoNumber;
|
||||||
if (infoNumber > 0) {
|
|
||||||
infoNumberQuests.put(infoNumber, questID);
|
infoNumber = q.getInfoNumber(Status.STARTED);
|
||||||
}
|
if (infoNumber > 0) {
|
||||||
|
loadedInfoNumberQuests.put(infoNumber, questID);
|
||||||
infoNumber = q.getInfoNumber(Status.COMPLETED);
|
}
|
||||||
if (infoNumber > 0) {
|
|
||||||
infoNumberQuests.put(infoNumber, questID);
|
infoNumber = q.getInfoNumber(Status.COMPLETED);
|
||||||
}
|
if (infoNumber > 0) {
|
||||||
}
|
loadedInfoNumberQuests.put(infoNumber, questID);
|
||||||
} catch (Exception ex) {
|
}
|
||||||
ex.printStackTrace();
|
}
|
||||||
}
|
|
||||||
}
|
MapleQuest.quests = loadedQuests;
|
||||||
|
MapleQuest.infoNumberQuests = loadedInfoNumberQuests;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user