multiTargetedSkills = new ArrayList<>();
diff --git a/src/main/java/server/quest/MapleQuest.java b/src/main/java/server/quest/MapleQuest.java
index bff4ba65a2..5495a51726 100644
--- a/src/main/java/server/quest/MapleQuest.java
+++ b/src/main/java/server/quest/MapleQuest.java
@@ -29,12 +29,12 @@ import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
+import provider.wz.WZFiles;
import server.quest.actions.*;
import server.quest.requirements.*;
import tools.MaplePacketCreator;
import tools.StringUtil;
-import java.io.File;
import java.util.*;
import java.util.Map.Entry;
@@ -68,7 +68,7 @@ public class MapleQuest {
private boolean autoPreComplete, autoComplete;
private boolean repeatable = false;
private String name = "", parent = "";
- private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz"));
+ private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(WZFiles.QUEST);
private final static MapleData questInfo = questData.getData("QuestInfo.img");
private final static MapleData questAct = questData.getData("Act.img");
private final static MapleData questReq = questData.getData("Check.img");
diff --git a/src/main/java/tools/DatabaseConnection.java b/src/main/java/tools/DatabaseConnection.java
index ba74ee0f18..0246152ea3 100644
--- a/src/main/java/tools/DatabaseConnection.java
+++ b/src/main/java/tools/DatabaseConnection.java
@@ -63,6 +63,10 @@ public class DatabaseConnection {
* @return true if connection to the database initiated successfully, false if not successful
*/
public static boolean initializeConnectionPool() {
+ if (dataSource != null) {
+ return true;
+ }
+
log.info("Initializing connection pool...");
final HikariConfig config = getConfig();
Instant initStart = Instant.now();
diff --git a/tools/MapleArrowFetcher/src/maplearrowfetcher/MapleArrowFetcher.java b/src/main/java/tools/mapletools/ArrowFetcher.java
similarity index 71%
rename from tools/MapleArrowFetcher/src/maplearrowfetcher/MapleArrowFetcher.java
rename to src/main/java/tools/mapletools/ArrowFetcher.java
index 308edb09b2..d492414a1a 100644
--- a/tools/MapleArrowFetcher/src/maplearrowfetcher/MapleArrowFetcher.java
+++ b/src/main/java/tools/mapletools/ArrowFetcher.java
@@ -17,205 +17,203 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
-package maplearrowfetcher;
+package tools.mapletools;
-import life.MapleLifeFactory;
-import life.MapleMonsterStats;
-import tools.DatabaseConnection;
+import server.life.MapleMonsterStats;
import tools.Pair;
import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
/**
- *
* @author RonanLana
- *
+ *
* This application traces arrow drop data on the underlying DB (that must be
* defined on the DatabaseConnection file of this project) and generates a SQL file
* that proposes updated arrow quantitty on drop entries for the drop_data table.
- *
+ *
* The arrow quantity range is calculated accordingly with the target mob stats, such
* as level and if it's a boss or not.
- *
*/
-public class MapleArrowFetcher {
-
+public class ArrowFetcher {
+ private static final String OUTPUT_FILE_NAME = "arrow_drop_data.sql";
+ private static final int MIN_ARROW_ID = 2060000;
+ private static final int MAX_ARROW_ID = 2061004;
+ private static final float CORRECTION_FACTOR = 2.2f;
+
+ private static final Map> mobRange = new HashMap<>();
private static PrintWriter printWriter;
- private static String newFile = "lib/arrow_drop_data.sql";
-
- private static int minArrowId = 2060000;
- private static int maxArrowId = 2061004;
-
- private static float correctionFactor = 2.2f;
-
private static Map mobStats;
- private static Map> mobRange = new HashMap<>();
-
+
private static Pair calcArrowRange(int level, boolean boss) {
int minRange, maxRange;
-
+
// MIN range
- minRange = (int)Math.ceil(((2.870503597 * level) - 1.870503597) * (boss ? 1.4 : 1.0) / correctionFactor);
-
+ minRange = (int) Math.ceil(((2.870503597 * level) - 1.870503597) * (boss ? 1.4 : 1.0) / CORRECTION_FACTOR);
+
// MAX range
- maxRange = (int)Math.ceil(1.25 * minRange);
-
+ maxRange = (int) Math.ceil(1.25 * minRange);
+
return new Pair<>(minRange, maxRange);
}
-
+
private static void calcAllMobsArrowRange() {
System.out.print("Calculating range... ");
-
- for(Entry mobStat : mobStats.entrySet()) {
+
+ for (Entry mobStat : mobStats.entrySet()) {
MapleMonsterStats mms = mobStat.getValue();
Pair arrowRange;
-
+
arrowRange = calcArrowRange(mms.getLevel(), mms.isBoss());
mobRange.put(mobStat.getKey(), arrowRange);
}
-
+
System.out.println("done!");
}
-
+
private static void printSqlHeader() {
printWriter.println(" # SQL File autogenerated from the MapleArrowFetcher feature by Ronan Lana.");
printWriter.println(" # Generated data takes into account mob stats such as level and boss for the raw arrow ranges.");
printWriter.println(" # Only current arrows entries on the DB it was compiled are being updated here.");
printWriter.println();
-
+
printWriter.println("UPDATE drop_data");
printWriter.println("SET minimum_quantity = CASE");
}
-
+
private static void printSqlMiddle() {
printWriter.println(" ELSE minimum_quantity END,");
printWriter.println(" maximum_quantity = CASE");
}
-
+
private static void printSqlFooter() {
printWriter.println(" ELSE maximum_quantity END");
printWriter.println(";");
}
-
+
private static void updateSqlMobArrowMinEntry(int[] entry) {
printWriter.println(" WHEN dropperid = " + entry[0] + " AND itemid = " + entry[1] + " THEN " + entry[2]);
}
-
+
private static void updateSqlMobArrowMaxEntry(int[] entry) {
printWriter.println(" WHEN dropperid = " + entry[0] + " AND itemid = " + entry[1] + " THEN " + entry[3]);
}
-
+
private static List getArrowEntryValues(Map> existingEntries) {
List entryValues = new ArrayList<>(200);
-
+
List>> listEntries = new ArrayList<>(existingEntries.entrySet());
-
- Collections.sort(listEntries, (o1, o2) -> {
- int val1 = o1.getKey();
- int val2 = o2.getKey();
- return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1));
+
+ listEntries.sort((o1, o2) -> {
+ int val1 = o1.getKey();
+ int val2 = o2.getKey();
+ return Integer.compare(val1, val2);
});
-
- for(Entry> ee : listEntries) {
+
+ for (Entry> ee : listEntries) {
int mobid = ee.getKey();
Pair mr = mobRange.get(mobid);
-
- for(Integer itemid : ee.getValue()) {
+
+ for (Integer itemid : ee.getValue()) {
int itemWeight = (itemid % 10) + 1;
-
+
int[] values = new int[4];
values[0] = mobid;
values[1] = itemid;
-
- values[2] = (int) Math.ceil(mr.getLeft() / itemWeight); // weighted min quantity
+
+ values[2] = (int) Math.ceil(mr.getLeft() / itemWeight); // weighted min quantity
values[3] = (int) Math.ceil(mr.getRight() / itemWeight); // weighted max quantity
-
+
entryValues.add(values);
}
}
-
+
return entryValues;
}
-
+
private static void updateMobsArrowRange() {
System.out.print("Generating updated ranges... ");
- Connection con = DatabaseConnection.getConnection();
+ final Connection con = SimpleDatabaseConnection.getConnection();
+
Map> existingEntries = new HashMap<>(200);
-
+
try {
// select all arrow drop entries on the DB, to update their values
- PreparedStatement ps = con.prepareStatement("SELECT dropperid, itemid FROM drop_data WHERE itemid >= " + minArrowId + " AND itemid <= " + maxArrowId + " ORDER BY itemid;");
+ PreparedStatement ps = con.prepareStatement("SELECT dropperid, itemid FROM drop_data WHERE itemid >= " + MIN_ARROW_ID + " AND itemid <= " + MAX_ARROW_ID + " ORDER BY itemid;");
ResultSet rs = ps.executeQuery();
-
+
if (rs.isBeforeFirst()) {
- while(rs.next()) {
+ while (rs.next()) {
int mobid = rs.getInt(1);
int itemid = rs.getInt(2);
-
- if(mobRange.containsKey(mobid)) {
+
+ if (mobRange.containsKey(mobid)) {
List em = existingEntries.get(mobid);
-
- if(em == null) {
+
+ if (em == null) {
em = new ArrayList<>(2);
existingEntries.put(mobid, em);
}
-
+
em.add(itemid);
}
}
-
- if(!existingEntries.isEmpty()) {
+
+ if (!existingEntries.isEmpty()) {
List entryValues = getArrowEntryValues(existingEntries);
-
- printWriter = new PrintWriter(newFile, "UTF-8");
+
+ printWriter = new PrintWriter(ToolConstants.getOutputFile(OUTPUT_FILE_NAME), StandardCharsets.UTF_8);
printSqlHeader();
-
- for(int[] arrowEntry : entryValues) {
+
+ for (int[] arrowEntry : entryValues) {
updateSqlMobArrowMinEntry(arrowEntry);
}
-
+
printSqlMiddle();
-
- for(int[] arrowEntry : entryValues) {
+
+ for (int[] arrowEntry : entryValues) {
updateSqlMobArrowMaxEntry(arrowEntry);
}
-
+
printSqlFooter();
-
+
printWriter.close();
} else {
throw new Exception("NO DATA");
}
-
+
} else {
throw new Exception("NO DATA");
}
-
+
rs.close();
ps.close();
con.close();
-
+
System.out.println("done!");
-
- } catch(Exception e) {
- if(e.getMessage() != null && e.getMessage().equals("NO DATA")) {
+
+ } catch (Exception e) {
+ if (e.getMessage() != null && e.getMessage().equals("NO DATA")) {
System.out.println("failed! The DB has no arrow entry to be updated.");
} else {
e.printStackTrace();
}
}
}
-
+
public static void main(String[] args) {
// load mob stats from WZ
- mobStats = MapleLifeFactory.getAllMonsterStats();
-
+ mobStats = MonsterStatFetcher.getAllMonsterStats();
+
calcAllMobsArrowRange();
updateMobsArrowRange();
}
diff --git a/src/main/java/tools/mapletools/BossHpBarFetcher.java b/src/main/java/tools/mapletools/BossHpBarFetcher.java
new file mode 100644
index 0000000000..a08d0cfdcb
--- /dev/null
+++ b/src/main/java/tools/mapletools/BossHpBarFetcher.java
@@ -0,0 +1,190 @@
+package tools.mapletools;
+
+import provider.wz.WZFiles;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author RonanLana
+ *
+ * This application parses the Mob.wz file inputted and generates a report showing
+ * all cases where a mob has a boss HP bar and doesn't have a "boss" label.
+ *
+ * Running it should generate a report file under "lib" folder with the search results.
+ */
+public class BossHpBarFetcher {
+ private static final String OUTPUT_FILE_NAME = "boss_hp_bar_report.txt";
+ private static final int INITIAL_STRING_LENGTH = 50;
+ private static final List missingBosses = new ArrayList<>();
+
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int curBoss;
+ private static int curHpTag;
+ private static int curMobId;
+
+ private static String getName(String token) {
+ int i, j;
+ char[] dest;
+ String d;
+
+ i = token.lastIndexOf("name");
+ i = token.indexOf("\"", i) + 1; //lower bound of the string
+ j = token.indexOf("\"", i); //upper bound
+
+ dest = new char[INITIAL_STRING_LENGTH];
+ token.getChars(i, j, dest, 0);
+
+ d = new String(dest);
+ return (d.trim());
+ }
+
+ private static String getValue(String token) {
+ int i, j;
+ char[] dest;
+ String d;
+
+ i = token.lastIndexOf("value");
+ i = token.indexOf("\"", i) + 1; //lower bound of the string
+ j = token.indexOf("\"", i); //upper bound
+
+ dest = new char[INITIAL_STRING_LENGTH];
+ token.getChars(i, j, dest, 0);
+
+ d = new String(dest);
+ return (d.trim());
+ }
+
+ private static void forwardCursor(int st) {
+ String line = null;
+
+ try {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
+ simpleToken(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void simpleToken(String token) {
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ status += 1;
+ }
+ }
+
+ private static void readMobLabel(String token) {
+ String name = getName(token);
+ String value = getValue(token);
+
+ switch (name) {
+ case "boss" -> curBoss = Integer.parseInt(value);
+ case "hpTagColor" -> curHpTag = Integer.parseInt(value);
+ }
+ }
+
+ private static void processMobData() {
+ if (curHpTag != Integer.MAX_VALUE && curBoss == Integer.MAX_VALUE) {
+ missingBosses.add(curMobId);
+ }
+ }
+
+ private static void translateToken(String token) {
+ String d;
+
+ if (token.contains("/imgdir")) {
+ status -= 1;
+
+ if (status == 1) {
+ processMobData();
+ }
+ } else if (token.contains("imgdir")) {
+ if (status == 0) {
+ String mobText = getName(token);
+ curMobId = Integer.parseInt(mobText.substring(0, mobText.lastIndexOf('.')));
+ } else if (status == 1) { //getting info
+ d = getName(token);
+
+ if (!d.contentEquals("info")) {
+ forwardCursor(status);
+ } else {
+ curBoss = Integer.MAX_VALUE;
+ curHpTag = Integer.MAX_VALUE;
+ }
+ } else if (status == 2) {
+ forwardCursor(status);
+ }
+
+ status += 1;
+ } else {
+ if (status == 2) { //info tags
+ readMobLabel(token);
+ }
+ }
+ }
+
+ private static void readBossHpBarData() throws IOException {
+ String line;
+
+ final File mobDirectory = WZFiles.MOB.getFile();
+ for (File file : mobDirectory.listFiles()) {
+ if (file.isFile()) {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(fileReader);
+
+ while ((line = bufferedReader.readLine()) != null) {
+ translateToken(line);
+ }
+
+ bufferedReader.close();
+ fileReader.close();
+ }
+ }
+ }
+
+ private static void printReportFileHeader(PrintWriter writer) {
+ writer.println(" # Report File autogenerated from the MapleBossHpBarFetcher feature by Ronan Lana.");
+ writer.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
+ writer.println();
+ }
+
+ private static void printReportFileResults(PrintWriter writer) {
+ for (int mobId : missingBosses) {
+ writer.println("Missing 'isBoss' on id: " + mobId);
+ }
+ }
+
+ private static void reportBossHpBarData() {
+ // This will reference one line at a time
+
+ try {
+ System.out.println("Reading WZs...");
+ readBossHpBarData();
+
+ System.out.println("Reporting results...");
+ final PrintWriter printWriter = new PrintWriter(ToolConstants.getOutputFile(OUTPUT_FILE_NAME), StandardCharsets.UTF_8);
+
+ printReportFileHeader(printWriter);
+ printReportFileResults(printWriter);
+
+ printWriter.close();
+ System.out.println("Done!");
+ } catch (FileNotFoundException ex) {
+ System.out.println("Unable to open mob file.");
+ } catch (IOException ex) {
+ System.out.println("Error reading mob file.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ reportBossHpBarData();
+ }
+
+}
diff --git a/tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/MapleCashCosmeticsChecker.java b/src/main/java/tools/mapletools/CashCosmeticsChecker.java
similarity index 74%
rename from tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/MapleCashCosmeticsChecker.java
rename to src/main/java/tools/mapletools/CashCosmeticsChecker.java
index bec5033721..696f3218b1 100644
--- a/tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/MapleCashCosmeticsChecker.java
+++ b/src/main/java/tools/mapletools/CashCosmeticsChecker.java
@@ -1,77 +1,49 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplecashcosmeticschecker;
+import provider.wz.WZFiles;
+import tools.Pair;
import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.util.*;
-import java.util.Map.Entry;
/**
- *
* @author RonanLana
-
- This application parses the cosmetic recipes defined within "lib/care" folder, loads
- every present cosmetic itemid from the XML data, then checks the scripts for missed
- cosmetics within the stylist/surgeon. Results from the search are reported in a report
- file.
-
- Note: to best make use of this feature, set ignoreCurrentScriptCosmetics = true. This
- way, every available cosmetic present on the recipes will be listed on the report.
-
- Estimated parse time: 1 minute
-
+ *
+ * This application parses the cosmetic recipes defined within "lib/care" folder, loads
+ * every present cosmetic itemid from the XML data, then checks the scripts for missed
+ * cosmetics within the stylist/surgeon. Results from the search are reported in a report
+ * file.
+ *
+ * Note: to best make use of this feature, set IGNORE_CURRENT_SCRIPT_COSMETICS = true. This
+ * way, every available cosmetic present on the recipes will be listed on the report.
+ *
+ * Estimated parse time: 1 minute
*/
-public class MapleCashCosmeticsChecker {
- static String libPath = "lib";
- static String handbookPath = "../../handbook";
- static String wzPath = "../../wz";
- static String scriptPath = "../../scripts";
-
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static boolean ignoreCurrentScriptCosmetics = false;
-
- static int initialStringLength = 50;
-
- static byte status = 0;
-
- static Map> scriptCosmetics = new HashMap<>();
- static Map scriptEntries = new HashMap<>(500);
-
- static Set allCosmetics = new HashSet<>();
-
- static Set unusedCosmetics = new HashSet<>();
- static Map> usedCosmetics = new HashMap<>();
-
- static Map couponNames = new HashMap<>();
- static Map cosmeticNpcs = new HashMap<>(); // expected only 1 NPC per cosmetic coupon (town care/salon)
- static Map, Integer> cosmeticNpcids = new HashMap<>();
-
- static Set missingCosmeticNames = new HashSet<>();
- static Map cosmeticNameIds = new HashMap<>();
- static Map cosmeticIdNames = new HashMap<>();
-
- static Map, Set> missingCosmeticsNpcTypes = new HashMap<>();
-
+public class CashCosmeticsChecker {
+ private static final String INPUT_DIRECTORY_PATH = ToolConstants.getInputFile("care").getPath();
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("cash_cosmetics_result.txt");
+ private static final boolean IGNORE_CURRENT_SCRIPT_COSMETICS = false; // Toggle to preference
+ private static final int INITIAL_STRING_LENGTH = 50;
+
+ private static final Map> scriptCosmetics = new HashMap<>();
+ private static final Map scriptEntries = new HashMap<>(500);
+ private static final Set allCosmetics = new HashSet<>();
+ private static final Set unusedCosmetics = new HashSet<>();
+ private static final Map> usedCosmetics = new HashMap<>();
+ private static final Map couponNames = new HashMap<>();
+ private static final Map cosmeticNpcs = new HashMap<>(); // expected only 1 NPC per cosmetic coupon (town care/salon)
+ private static final Map, Integer> cosmeticNpcids = new HashMap<>();
+ private static final Set missingCosmeticNames = new HashSet<>();
+ private static final Map cosmeticNameIds = new HashMap<>();
+ private static final Map cosmeticIdNames = new HashMap<>();
+ private static final Map, Set> missingCosmeticsNpcTypes = new HashMap<>();
+
+ private static PrintWriter printWriter = null;
+ private static InputStreamReader fileReader = null;
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+
private static String getName(String token) {
int i, j;
char[] dest;
@@ -81,13 +53,13 @@ public class MapleCashCosmeticsChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static String getValue(String token) {
int i, j;
char[] dest;
@@ -97,84 +69,81 @@ public class MapleCashCosmeticsChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
+
private static void translateToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
-
+
if (status == 3) {
String d = getName(token);
-
+
if (!(d.contentEquals("Face") || d.contentEquals("Hair"))) {
forwardCursor(status);
}
} else if (status == 4) {
String d = getName(token);
- int itemid = Integer.valueOf(d);
-
+ int itemid = Integer.parseInt(d);
+
int cosmeticid;
if (itemid >= 30000) {
cosmeticid = (itemid / 10) * 10;
} else {
cosmeticid = itemid - ((itemid / 100) % 10) * 100;
}
-
+
allCosmetics.add(cosmeticid);
forwardCursor(status);
}
}
}
-
+
private static void readEqpStringData(String eqpStringDirectory) throws IOException {
String line;
-
- fileReader = new InputStreamReader(new FileInputStream(eqpStringDirectory), "UTF-8");
+
+ fileReader = new InputStreamReader(new FileInputStream(eqpStringDirectory), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateToken(line);
}
bufferedReader.close();
fileReader.close();
}
-
+
private static void loadCosmeticWzData() throws IOException {
System.out.println("Reading String.wz ...");
- readEqpStringData(wzPath + "/String.wz/Eqp.img.xml");
+ readEqpStringData(WZFiles.STRING.getFilePath() + "/Eqp.img.xml");
}
-
+
private static void setCosmeticUsage(List usedByNpcids, int cosmeticid) {
if (!usedByNpcids.isEmpty()) {
usedCosmetics.put(cosmeticid, usedByNpcids);
@@ -182,7 +151,7 @@ public class MapleCashCosmeticsChecker {
unusedCosmetics.add(cosmeticid);
}
}
-
+
private static void listFiles(String directoryName, ArrayList files) {
File directory = new File(directoryName);
@@ -196,60 +165,60 @@ public class MapleCashCosmeticsChecker {
}
}
}
-
+
private static int getNpcIdFromFilename(String name) {
try {
- return Integer.valueOf(name.substring(0, name.indexOf('.')));
- } catch(Exception e) {
+ return Integer.parseInt(name.substring(0, name.indexOf('.')));
+ } catch (Exception e) {
return -1;
}
}
-
+
private static List findCosmeticDataNpcids(int itemid) {
List npcids = new LinkedList<>();
- for (Entry> sc : scriptCosmetics.entrySet()) {
+ for (Map.Entry> sc : scriptCosmetics.entrySet()) {
if (sc.getValue().contains(itemid)) {
npcids.add(itemid);
}
}
-
+
return npcids;
}
-
+
private static void loadScripts() throws IOException {
ArrayList files = new ArrayList<>();
- listFiles(scriptPath + "/npc", files);
+ listFiles(ToolConstants.SCRIPTS_PATH + "/npc", files);
- for(File f : files) {
+ for (File f : files) {
Integer npcid = getNpcIdFromFilename(f.getName());
-
+
//System.out.println("Parsing " + f.getAbsolutePath());
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line;
StringBuilder stringBuffer = new StringBuilder();
-
+
boolean cosmeticNpc = false;
Set cosmeticids = new HashSet<>();
- while((line = bufferedReader.readLine())!=null){
+ while ((line = bufferedReader.readLine()) != null) {
String[] s = line.split("hair_. = Array\\(", 2);
-
+
if (s.length > 1) {
cosmeticNpc = true;
s = s[1].split("\\)", 2);
s = s[0].split(", ");
-
+
for (String st : s) {
if (!st.isEmpty()) {
- int itemid = Integer.valueOf(st);
+ int itemid = Integer.parseInt(st);
cosmeticids.add(itemid);
}
}
} else {
s = line.split("face_. = Array\\(", 2);
-
+
if (s.length > 1) {
cosmeticNpc = true;
s = s[1].split("\\)", 2);
@@ -257,18 +226,18 @@ public class MapleCashCosmeticsChecker {
for (String st : s) {
if (!st.isEmpty()) {
- int itemid = Integer.valueOf(st);
+ int itemid = Integer.parseInt(st);
cosmeticids.add(itemid);
}
}
}
}
-
+
stringBuffer.append(line).append("\n");
}
-
+
scriptEntries.put(npcid, stringBuffer.toString());
-
+
if (cosmeticNpc) {
scriptCosmetics.put(npcid, cosmeticids);
}
@@ -277,72 +246,74 @@ public class MapleCashCosmeticsChecker {
fileReader.close();
}
}
-
+
private static void processCosmeticScriptData() throws IOException {
System.out.println("Reading script files ...");
loadScripts();
-
- if (ignoreCurrentScriptCosmetics) {
+
+ if (IGNORE_CURRENT_SCRIPT_COSMETICS) {
for (Set npcCosmetics : scriptCosmetics.values()) {
npcCosmetics.clear();
}
}
-
+
for (Integer itemid : allCosmetics) {
List npcids = findCosmeticDataNpcids(itemid);
setCosmeticUsage(npcids, itemid);
}
}
-
+
private static List loadCosmeticCouponids() throws IOException {
List couponItemids = new LinkedList<>();
-
- fileReader = new InputStreamReader(new FileInputStream(handbookPath + "/Cash.txt"), "UTF-8");
+
+ fileReader = new InputStreamReader(new FileInputStream(getHandbookFileName("/Cash.txt")), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line;
- while((line = bufferedReader.readLine())!=null){
- if (line.isEmpty()) continue;
+ while ((line = bufferedReader.readLine()) != null) {
+ if (line.isEmpty()) {
+ continue;
+ }
String[] s = line.split(" - ", 3);
-
- int itemid = Integer.valueOf(s[0]);
+
+ int itemid = Integer.parseInt(s[0]);
if (itemid >= 5150000 && itemid < 5160000) {
couponItemids.add(itemid);
couponNames.put(itemid, s[1]);
}
}
-
+
bufferedReader.close();
fileReader.close();
-
+
return couponItemids;
}
-
+
private static List findItemidOnScript(int itemid) {
List files = new LinkedList<>();
String t = String.valueOf(itemid);
-
- for (Entry text : scriptEntries.entrySet()) {
+
+ for (Map.Entry text : scriptEntries.entrySet()) {
if (text.getValue().contains(t)) {
files.add(text.getKey());
}
}
-
+
return files;
}
-
+
private static void loadCosmeticCouponNpcs() throws IOException {
System.out.println("Locating cosmetic NPCs ...");
-
+
for (Integer itemid : loadCosmeticCouponids()) {
List npcids = findItemidOnScript(itemid);
-
+
if (!npcids.isEmpty()) {
cosmeticNpcs.put(itemid, npcids.get(0));
}
}
}
-
+
private enum CosmeticType {
HAIRSTYLE,
HAIRCOLOR,
@@ -351,11 +322,11 @@ public class MapleCashCosmeticsChecker {
EYE_COLOR,
SKIN_CARE
}
-
+
private static Pair parseCosmeticCoupon(String[] tokens) {
for (int i = 0; i < tokens.length; i++) {
String s = tokens[i];
-
+
if (s.startsWith("Hair")) {
if (s.contentEquals("Hairstyle")) {
return new Pair<>(i, CosmeticType.HAIRSTYLE);
@@ -378,10 +349,10 @@ public class MapleCashCosmeticsChecker {
return new Pair<>(i, CosmeticType.SKIN_CARE);
}
}
-
+
return null;
}
-
+
private static List getCosmeticCouponData(String town, String type, String subtype) {
List ret = new ArrayList<>(3);
ret.add(town);
@@ -389,77 +360,83 @@ public class MapleCashCosmeticsChecker {
ret.add(subtype);
return ret;
}
-
+
private static List parseCosmeticCoupon(String couponName) {
String town, type, subtype = "EXP";
-
+
String[] s = couponName.split(" Coupon ", 2);
-
+
if (s.length > 1) {
subtype = s[1].substring(1, s[1].length() - 1);
}
-
+
String[] tokens = s[0].split(" ");
Pair cosmeticData = parseCosmeticCoupon(tokens);
- if (cosmeticData == null) return null;
-
+ if (cosmeticData == null) {
+ return null;
+ }
+
town = "";
for (int i = 0; i < cosmeticData.left; i++) {
town += (tokens[i] + "_");
}
town = town.substring(0, town.length() - 1).toLowerCase();
-
+
switch (cosmeticData.right) {
case HAIRSTYLE:
type = "hair";
break;
-
+
case FACE_SURGERY:
type = "face";
break;
-
+
default:
return null;
}
-
+
return getCosmeticCouponData(town, type, subtype);
}
-
+
private static void generateCosmeticPlaceNpcs() {
- for (Entry e : couponNames.entrySet()) {
+ for (Map.Entry e : couponNames.entrySet()) {
Integer npcid = cosmeticNpcs.get(e.getKey());
- if (npcid == null) continue;
-
+ if (npcid == null) {
+ continue;
+ }
+
String couponName = e.getValue();
List couponData = parseCosmeticCoupon(couponName);
-
- if (couponData == null) continue;
+
+ if (couponData == null) {
+ continue;
+ }
cosmeticNpcids.put(couponData, npcid);
}
}
-
+
private static Integer getCosmeticNpcid(String townName, String typeCosmetic, String typeCoupon) {
return cosmeticNpcids.get(getCosmeticCouponData(townName, typeCosmetic, typeCoupon));
}
-
+
private static String getCosmeticName(String name, boolean gender) {
- String ret = name + " (" + (gender ? "F" : "M") + ")";
- return ret;
+ final String genderString = gender ? "F" : "M";
+ return String.format("%s (%s)", name, genderString);
}
-
+
private static void loadCosmeticNames(String cosmeticPath) throws IOException {
- fileReader = new InputStreamReader(new FileInputStream(cosmeticPath), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(cosmeticPath), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line;
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
String[] s = line.split(" - ", 3);
- int itemid = Integer.valueOf(s[0]);
-
+ int itemid = Integer.parseInt(s[0]);
+
String name;
if (itemid < 30000) {
itemid = itemid - ((itemid / 100) % 10) * 100;
-
+
int idx = s[1].lastIndexOf(" ");
if (idx > -1) {
name = s[1].substring(0, idx);
@@ -468,7 +445,7 @@ public class MapleCashCosmeticsChecker {
}
} else {
itemid = (Integer.valueOf(s[0]) / 10) * 10;
-
+
int idx = s[1].indexOf(" ");
if (idx > -1) {
name = s[1].substring(idx + 1);
@@ -476,17 +453,17 @@ public class MapleCashCosmeticsChecker {
name = s[1];
}
}
-
+
name = name.trim();
-
+
String cname = getCosmeticName(name, (((itemid / 1000) % 10) % 3) != 0);
-
+
/*
if (cosmeticNameIds.containsKey(cname) && Math.abs(cosmeticNameIds.get(cname) - itemid) > 50) {
System.out.println("Clashing '" + name + "' " + itemid + "/" + cosmeticNameIds.get(cname));
}
*/
-
+
cosmeticNameIds.put(cname, itemid);
cosmeticIdNames.put(itemid, name);
}
@@ -494,17 +471,21 @@ public class MapleCashCosmeticsChecker {
bufferedReader.close();
fileReader.close();
}
-
+
private static void loadCosmeticNames() throws IOException {
System.out.println("Reading cosmetics from handbook ...");
-
- loadCosmeticNames(handbookPath + "/Equip/Face.txt");
- loadCosmeticNames(handbookPath + "/Equip/Hair.txt");
+
+ loadCosmeticNames(getHandbookFileName("/Equip/Face.txt"));
+ loadCosmeticNames(getHandbookFileName("/Equip/Hair.txt"));
}
-
+
+ private static String getHandbookFileName(String fileName) {
+ return ToolConstants.HANDBOOK_PATH + fileName;
+ }
+
private static List fetchExpectedCosmetics(String[] cosmeticList, boolean gender) {
List list = new LinkedList<>();
-
+
for (String cosmetic : cosmeticList) {
String cname = getCosmeticName(cosmetic, gender);
Integer itemid = cosmeticNameIds.get(cname);
@@ -514,30 +495,30 @@ public class MapleCashCosmeticsChecker {
missingCosmeticNames.add(cosmetic);
}
}
-
+
return list;
}
-
+
private static void verifyCosmeticExpectedFile(File f) throws IOException {
String townName = f.getParent().substring(f.getParent().lastIndexOf("\\") + 1);
String typeCosmetic = f.getName().substring(0, f.getName().indexOf("."));
-
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line;
- while((line = bufferedReader.readLine())!=null){
+ while ((line = bufferedReader.readLine()) != null) {
String[] s = line.split(": ", 2);
String[] t = s[0].split("ale ");
-
+
String typeCoupon = t[1];
boolean gender = !t[0].contentEquals("M");
-
+
Integer npcid = getCosmeticNpcid(townName, typeCosmetic, typeCoupon);
if (npcid != null) {
String[] cosmetics = s[1].split(", ");
List cosmeticItemids = fetchExpectedCosmetics(cosmetics, gender);
-
+
Set npcCosmetics = scriptCosmetics.get(npcid);
Set missingCosmetics = new HashSet<>();
for (Integer itemid : cosmeticItemids) {
@@ -545,10 +526,10 @@ public class MapleCashCosmeticsChecker {
missingCosmetics.add(itemid);
}
}
-
+
if (!missingCosmetics.isEmpty()) {
Pair key = new Pair<>(npcid, typeCoupon);
-
+
Set list = missingCosmeticsNpcTypes.get(key);
if (list == null) {
missingCosmeticsNpcTypes.put(key, missingCosmetics);
@@ -558,34 +539,34 @@ public class MapleCashCosmeticsChecker {
}
}
}
-
+
bufferedReader.close();
fileReader.close();
}
-
+
private static void verifyCosmeticExpectedData() throws IOException {
System.out.println("Analyzing cosmetic NPC scripts ...");
-
+
ArrayList cosmeticRecipes = new ArrayList<>();
- listFiles(libPath + "/care", cosmeticRecipes);
-
+ listFiles(INPUT_DIRECTORY_PATH, cosmeticRecipes);
+
for (File f : cosmeticRecipes) {
verifyCosmeticExpectedFile(f);
}
}
-
+
private static List, List>> getSortedMapEntries(Map, Set> map) {
List, List>> list = new ArrayList<>(map.size());
- for(Entry, Set> e : map.entrySet()) {
+ for (Map.Entry, Set> e : map.entrySet()) {
List il = new ArrayList<>(2);
il.addAll(e.getValue());
-
- Collections.sort(il, (o1, o2) -> o1 - o2);
-
+
+ il.sort((o1, o2) -> o1 - o2);
+
list.add(new Pair<>(e.getKey(), il));
}
-
- Collections.sort(list, (o1, o2) -> {
+
+ list.sort((o1, o2) -> {
int cmp = o1.getLeft().getLeft() - o2.getLeft().getLeft();
if (cmp == 0) {
return o1.getLeft().getRight().compareTo(o2.getLeft().getRight());
@@ -593,20 +574,20 @@ public class MapleCashCosmeticsChecker {
return cmp;
}
});
-
+
return list;
}
-
+
private static void printReportFileHeader() {
printWriter.println(" # Report File autogenerated from the MapleCashCosmeticsChecker feature by Ronan Lana.");
printWriter.println(" # Generated data takes into account several data info from the server source files and the server-side WZ.xmls.");
printWriter.println();
}
-
+
private static Pair, List> getCosmeticReport(List itemids) {
List maleItemids = new LinkedList<>();
List femaleItemids = new LinkedList<>();
-
+
for (Integer i : itemids) {
if ((((i / 1000) % 10) % 3) == 0) {
maleItemids.add(i);
@@ -614,10 +595,10 @@ public class MapleCashCosmeticsChecker {
femaleItemids.add(i);
}
}
-
+
return new Pair<>(maleItemids, femaleItemids);
}
-
+
private static void reportNpcCosmetics(List itemids) {
if (!itemids.isEmpty()) {
String res = " ";
@@ -625,75 +606,75 @@ public class MapleCashCosmeticsChecker {
res += (i + ", ");
unusedCosmetics.remove(i);
}
-
+
printWriter.println(res.substring(0, res.length() - 2));
}
}
-
+
private static void reportCosmeticResults() throws IOException {
System.out.println("Reporting results ...");
-
- printWriter = new PrintWriter("lib/result.txt", "UTF-8");
-
+
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
printReportFileHeader();
-
+
if (!missingCosmeticsNpcTypes.isEmpty()) {
printWriter.println("Found " + missingCosmeticsNpcTypes.size() + " entries with missing cosmetic entries.");
-
+
for (Pair, List> mcn : getSortedMapEntries(missingCosmeticsNpcTypes)) {
printWriter.println(" NPC " + mcn.getLeft());
-
+
Pair, List> genderItemids = getCosmeticReport(mcn.getRight());
reportNpcCosmetics(genderItemids.getLeft());
reportNpcCosmetics(genderItemids.getRight());
printWriter.println();
}
}
-
+
if (!unusedCosmetics.isEmpty()) {
printWriter.println("Unused cosmetics: " + unusedCosmetics.size());
-
+
List list = new ArrayList<>(unusedCosmetics);
Collections.sort(list);
-
+
for (Integer i : list) {
printWriter.println(i + " " + cosmeticIdNames.get(i));
}
-
+
printWriter.println();
}
-
+
if (!missingCosmeticNames.isEmpty()) {
printWriter.println("Missing cosmetic itemids: " + missingCosmeticNames.size());
-
+
List listString = new ArrayList<>(missingCosmeticNames);
Collections.sort(listString);
-
+
for (String c : listString) {
printWriter.println(c);
}
-
+
printWriter.println();
}
printWriter.close();
}
-
+
public static void main(String[] args) {
try {
loadCosmeticWzData();
processCosmeticScriptData();
-
+
loadCosmeticCouponNpcs();
generateCosmeticPlaceNpcs();
-
+
loadCosmeticNames();
verifyCosmeticExpectedData();
-
+
reportCosmeticResults();
System.out.println("Done!");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
-}
\ No newline at end of file
+}
diff --git a/tools/MapleCashCosmeticsFetcher/src/maplecashcosmeticsfetcher/MapleCashCosmeticsFetcher.java b/src/main/java/tools/mapletools/CashCosmeticsFetcher.java
similarity index 52%
rename from tools/MapleCashCosmeticsFetcher/src/maplecashcosmeticsfetcher/MapleCashCosmeticsFetcher.java
rename to src/main/java/tools/mapletools/CashCosmeticsFetcher.java
index 797be5090b..2c775f7362 100644
--- a/tools/MapleCashCosmeticsFetcher/src/maplecashcosmeticsfetcher/MapleCashCosmeticsFetcher.java
+++ b/src/main/java/tools/mapletools/CashCosmeticsFetcher.java
@@ -1,57 +1,28 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplecashcosmeticsfetcher;
+import server.MapleItemInformationProvider;
+import tools.DatabaseConnection;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.ArrayList;
-
-import tools.MapleItemInformationProvider;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
/**
*
* @author RonanLana
-
- This application gathers info from the WZ.XML files, fetching all cosmetic coupons and tickets from there, and then
- searches the NPC script files, identifying the stylish NPCs that supposedly uses them. It will reports all NPCs that
- uses up a card, as well as report those currently unused.
-
- Estimated parse time: 10 seconds
+
+This application gathers info from the WZ.XML files, fetching all cosmetic coupons and tickets from there, and then
+searches the NPC script files, identifying the stylish NPCs that supposedly uses them. It will reports all NPCs that
+uses up a card, as well as report those currently unused.
+
+Estimated parse time: 10 seconds
*/
-public class MapleCashCosmeticsFetcher {
- static MapleItemInformationProvider ii;
-
- static String wzPath = "../../wz";
- static String scriptPath = "../../scripts";
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static Map scriptEntries = new HashMap<>(500);
+public class CashCosmeticsFetcher {
+ private static final Map scriptEntries = new HashMap<>(500);
private static void listFiles(String directoryName, ArrayList files) {
File directory = new File(directoryName);
@@ -66,25 +37,25 @@ public class MapleCashCosmeticsFetcher {
}
}
}
-
+
private static int getNpcIdFromFilename(String name) {
try {
- return Integer.valueOf(name.substring(0, name.indexOf('.')));
+ return Integer.parseInt(name.substring(0, name.indexOf('.')));
} catch(Exception e) {
return -1;
}
}
-
+
private static void loadScripts() throws Exception {
ArrayList files = new ArrayList<>();
- listFiles(scriptPath + "/npc", files);
+ listFiles(ToolConstants.SCRIPTS_PATH + "/npc", files);
for(File f : files) {
Integer npcid = getNpcIdFromFilename(f.getName());
-
+
//System.out.println("Parsing " + f.getAbsolutePath());
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
- bufferedReader = new BufferedReader(fileReader);
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuilder stringBuffer = new StringBuilder();
String line;
@@ -92,28 +63,29 @@ public class MapleCashCosmeticsFetcher {
while((line = bufferedReader.readLine())!=null){
stringBuffer.append(line).append("\n");
}
-
+
scriptEntries.put(npcid, stringBuffer.toString());
bufferedReader.close();
fileReader.close();
}
}
-
+
private static List findItemidOnScript(int itemid) {
List files = new LinkedList<>();
String t = String.valueOf(itemid);
-
- for (Entry text : scriptEntries.entrySet()) {
+
+ for (Map.Entry text : scriptEntries.entrySet()) {
if (text.getValue().contains(t)) {
files.add(text.getKey());
}
}
-
+
return files;
}
-
+
private static void reportCosmeticCouponResults() {
+ final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (int itemid = 5150000; itemid <= 5154000; itemid++) {
String itemName = ii.getName(itemid);
@@ -128,18 +100,16 @@ public class MapleCashCosmeticsFetcher {
}
}
}
-
+
public static void main(String[] args) {
- System.setProperty("wzpath", wzPath);
- ii = MapleItemInformationProvider.getInstance();
-
+ DatabaseConnection.initializeConnectionPool(); // MapleItemInformationProvider loads unrelated stuff from the db
try {
loadScripts();
System.out.println("Loaded scripts");
-
+
reportCosmeticCouponResults();
} catch(Exception e) {
e.printStackTrace();
}
}
-}
\ No newline at end of file
+}
diff --git a/tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java b/src/main/java/tools/mapletools/CashDropFetcher.java
similarity index 56%
rename from tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java
rename to src/main/java/tools/mapletools/CashDropFetcher.java
index cc610c9fcd..75176c4a81 100644
--- a/tools/MapleCashDropFetcher/src/maplecashdropfetcher/MapleCashDropFetcher.java
+++ b/src/main/java/tools/mapletools/CashDropFetcher.java
@@ -1,96 +1,59 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
+import tools.Pair;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplecashdropfetcher;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.sql.Connection;
-import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.HashSet;
-import java.util.Set;
-
-import java.io.File;
-
-import tools.Pair;
+import java.util.*;
/**
- *
* @author RonanLana
-
- This application gets info from the WZ.XML files regarding cash itemids then searches the drop data on the DB
- after any NX (cash item) drops and reports them.
-
- Estimated parse time: 2 minutes
+ *
+ * This application gets info from the WZ.XML files regarding cash itemids then searches the drop data on the DB
+ * after any NX (cash item) drops and reports them.
+ *
+ * Estimated parse time: 2 minutes
*/
-public class MapleCashDropFetcher {
- static String host = "jdbc:mysql://localhost:3306/cosmic";
- static String driver = "com.mysql.jdbc.Driver";
- static String username = "cosmic_server";
- static String password = "snailshell";
+public class CashDropFetcher {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("cash_drop_report.txt");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
+ private static final int INITIAL_STRING_LENGTH = 50;
+ private static final int ITEM_FILE_NAME_SIZE = 13;
- static String wzPath = "../../wz";
-
- static String directoryName = "../..";
- static String newFile = "lib/CashDropReport.txt";
+ private static final Set nxItems = new HashSet<>();
+ private static final Set nxDrops = new HashSet<>();
- static Connection con = null;
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static int initialLength = 200;
- static int initialStringLength = 50;
- static int itemFileNameSize = 13;
-
- static Set nxItems = new HashSet<>();
- static Set nxDrops = new HashSet<>();
-
- static byte status = 0;
- static int currentItemid = 0;
+ private static PrintWriter printWriter = null;
+ private static BufferedReader bufferedReader = null;
+
+ private static byte status = 0;
+ private static int currentItemid = 0;
private static String getName(String token) {
int i, j;
char[] dest;
String d;
-
+
i = token.lastIndexOf("name");
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- if(j < i) return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
-
- dest = new char[initialStringLength];
+ if (j < i) {
+ return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
+ }
+
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static String getValue(String token) {
int i, j;
char[] dest;
@@ -100,115 +63,106 @@ public class MapleCashDropFetcher {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
-
+
+
private static void inspectEquipWzEntry() {
String line = null;
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateEquipToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void translateEquipToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
- if(status == 1) {
- if(!getName(token).equals("info")) {
+ } else if (token.contains("imgdir")) {
+ if (status == 1) {
+ if (!getName(token).equals("info")) {
forwardCursor(status);
}
}
-
+
status += 1;
- }
- else {
- if(status == 2) {
+ } else {
+ if (status == 2) {
String d = getName(token);
-
- if(d.equals("cash")) {
- if(!getValue(token).equals("0")) {
+
+ if (d.equals("cash")) {
+ if (!getValue(token).equals("0")) {
nxItems.add(currentItemid);
}
-
+
forwardCursor(status);
}
}
}
}
-
+
private static void inspectItemWzEntry() {
String line = null;
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateItemToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void translateItemToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
- if(status == 1) {
- currentItemid = Integer.valueOf(getName(token));
- }
- else if(status == 2) {
- if(!getName(token).equals("info")) {
+ } else if (token.contains("imgdir")) {
+ if (status == 1) {
+ currentItemid = Integer.parseInt(getName(token));
+ } else if (status == 2) {
+ if (!getName(token).equals("info")) {
forwardCursor(status);
}
}
-
+
status += 1;
- }
- else {
- if(status == 3) {
+ } else {
+ if (status == 3) {
String d = getName(token);
-
- if(d.equals("cash")) {
- if(!getValue(token).equals("0")) {
+
+ if (d.equals("cash")) {
+ if (!getValue(token).equals("0")) {
nxItems.add(currentItemid);
}
-
+
forwardCursor(status);
}
}
@@ -220,7 +174,7 @@ public class MapleCashDropFetcher {
printWriter.println(" # Generated data takes into account several data info from the underlying DB and the server-side WZ.xmls.");
printWriter.println();
}
-
+
private static void listFiles(String directoryName, ArrayList files) {
File directory = new File(directoryName);
@@ -234,93 +188,92 @@ public class MapleCashDropFetcher {
}
}
}
-
+
private static int getItemIdFromFilename(String name) {
try {
- return Integer.valueOf(name.substring(0, name.indexOf('.')));
- } catch(Exception e) {
+ return Integer.parseInt(name.substring(0, name.indexOf('.')));
+ } catch (Exception e) {
return -1;
}
}
-
+
private static String getDropTableName(boolean dropdata) {
return (dropdata ? "drop_data" : "reactordrops");
}
-
+
private static String getDropElementName(boolean dropdata) {
return (dropdata ? "dropperid" : "reactorid");
}
-
+
private static void filterNxDropsOnDB(boolean dropdata) throws SQLException {
nxDrops.clear();
-
+
PreparedStatement ps = con.prepareStatement("SELECT DISTINCT itemid FROM " + getDropTableName(dropdata));
ResultSet rs = ps.executeQuery();
-
- while(rs.next()) {
+
+ while (rs.next()) {
int itemid = rs.getInt("itemid");
-
- if(nxItems.contains(itemid)) {
+
+ if (nxItems.contains(itemid)) {
nxDrops.add(itemid);
}
}
-
+
rs.close();
ps.close();
}
-
+
private static List> getNxDropsEntries(boolean dropdata) throws SQLException {
List> entries = new ArrayList<>();
-
+
List sortedNxDrops = new ArrayList<>(nxDrops);
Collections.sort(sortedNxDrops);
-
- for(Integer nx : sortedNxDrops) {
+
+ for (Integer nx : sortedNxDrops) {
PreparedStatement ps = con.prepareStatement("SELECT " + getDropElementName(dropdata) + " FROM " + getDropTableName(dropdata) + " WHERE itemid = ?");
ps.setInt(1, nx);
-
+
ResultSet rs = ps.executeQuery();
- while(rs.next()) {
+ while (rs.next()) {
entries.add(new Pair<>(nx, rs.getInt(getDropElementName(dropdata))));
}
-
+
rs.close();
ps.close();
}
-
+
return entries;
}
-
+
private static void reportNxDropResults(boolean dropdata) throws SQLException {
filterNxDropsOnDB(dropdata);
-
- if(!nxDrops.isEmpty()) {
+
+ if (!nxDrops.isEmpty()) {
List> nxEntries = getNxDropsEntries(dropdata);
printWriter.println("NX DROPS ON " + getDropTableName(dropdata));
- for(Pair nx : nxEntries) {
+ for (Pair nx : nxEntries) {
printWriter.println(nx.left + " : " + nx.right);
}
printWriter.println("\n\n\n");
}
}
-
- private static void ReportNxDropData() {
+
+ private static void reportNxDropData() {
try {
- Class.forName(driver).newInstance();
-
System.out.println("Reading Character.wz ...");
ArrayList files = new ArrayList<>();
- listFiles(wzPath + "/Character.wz", files);
-
- for(File f : files) {
+ listFiles(WZFiles.CHARACTER.getFilePath(), files);
+
+ InputStreamReader fileReader = null;
+ for (File f : files) {
//System.out.println("Parsing " + f.getAbsolutePath());
int itemid = getItemIdFromFilename(f.getName());
- if(itemid < 0) {
+ if (itemid < 0) {
continue;
}
-
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
currentItemid = itemid;
@@ -329,24 +282,24 @@ public class MapleCashDropFetcher {
bufferedReader.close();
fileReader.close();
}
-
+
System.out.println("Reading Item.wz ...");
files = new ArrayList<>();
- listFiles(wzPath + "/Item.wz", files);
-
- for(File f : files) {
+ listFiles(WZFiles.ITEM.getFilePath(), files);
+
+ for (File f : files) {
//System.out.println("Parsing " + f.getAbsolutePath());
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
- if(f.getName().length() <= itemFileNameSize) {
+ if (f.getName().length() <= ITEM_FILE_NAME_SIZE) {
inspectItemWzEntry();
} else { // pet file structure is similar to equips, maybe there are other item-types following this behaviour?
int itemid = getItemIdFromFilename(f.getName());
- if(itemid < 0) {
+ if (itemid < 0) {
continue;
}
-
+
currentItemid = itemid;
inspectEquipWzEntry();
}
@@ -354,53 +307,35 @@ public class MapleCashDropFetcher {
bufferedReader.close();
fileReader.close();
}
-
+
System.out.println("Reporting results...");
-
- // filter drop data on DB
- con = DriverManager.getConnection(host, username, password);
-
+
// report suspects of missing quest drop data, as well as those drop data that may have incorrect questids.
- printWriter = new PrintWriter(newFile, "UTF-8");
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
printReportFileHeader();
-
+
reportNxDropResults(true);
reportNxDropResults(false);
-
+
/*
printWriter.println("NX LIST"); // list of all cash items found
for(Integer nx : nxItems) {
printWriter.println(nx);
}
*/
-
+
con.close();
printWriter.close();
System.out.println("Done!");
- }
-
- catch(SQLException e) {
+ } catch (SQLException e) {
System.out.println("Warning: Could not establish connection to database to report quest data.");
System.out.println(e.getMessage());
- }
-
- catch(ClassNotFoundException e) {
- System.out.println("Error: could not find class");
- System.out.println(e.getMessage());
- }
-
- catch(InstantiationException e) {
- System.out.println("Error: instantiation failure");
- System.out.println(e.getMessage());
- }
-
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
public static void main(String[] args) {
- ReportNxDropData();
+ reportNxDropData();
}
-
}
diff --git a/tools/MapleCashVegaChecker/src/maplecashvegachecker/MapleCashVegaChecker.java b/src/main/java/tools/mapletools/CashVegaChecker.java
similarity index 65%
rename from tools/MapleCashVegaChecker/src/maplecashvegachecker/MapleCashVegaChecker.java
rename to src/main/java/tools/mapletools/CashVegaChecker.java
index 220a1fdd24..ffdebc41d6 100644
--- a/tools/MapleCashVegaChecker/src/maplecashvegachecker/MapleCashVegaChecker.java
+++ b/src/main/java/tools/mapletools/CashVegaChecker.java
@@ -1,57 +1,32 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplecashvegachecker;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
/**
*
* @author RonanLana
- *
- This application main objective is to read Vega-related information from
- the item's description report back missing nodes for these items.
-
- Estimated parse time: 10 seconds
+ *
+This application main objective is to read Vega-related information from
+the item's description report back missing nodes for these items.
+
+Estimated parse time: 10 seconds
*/
-public class MapleCashVegaChecker {
-
- private static String wzPath = "../../wz";
-
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static int initialStringLength = 1000;
- static int currentItem;
-
- static byte status = 0;
-
- static Set vegaItems = new HashSet<>();
-
+public class CashVegaChecker {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("vega_checker_report.txt");
+ private static final int INITIAL_STRING_LENGTH = 1000;
+ private static final Set vegaItems = new HashSet<>();
+
+ private static PrintWriter printWriter = null;
+ private static InputStreamReader fileReader = null;
+ private static BufferedReader bufferedReader = null;
+ private static int currentItem;
+ private static byte status = 0;
+
private static String getName(String token) {
int i, j;
char[] dest;
@@ -61,13 +36,13 @@ public class MapleCashVegaChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
return(d.trim());
}
-
+
private static String getValue(String token) {
int i, j;
char[] dest;
@@ -77,13 +52,13 @@ public class MapleCashVegaChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
-
+
d = new String(dest);
return(d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
@@ -105,16 +80,16 @@ public class MapleCashVegaChecker {
status += 1;
}
}
-
+
private static void translateItemToken(String token) {
if(token.contains("/imgdir")) {
status -= 1;
}
else if(token.contains("imgdir")) {
status += 1;
-
+
if (status == 2) {
- currentItem = Integer.valueOf(getName(token));
+ currentItem = Integer.parseInt(getName(token));
}
} else {
if (status == 2) {
@@ -124,7 +99,7 @@ public class MapleCashVegaChecker {
}
}
}
-
+
private static void translateVegaToken(String token) {
if(token.contains("/imgdir")) {
status -= 1;
@@ -139,11 +114,11 @@ public class MapleCashVegaChecker {
}
}
}
-
+
private static void readItemDescriptionFile(File f) {
System.out.print("Reading String.wz... ");
try {
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line;
@@ -158,11 +133,11 @@ public class MapleCashVegaChecker {
}
System.out.println(vegaItems.size() + " Vega Scroll items found");
}
-
+
private static void readVegaDescriptionFile(File f) {
System.out.println("Reading Etc.wz...");
try {
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line;
@@ -176,38 +151,38 @@ public class MapleCashVegaChecker {
ioe.printStackTrace();
}
}
-
+
private static void printReportFileHeader() {
printWriter.println(" # Report File autogenerated from the MapleCashVegaChecker feature by Ronan Lana.");
printWriter.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
printWriter.println();
}
-
+
private static void reportMissingVegaItems() {
System.out.println("Reporting results ...");
-
+
try {
- printWriter = new PrintWriter("lib/result.txt", "UTF-8");
-
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
printReportFileHeader();
for (Integer itemid : vegaItems) {
printWriter.println(" " + itemid);
}
-
+
printWriter.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
-
+
}
-
+
public static void main(String[] args) {
-
- readItemDescriptionFile(new File(wzPath + "/String.wz/Consume.img.xml"));
- readVegaDescriptionFile(new File(wzPath + "/Etc.wz/VegaSpell.img.xml"));
-
+
+ readItemDescriptionFile(new File(WZFiles.STRING.getFilePath() + "/Consume.img.xml"));
+ readVegaDescriptionFile(new File(WZFiles.ETC.getFilePath() + "/VegaSpell.img.xml"));
+
reportMissingVegaItems();
}
-
+
}
diff --git a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java b/src/main/java/tools/mapletools/CodeCouponGenerator.java
similarity index 64%
rename from tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java
rename to src/main/java/tools/mapletools/CodeCouponGenerator.java
index 45e2abab35..0539cf4d17 100644
--- a/tools/MapleCodeCouponGenerator/src/maplecodecoupongenerator/MapleCodeCouponGenerator.java
+++ b/src/main/java/tools/mapletools/CodeCouponGenerator.java
@@ -1,79 +1,46 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import tools.Pair;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplecodecoupongenerator;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
/**
- *
* @author RonanLana
-
- This application parses the coupon descriptor XML file and automatically generates
- code entries on the DB reflecting the descriptions found. Parse time relies on the
- sum of coupon codes created and amount of current codes on DB.
-
- Estimated parse time: 2 minutes (for 100 code entries)
+ *
+ * This application parses the coupon descriptor XML file and automatically generates
+ * code entries on the DB reflecting the descriptions found. Parse time relies on the
+ * sum of coupon codes created and amount of current codes on DB.
+ *
+ * Estimated parse time: 2 minutes (for 100 code entries)
*/
-public class MapleCodeCouponGenerator {
- static String host = "jdbc:mysql://localhost:3306/cosmic";
- static String driver = "com.mysql.jdbc.Driver";
- static String username = "cosmic_server";
- static String password = "snailshell";
-
- static Connection con = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static String fileName = "lib/CouponCodes.img.xml";
- static long currentTime;
-
- static int initialStringLength = 250;
-
- static String name;
- static boolean active;
- static int quantity, duration;
- static int maplePoint, nxCredit, nxPrepaid;
-
- static List> itemList = new ArrayList<>();
- static Pair item;
-
-
- static List activeCoupons = new ArrayList<>();
- static List generatedKeys;
- static Set usedCodes = new HashSet<>();
-
- static byte status;
-
+public class CodeCouponGenerator {
+ private static final File INPUT_FILE = ToolConstants.getInputFile("CouponCodes.img.xml");
+ private static final int INITIAL_STRING_LENGTH = 250;
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
+
+ private static final List activeCoupons = new ArrayList<>();
+ private static final Set usedCodes = new HashSet<>();
+ private static final List> itemList = new ArrayList<>();
+
+ private static BufferedReader bufferedReader = null;
+ private static long currentTime;
+ private static String name;
+ private static boolean active;
+ private static int quantity;
+ private static int duration;
+ private static int maplePoint;
+ private static int nxCredit;
+ private static int nxPrepaid;
+ private static Pair item;
+ private static List generatedKeys;
+ private static byte status;
+
private static void resetCouponPackage() {
name = null;
active = false;
@@ -84,17 +51,17 @@ public class MapleCodeCouponGenerator {
nxPrepaid = 0;
itemList.clear();
}
-
+
private static String getName(String token) {
int i, j;
char[] dest;
String d;
-
+
i = token.lastIndexOf("name");
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
try {
token.getChars(i, j, dest, 0);
} catch (StringIndexOutOfBoundsException e) {
@@ -105,14 +72,13 @@ public class MapleCodeCouponGenerator {
e.printStackTrace();
try {
Thread.sleep(100000000);
- } catch (Exception ex) {}
+ } catch (Exception ex) {
+ }
}
-
- d = new String(dest);
- return(d.trim());
+ return new String(dest).trim();
}
-
+
private static String getValue(String token) {
int i, j;
char[] dest;
@@ -122,68 +88,64 @@ public class MapleCodeCouponGenerator {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
+
private static void translateToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
-
+
if (status == 1) {
if (active) {
activeCoupons.add(new CodeCouponDescriptor(name, quantity, duration, maplePoint, nxCredit, nxPrepaid, itemList));
}
-
+
resetCouponPackage();
} else if (status == 3) {
itemList.add(item);
}
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
-
+
if (status == 4) {
item = new Pair<>(-1, -1);
} else if (status == 2) {
String d = getName(token);
-
+
System.out.println(" Reading coupon '" + d + "'");
name = d;
}
- }
- else {
+ } else {
String d = getName(token);
-
+
if (status == 2) {
switch (d) {
case "active":
- if (Integer.valueOf(getValue(token)) == 0) {
+ if (Integer.parseInt(getValue(token)) == 0) {
forwardCursor(status);
resetCouponPackage();
} else {
@@ -192,19 +154,19 @@ public class MapleCodeCouponGenerator {
break;
case "quantity":
- quantity = Integer.valueOf(getValue(token));
+ quantity = Integer.parseInt(getValue(token));
break;
case "duration":
- duration = Integer.valueOf(getValue(token));
+ duration = Integer.parseInt(getValue(token));
break;
case "maplePoint":
- maplePoint = Integer.valueOf(getValue(token));
+ maplePoint = Integer.parseInt(getValue(token));
break;
case "nxCredit":
- nxCredit = Integer.valueOf(getValue(token));
+ nxCredit = Integer.parseInt(getValue(token));
break;
case "nxPrepaid":
- nxPrepaid = Integer.valueOf(getValue(token));
+ nxPrepaid = Integer.parseInt(getValue(token));
break;
}
} else if (status == 4) {
@@ -219,13 +181,13 @@ public class MapleCodeCouponGenerator {
}
}
}
-
+
private static class CodeCouponDescriptor {
protected String name;
protected int quantity, duration;
protected int nxCredit, maplePoint, nxPrepaid;
protected List> itemList;
-
+
protected CodeCouponDescriptor(String name, int quantity, int duration, int maplePoint, int nxCredit, int nxPrepaid, List> itemList) {
this.name = name;
this.quantity = quantity;
@@ -233,109 +195,111 @@ public class MapleCodeCouponGenerator {
this.maplePoint = maplePoint;
this.nxCredit = nxCredit;
this.nxPrepaid = nxPrepaid;
-
+
this.itemList = new ArrayList<>(itemList);
}
}
-
+
private static String randomizeCouponCode() {
return Long.toHexString(Double.doubleToLongBits(Math.random())).substring(0, 15);
}
-
+
private static String generateCouponCode() {
String newCode;
do {
newCode = randomizeCouponCode();
} while (usedCodes.contains(newCode));
-
+
usedCodes.add(newCode);
return newCode;
}
-
+
private static List getGeneratedKeys(PreparedStatement ps) throws SQLException {
if (generatedKeys == null) {
generatedKeys = new ArrayList<>();
-
+
ResultSet rs = ps.getGeneratedKeys();
while (rs.next()) {
generatedKeys.add(rs.getInt(1));
}
rs.close();
}
-
+
return generatedKeys;
}
-
+
private static void commitCodeCouponDescription(CodeCouponDescriptor recipe) throws SQLException {
- if (recipe.quantity < 1) return;
-
+ if (recipe.quantity < 1) {
+ return;
+ }
+
System.out.println(" Generating coupon '" + recipe.name + "'");
generatedKeys = null;
-
+
PreparedStatement ps = con.prepareStatement("INSERT IGNORE INTO `nxcode` (`code`, `expiration`) VALUES (?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setLong(2, currentTime + ((long) recipe.duration * 60 * 60 * 1000));
-
- for(int i = 0; i < recipe.quantity; i++) {
+
+ for (int i = 0; i < recipe.quantity; i++) {
ps.setString(1, generateCouponCode());
ps.addBatch();
}
ps.executeBatch();
-
+
PreparedStatement ps2 = con.prepareStatement("INSERT IGNORE INTO `nxcode_items` (`codeid`, `type`, `item`, `quantity`) VALUES (?, ?, ?, ?)");
if (!recipe.itemList.isEmpty()) {
ps2.setInt(2, 5);
List keys = getGeneratedKeys(ps);
-
+
for (Pair p : recipe.itemList) {
ps2.setInt(3, p.getLeft());
ps2.setInt(4, p.getRight());
-
+
for (Integer codeid : keys) {
ps2.setInt(1, codeid);
ps2.addBatch();
}
}
}
-
+
ps2.setInt(3, 0);
if (recipe.nxCredit > 0) {
ps2.setInt(2, 0);
ps2.setInt(4, recipe.nxCredit);
List keys = getGeneratedKeys(ps);
-
- for(Integer codeid : keys) {
+
+ for (Integer codeid : keys) {
ps2.setInt(1, codeid);
ps2.addBatch();
}
}
-
+
if (recipe.maplePoint > 0) {
ps2.setInt(2, 1);
ps2.setInt(4, recipe.maplePoint);
List keys = getGeneratedKeys(ps);
-
- for(Integer codeid : keys) {
+
+ for (Integer codeid : keys) {
ps2.setInt(1, codeid);
ps2.addBatch();
}
}
-
+
if (recipe.nxPrepaid > 0) {
ps2.setInt(2, 2);
ps2.setInt(4, recipe.nxPrepaid);
List keys = getGeneratedKeys(ps);
-
- for(Integer codeid : keys) {
+
+ for (Integer codeid : keys) {
ps2.setInt(1, codeid);
ps2.addBatch();
}
}
-
+
ps2.executeBatch();
ps2.close();
ps.close();
}
-
+
private static void loadUsedCouponCodes() throws SQLException {
PreparedStatement ps = con.prepareStatement("SELECT code FROM nxcode", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = ps.executeQuery();
@@ -345,51 +309,48 @@ public class MapleCodeCouponGenerator {
rs.close();
ps.close();
}
-
- private static void generateCodeCoupons(String fileName) throws IOException {
- fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
+
+ private static void generateCodeCoupons(File file) throws IOException {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
resetCouponPackage();
status = 0;
-
+
System.out.println("Reading XML coupon information...");
String line;
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateToken(line);
}
bufferedReader.close();
fileReader.close();
System.out.println();
-
+
try {
- Class.forName(driver).newInstance();
- con = DriverManager.getConnection(host, username, password);
-
System.out.println("Loading DB coupon codes...");
loadUsedCouponCodes();
System.out.println();
-
+
System.out.println("Saving generated coupons...");
currentTime = System.currentTimeMillis();
for (CodeCouponDescriptor ccd : activeCoupons) {
commitCodeCouponDescription(ccd);
}
System.out.println();
-
+
con.close();
System.out.println("Done.");
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException e) {
+ } catch (SQLException e) {
e.printStackTrace();
}
}
-
+
public static void main(String[] args) {
try {
- generateCodeCoupons(fileName);
- } catch(IOException ex) {
- System.out.println("Error reading file '" + fileName + "'");
+ generateCodeCoupons(INPUT_FILE);
+ } catch (IOException ex) {
+ System.out.println("Error reading file '" + INPUT_FILE.getAbsolutePath() + "'");
}
}
}
diff --git a/src/main/java/tools/mapletools/CouponInstaller.java b/src/main/java/tools/mapletools/CouponInstaller.java
new file mode 100644
index 0000000000..aba16b58dd
--- /dev/null
+++ b/src/main/java/tools/mapletools/CouponInstaller.java
@@ -0,0 +1,255 @@
+package tools.mapletools;
+
+import provider.wz.WZFiles;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+/**
+ * @author RonanLana
+ *
+ * This application gathers information about the Cash Shop's EXP & DROP coupons,
+ * such as applied rates, active times of day and days of week and dumps them in
+ * a SQL table that the server will make use.
+ */
+public class CouponInstaller {
+ private static final File COUPON_INPUT_FILE_1 = new File(WZFiles.ITEM.getFilePath(), "/Cash/0521.img.xml");
+ private static final File COUPON_INPUT_FILE_2 = new File(WZFiles.ITEM.getFilePath(), "/Cash/0536.img.xml");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int itemId = -1;
+ private static int itemMultiplier = 1;
+ private static int startHour = -1;
+ private static int endHour = -1;
+ private static int activeDay = 0;
+
+ private static String getName(String token) {
+ int i, j;
+ char[] dest;
+ String d;
+
+ i = token.lastIndexOf("name");
+ if (i < 0) {
+ return "";
+ }
+
+ i = token.indexOf("\"", i) + 1; //lower bound of the string
+ j = token.indexOf("\"", i); //upper bound
+
+ dest = new char[8];
+ token.getChars(i, j, dest, 0);
+
+ d = new String(dest);
+ return (d);
+ }
+
+ private static String getNodeValue(String token) {
+ int i, j;
+ char[] dest;
+ String d;
+
+ i = token.lastIndexOf("value=");
+ i = token.indexOf("\"", i) + 1; //lower bound of the string
+ j = token.indexOf("\"", i); //upper bound
+
+ if (j - i < 1) {
+ return "";
+ }
+
+ dest = new char[j - i];
+ token.getChars(i, j, dest, 0);
+
+ d = new String(dest);
+ return (d);
+ }
+
+ private static void forwardCursor(int st) {
+ String line = null;
+
+ try {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
+ simpleToken(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void simpleToken(String token) {
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ status += 1;
+ }
+ }
+
+ private static int getDayOfWeek(String day) {
+ return switch (day) {
+ case "SUN" -> 1;
+ case "MON" -> 2;
+ case "TUE" -> 3;
+ case "WED" -> 4;
+ case "THU" -> 5;
+ case "FRI" -> 6;
+ case "SAT" -> 7;
+ default -> 0;
+ };
+ }
+
+ private static void processHourTimeString(String time) {
+ startHour = Integer.parseInt(time.substring(4, 6));
+ endHour = Integer.parseInt(time.substring(7, 9));
+ }
+
+ private static void processDayTimeString(String time) {
+ String day = time.substring(0, 3);
+ int d = getDayOfWeek(day);
+
+ activeDay |= (1 << d);
+ }
+
+ private static void loadTimeFromCoupon(int st) {
+ System.out.println("Loading coupon id " + itemId + ". Rate: " + itemMultiplier + "x.");
+
+ String line = null;
+ try {
+ startHour = -1;
+ endHour = -1;
+ activeDay = 0;
+
+ String time = null;
+ while ((line = bufferedReader.readLine()) != null) {
+ simpleToken(line);
+ if (status < st) {
+ break;
+ }
+
+ time = getNodeValue(line);
+ processDayTimeString(time);
+
+ simpleToken(line);
+ }
+
+ if (time != null) {
+ processHourTimeString(time);
+
+ PreparedStatement ps = con.prepareStatement("INSERT INTO nxcoupons (couponid, rate, activeday, starthour, endhour) VALUES (?, ?, ?, ?, ?)");
+ ps.setInt(1, itemId);
+ ps.setInt(2, itemMultiplier);
+ ps.setInt(3, activeDay);
+ ps.setInt(4, startHour);
+ ps.setInt(5, endHour);
+ ps.execute();
+
+ ps.close();
+ }
+ } catch (SQLException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void translateToken(String token) {
+ String d;
+
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ if (status == 1) { //getting ItemId
+ d = getName(token);
+ itemId = Integer.parseInt(d);
+ } else if (status == 2) {
+ d = getName(token);
+
+ if (!d.contains("info")) {
+ forwardCursor(status);
+ }
+ } else if (status == 3) {
+ d = getName(token);
+
+ if (!d.contains("time")) {
+ forwardCursor(status);
+ } else {
+ loadTimeFromCoupon(status);
+ }
+ }
+
+ status += 1;
+ } else {
+ if (status == 3) {
+ d = getName(token);
+
+ if (d.contains("rate")) {
+ String r = getNodeValue(token);
+
+ double db = Double.parseDouble(r);
+ itemMultiplier = (int) db;
+ }
+ }
+ }
+ }
+
+ private static void installRateCoupons(File file) {
+ // This will reference one line at a time
+ String line = null;
+
+ try {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(fileReader);
+
+ while ((line = bufferedReader.readLine()) != null) {
+ translateToken(line);
+ }
+
+ bufferedReader.close();
+ fileReader.close();
+ } catch (FileNotFoundException ex) {
+ System.out.println("Unable to open file '" + file + "'");
+ } catch (IOException ex) {
+ System.out.println("Error reading file '" + file + "'");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void installCouponsTable() {
+ try {
+ PreparedStatement ps = con.prepareStatement("DROP TABLE IF EXISTS `nxcoupons`;");
+ ps.execute();
+ ps.close();
+
+ ps = con.prepareStatement(
+ """
+ CREATE TABLE IF NOT EXISTS `nxcoupons` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `couponid` int(11) NOT NULL DEFAULT '0',
+ `rate` int(11) NOT NULL DEFAULT '0',
+ `activeday` int(11) NOT NULL DEFAULT '0',
+ `starthour` int(11) NOT NULL DEFAULT '0',
+ `endhour` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;"""
+ );
+
+ ps.execute();
+ ps.close();
+
+ installRateCoupons(COUPON_INPUT_FILE_1);
+ installRateCoupons(COUPON_INPUT_FILE_2);
+
+ con.close();
+ } catch (SQLException e) {
+ System.out.println("Warning: Could not establish connection to database to change card chance rate.");
+ System.out.println(e.getMessage());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ installCouponsTable();
+ }
+}
diff --git a/tools/MapleDojoUpdater/src/mapledojoupdate/MapleDojoUpdate.java b/src/main/java/tools/mapletools/DojoUpdate.java
similarity index 53%
rename from tools/MapleDojoUpdater/src/mapledojoupdate/MapleDojoUpdate.java
rename to src/main/java/tools/mapletools/DojoUpdate.java
index f39284f75c..dbacb0ac18 100644
--- a/tools/MapleDojoUpdater/src/mapledojoupdate/MapleDojoUpdate.java
+++ b/src/main/java/tools/mapletools/DojoUpdate.java
@@ -1,70 +1,42 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package mapledojoupdate;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.sql.Connection;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
/**
- *
* @author RonanLana
-
- This application parses the Character.wz folder inputted and adds/updates the "info/level"
- node on every known equipment id. This addition enables client-side view of the equipment
- level attribute on every equipment in the game, given proper item visibility, be it from
- own equipments or from other players.
-
- Estimated parse time: 10 seconds
-
+ *
+ * This application parses the Character.wz folder inputted and adds/updates the "info/level"
+ * node on every known equipment id. This addition enables client-side view of the equipment
+ * level attribute on every equipment in the game, given proper item visibility, be it from
+ * own equipments or from other players.
+ *
+ * Estimated parse time: 10 seconds
*/
-public class MapleDojoUpdate {
+public class DojoUpdate {
+ private static final File INPUT_DIRECTORY = new File(WZFiles.MAP.getFile(), "/Map/Map9");
+ private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("dojo-maps");
+ private static final int DOJO_MIN_MAP_ID = 925_020_100;
+ private static final int DOJO_MAX_MAP_ID = 925_033_804;
+ private static final int INITIAL_STRING_LENGTH = 250;
+
+ private static PrintWriter printWriter = null;
+ private static BufferedReader bufferedReader = null;
+ private static boolean isDojoMapid;
+ private static byte status;
- static String dojoDirectory = "lib/original/";
- static String outputDirectory = "lib/updated/";
-
- static Connection con = null;
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static int initialStringLength = 250;
- static boolean isDojoMapid;
-
- static byte status;
-
private static String getName(String token) {
int i, j;
char[] dest;
String d;
-
+
i = token.lastIndexOf("name");
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
try {
token.getChars(i, j, dest, 0);
} catch (StringIndexOutOfBoundsException e) {
@@ -75,59 +47,56 @@ public class MapleDojoUpdate {
e.printStackTrace();
try {
Thread.sleep(100000000);
- } catch (Exception ex) {}
+ } catch (Exception ex) {
+ }
}
-
+
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
printWriter.println(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
+
private static void translateToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
printWriter.println(token);
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
printWriter.println(token);
status += 1;
-
+
if (status == 2) {
String d = getName(token);
- if(!d.contentEquals("info")) {
+ if (!d.contentEquals("info")) {
forwardCursor(status);
}
} else if (status > 2) {
forwardCursor(status);
}
- }
- else {
+ } else {
if (status == 2 && isDojoMapid) {
String item = getName(token);
-
+
if (item.contentEquals("onFirstUserEnter")) {
printWriter.println(" ");
} else if (item.contentEquals("onUserEnter")) {
@@ -140,24 +109,27 @@ public class MapleDojoUpdate {
}
}
}
-
+
private static int getMapId(String fileName) {
return Integer.parseInt(fileName.substring(0, 9));
}
-
+
private static void parseDojoData(File file, String curPath) throws IOException {
- printWriter = new PrintWriter(outputDirectory + curPath + file.getName(), "UTF-8");
-
- fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
+ int mapId = getMapId(file.getName());
+ isDojoMapid = isDojoMapId(mapId);
+ if (!isDojoMapid) {
+ return;
+ }
+
+ printWriter = new PrintWriter(OUTPUT_DIRECTORY.getPath() + "/" + curPath + file.getName(), StandardCharsets.UTF_8);
+
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
status = 0;
-
- int mapid = getMapId(file.getName());
- isDojoMapid = mapid >= 925020100 && mapid < 925040000;
-
+
String line;
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateToken(line);
}
@@ -167,35 +139,35 @@ public class MapleDojoUpdate {
printFileFooter();
printWriter.close();
}
-
+
+ private static boolean isDojoMapId(int mapId) {
+ return mapId >= DOJO_MIN_MAP_ID && mapId <= DOJO_MAX_MAP_ID;
+ }
+
private static void printFileFooter() {
printWriter.println("");
}
-
+
private static void parseDirectoryDojoData(String curPath) {
- File folder = new File(outputDirectory + curPath);
+ File folder = new File(OUTPUT_DIRECTORY, curPath);
if (!folder.exists()) {
folder.mkdir();
}
-
+
System.out.println("Parsing directory '" + curPath + "'");
- folder = new File(dojoDirectory + curPath);
+ folder = new File(INPUT_DIRECTORY, curPath);
for (File file : folder.listFiles()) {
if (file.isFile()) {
try {
parseDojoData(file, curPath);
- }
- catch(FileNotFoundException ex) {
+ } catch (FileNotFoundException ex) {
System.out.println("Unable to open dojo file " + file.getAbsolutePath() + ".");
- }
- catch(IOException ex) {
+ } catch (IOException ex) {
System.out.println("Error reading dojo file " + file.getAbsolutePath() + ".");
- }
-
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
} else {
@@ -203,9 +175,8 @@ public class MapleDojoUpdate {
}
}
}
-
+
public static void main(String[] args) {
parseDirectoryDojoData("");
}
-
}
diff --git a/tools/MapleEmptyItemWzChecker/src/mapleemptyitemwzchecker/MapleEmptyItemWzChecker.java b/src/main/java/tools/mapletools/EmptyItemWzChecker.java
similarity index 65%
rename from tools/MapleEmptyItemWzChecker/src/mapleemptyitemwzchecker/MapleEmptyItemWzChecker.java
rename to src/main/java/tools/mapletools/EmptyItemWzChecker.java
index 6636bbcf50..f696d319a1 100644
--- a/tools/MapleEmptyItemWzChecker/src/mapleemptyitemwzchecker/MapleEmptyItemWzChecker.java
+++ b/src/main/java/tools/mapletools/EmptyItemWzChecker.java
@@ -1,72 +1,38 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package mapleemptyitemwzchecker;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
/**
- *
* @author RonanLana
- *
- This application has two objectives: it reports in a detailed file all itemids which is
- currently missing either a name entry in the String.wz or an item entry in the Item.wz;
- And it removes from the String.wz XMLs all entries which misses properties on Item.wz.
+ *
+ * This application has two objectives: it reports in a detailed file all itemids which is
+ * currently missing either a name entry in the String.wz or an item entry in the Item.wz;
+ * And it removes from the String.wz XMLs all entries which misses properties on Item.wz.
*/
-public class MapleEmptyItemWzChecker {
-
- static String newFile = "lib/Report.txt";
- static String outputWzPath = "lib";
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static String wzPath = "../../wz";
- static String handbookPath = "../../handbook";
- static int initialStringLength = 50;
- static int itemFileNameSize = 13;
-
- static byte status = 0;
- static int currentItemid = 0;
- static int currentDepth = 0;
- static Stack currentPath = new Stack<>();
- static String currentFile;
-
- static Map stringWzItems = new HashMap<>();
- static Map contentWzItems = new HashMap<>();
-
- static Set handbookItems = new HashSet<>();
- static Set nonPropItems;
-
+public class EmptyItemWzChecker {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("empty_item_wz_report.txt");
+ private static final String OUTPUT_PATH = ToolConstants.OUTPUT_DIRECTORY.getPath();
+ private static final int INITIAL_STRING_LENGTH = 50;
+ private static final int ITEM_FILE_NAME_SIZE = 13;
+
+ private static final Stack currentPath = new Stack<>();
+ private static final Map stringWzItems = new HashMap<>();
+ private static final Map contentWzItems = new HashMap<>();
+ private static final Set handbookItems = new HashSet<>();
+
+ private static PrintWriter printWriter = null;
+ private static InputStreamReader fileReader = null;
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int currentItemid = 0;
+ private static int currentDepth = 0;
+ private static String currentFile;
+ private static Set nonPropItems;
+
private static String getName(String token) {
int i, j;
char[] dest;
@@ -76,35 +42,33 @@ public class MapleEmptyItemWzChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
+
private static void listFiles(String directoryName, ArrayList files) {
File directory = new File(directoryName);
@@ -118,137 +82,135 @@ public class MapleEmptyItemWzChecker {
}
}
}
-
+
private static int getItemIdFromFilename(String name) {
try {
- return Integer.valueOf(name.substring(0, name.indexOf('.')));
- } catch(Exception e) {
+ return Integer.parseInt(name.substring(0, name.indexOf('.')));
+ } catch (Exception e) {
return -1;
}
}
-
+
private static void inspectItemWzEntry() {
String line = null;
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateItemToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static String currentItemPath() {
String s = currentFile + " -> ";
-
+
for (String p : currentPath) {
s += (p + "\\");
}
-
+
return s;
}
-
+
private static void translateItemToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
-
+
currentPath.pop();
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
String d = getName(token);
-
- if(status == 2) {
- currentItemid = Integer.valueOf(d);
+
+ if (status == 2) {
+ currentItemid = Integer.parseInt(d);
contentWzItems.put(currentItemid, currentItemPath());
-
+
forwardCursor(status);
} else {
currentPath.push(d);
}
}
}
-
+
private static void inspectStringWzEntry() {
String line = null;
-
+
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateStringToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void translateStringToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
currentPath.pop();
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
String d = getName(token);
-
- if(status == currentDepth) {
- currentItemid = Integer.valueOf(d);
+
+ if (status == currentDepth) {
+ currentItemid = Integer.parseInt(d);
stringWzItems.put(currentItemid, currentItemPath());
//if (currentItemid >= 4000000) System.out.println(" " + currentItemid);
-
+
forwardCursor(status);
} else {
currentPath.push(d);
}
}
}
-
+
private static void loadStringWzFile(String filePath, int depth) throws IOException {
- fileReader = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
currentFile = filePath;
currentDepth = 2 + depth;
//System.out.println(filePath + " depth " + depth);
inspectStringWzEntry();
-
+
bufferedReader.close();
fileReader.close();
}
-
+
private static void loadStringWz() throws IOException {
System.out.println("Reading String.wz ...");
- String stringWzFiles[][] = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
- String stringWzPath = wzPath + "/String.wz/";
-
+ String[][] stringWzFiles = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
+
for (int i = 0; i < stringWzFiles.length; i++) {
for (String dirFile : stringWzFiles[i]) {
- loadStringWzFile(stringWzPath + dirFile + ".img.xml", i);
+ final String fileName = "/" + dirFile + ".img.xml";
+ loadStringWzFile(WZFiles.STRING.getFilePath() + fileName, i);
}
}
}
-
+
private static void loadItemWz() throws IOException {
System.out.println("Reading Item.wz ...");
ArrayList files = new ArrayList<>();
- listFiles(wzPath + "/Item.wz", files);
+ listFiles(WZFiles.ITEM.getFilePath(), files);
+
+ for (File f : files) {
+ if (f.getParentFile().getName().contentEquals("Special")) {
+ continue;
+ }
- for(File f : files) {
- if (f.getParentFile().getName().contentEquals("Special")) continue;
-
//System.out.println("Parsing " + f.getAbsolutePath());
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
currentFile = f.getCanonicalPath();
- if(f.getName().length() <= itemFileNameSize) {
+ if (f.getName().length() <= ITEM_FILE_NAME_SIZE) {
inspectItemWzEntry();
} else { // pet file structure is similar to equips, maybe there are other item-types following this behaviour?
int itemid = getItemIdFromFilename(f.getName());
- if(itemid < 0) {
+ if (itemid < 0) {
continue;
}
@@ -260,17 +222,19 @@ public class MapleEmptyItemWzChecker {
fileReader.close();
}
}
-
+
private static void loadCharacterWz() throws IOException {
System.out.println("Reading Character.wz ...");
ArrayList files = new ArrayList<>();
- listFiles(wzPath + "/Character.wz", files);
+ listFiles(WZFiles.CHARACTER.getFilePath(), files);
+
+ for (File f : files) {
+ if (f.getParentFile().getName().contentEquals("Character.wz")) {
+ continue;
+ }
- for(File f : files) {
- if (f.getParentFile().getName().contentEquals("Character.wz")) continue;
-
int itemid = getItemIdFromFilename(f.getName());
- if(itemid < 0) {
+ if (itemid < 0) {
continue;
}
@@ -279,57 +243,56 @@ public class MapleEmptyItemWzChecker {
contentWzItems.put(currentItemid, currentItemPath());
}
}
-
+
private static void calculateItemNameDiff(Set emptyItemNames, Set emptyNameItems) {
for (Integer i : contentWzItems.keySet()) {
if (!stringWzItems.containsKey(i)) {
emptyNameItems.add(i);
}
}
-
+
for (Integer i : stringWzItems.keySet()) {
if (!contentWzItems.containsKey(i)) {
emptyItemNames.add(i);
}
}
}
-
+
private static void readHandbookItems() throws IOException {
System.out.println("Reading handbook ...");
String[] handbookPaths = {"Equip", "Cash.txt", "Etc.txt", "Pet.txt", "Setup.txt", "Use.txt"};
-
+
for (String path : handbookPaths) {
- readHandbookPath(handbookPath + "/" + path);
+ readHandbookPath(ToolConstants.HANDBOOK_PATH + "/" + path);
}
}
-
+
private static void readHandbookPath(String filePath) throws IOException {
ArrayList files = new ArrayList<>();
-
+
File testFile = new File(filePath);
if (testFile.isDirectory()) {
listFiles(filePath, files);
} else {
files.add(testFile);
}
-
+
for (File f : files) {
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
String line = null;
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
String[] tokens = line.split(" - ");
if (tokens[0].length() > 0) {
- int itemid = Integer.valueOf(tokens[0]);
+ int itemid = Integer.parseInt(tokens[0]);
handbookItems.add(itemid);
}
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
@@ -337,60 +300,60 @@ public class MapleEmptyItemWzChecker {
fileReader.close();
}
}
-
+
private static void printReportFileHeader() {
printWriter.println(" # Report File autogenerated from the MapleEmptyItemWzChecker feature by Ronan Lana.");
printWriter.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
printWriter.println();
}
-
+
private static List getSortedItems(Set items) {
List sortedItems = new ArrayList<>(items);
Collections.sort(sortedItems);
-
+
return sortedItems;
}
-
+
private static void printReportFileResults(Set emptyItemNames, Set emptyNameItems) {
if (!emptyItemNames.isEmpty()) {
printWriter.println("String.wz NAMES with no Item.wz node, " + emptyItemNames.size() + " entries:");
-
- for(Integer itemid : getSortedItems(emptyItemNames)) {
+
+ for (Integer itemid : getSortedItems(emptyItemNames)) {
printWriter.println(" " + itemid + " " + stringWzItems.get(itemid) + (handbookItems.contains(itemid) ? "" : " NOT FOUND"));
}
-
+
printWriter.println();
}
-
+
if (!emptyNameItems.isEmpty()) {
printWriter.println("Item.wz ITEMS with no String.wz node, " + emptyNameItems.size() + " entries:");
-
- for(Integer itemid : getSortedItems(emptyNameItems)) {
+
+ for (Integer itemid : getSortedItems(emptyNameItems)) {
printWriter.println(" " + itemid + " " + contentWzItems.get(itemid) + (handbookItems.contains(itemid) ? "" : " NOT FOUND"));
}
-
+
printWriter.println();
}
}
-
+
private static void reportItemNameDiff(Set emptyItemNames, Set emptyNameItems) throws IOException {
System.out.println("Reporting results...");
- printWriter = new PrintWriter(newFile, "UTF-8");
-
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
printReportFileHeader();
printReportFileResults(emptyItemNames, emptyNameItems);
-
+
printWriter.close();
}
-
+
private static void locateItemStringWzDiff() throws IOException {
Set emptyItemNames = new HashSet<>(), emptyNameItems = new HashSet<>();
calculateItemNameDiff(emptyItemNames, emptyNameItems);
-
+
reportItemNameDiff(emptyItemNames, emptyNameItems);
nonPropItems = emptyItemNames;
}
-
+
private static void runEmptyItemWzChecker() throws IOException {
readHandbookItems();
@@ -400,77 +363,75 @@ public class MapleEmptyItemWzChecker {
locateItemStringWzDiff();
}
-
+
private static void generateStringWzEntry() {
String line = null;
-
+
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
updateStringToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void updateStringToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
-
- }
- else if(token.contains("imgdir")) {
+
+ } else if (token.contains("imgdir")) {
status += 1;
-
+
if (status == currentDepth && nonPropItems.contains(Integer.valueOf(getName(token)))) {
forwardCursor(status);
return;
}
}
-
+
printWriter.println(token);
}
-
+
private static void generateStringWzFile(String filePath, int depth) throws IOException {
- fileReader = new InputStreamReader(new FileInputStream(wzPath + filePath), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(WZFiles.DIRECTORY + filePath), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
- printWriter = new PrintWriter(outputWzPath + filePath, "UTF-8");
+ printWriter = new PrintWriter(OUTPUT_PATH + filePath, StandardCharsets.UTF_8);
currentDepth = 2 + depth;
-
+
//System.out.println(filePath + " depth " + depth);
generateStringWzEntry();
-
+
printWriter.close();
bufferedReader.close();
fileReader.close();
}
-
+
private static void generateStringWz() throws IOException {
System.out.println("Generating clean String.wz ...");
- String stringWzFiles[][] = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
+ String[][] stringWzFiles = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
String stringWzPath = "/String.wz/";
-
- File folder = new File(outputWzPath + "/String.wz/");
+
+ File folder = new File(OUTPUT_PATH + "/String.wz/");
if (!folder.exists()) {
folder.mkdirs();
}
-
+
for (int i = 0; i < stringWzFiles.length; i++) {
for (String dirFile : stringWzFiles[i]) {
generateStringWzFile(stringWzPath + dirFile + ".img.xml", i);
}
}
}
-
+
public static void main(String[] args) {
try {
runEmptyItemWzChecker();
generateStringWz();
-
+
System.out.println("Done!");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
-
+
}
diff --git a/tools/MapleEquipmentOmnileveler/src/mapleequipmentomnileveler/MapleEquipmentOmnileveler.java b/src/main/java/tools/mapletools/EquipmentOmniLeveller.java
similarity index 65%
rename from tools/MapleEquipmentOmnileveler/src/mapleequipmentomnileveler/MapleEquipmentOmnileveler.java
rename to src/main/java/tools/mapletools/EquipmentOmniLeveller.java
index 6e0731f40d..b10caeb260 100644
--- a/tools/MapleEquipmentOmnileveler/src/mapleequipmentomnileveler/MapleEquipmentOmnileveler.java
+++ b/src/main/java/tools/mapletools/EquipmentOmniLeveller.java
@@ -1,82 +1,51 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package mapleequipmentomnileveler;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.sql.Connection;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
/**
- *
* @author RonanLana
-
- This application parses the Character.wz folder inputted and adds/updates the "info/level"
- node on every known equipment id. This addition enables client-side view of the equipment
- level attribute on every equipment in the game, given proper item visibility, be it from
- own equipments or from other players.
-
- Estimated parse time: 7 minutes
-
+ *
+ * This application parses the Character.wz folder inputted and adds/updates the "info/level"
+ * node on every known equipment id. This addition enables client-side view of the equipment
+ * level attribute on every equipment in the game, given proper item visibility, be it from
+ * own equipments or from other players.
+ *
+ * Estimated parse time: 7 minutes
*/
-public class MapleEquipmentOmnileveler {
+public class EquipmentOmniLeveller {
+ private static final File INPUT_DIRECTORY = WZFiles.CHARACTER.getFile();
+ private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("equips-with-levels");
+ private static final int INITIAL_STRING_LENGTH = 250;
+ private static final int FIXED_EXP = 10000;
+ private static final int MAX_EQP_LEVEL = 30;
+
+ private static PrintWriter printWriter = null;
+ private static InputStreamReader fileReader = null;
+ private static BufferedReader bufferedReader = null;
+
+ private static int infoTagState = -1;
+ private static int infoTagExpState = -1;
+ private static boolean infoTagLevel;
+ private static boolean infoTagLevelExp;
+ private static boolean infoTagLevelInfo;
+ private static int parsedLevels = 0;
+ private static byte status;
+ private static boolean upgradeable;
+ private static boolean cash;
- static String equipDirectory = "lib/original/";
- static String outputDirectory = "lib/updated/";
-
- static Connection con = null;
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static int initialStringLength = 250;
-
- static int fixedExp = 10000;
- static int maxEqpLevel = 30;
-
- static int infoTagState = -1, infoTagExpState = -1;
-
- static boolean infoTagLevel;
- static boolean infoTagLevelExp;
- static boolean infoTagLevelInfo;
-
- static int parsedLevels = 0;
-
- static byte status;
- static boolean upgradeable;
- static boolean cash;
-
private static String getName(String token) {
int i, j;
char[] dest;
String d;
-
+
i = token.lastIndexOf("name");
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
try {
token.getChars(i, j, dest, 0);
} catch (StringIndexOutOfBoundsException e) {
@@ -87,14 +56,15 @@ public class MapleEquipmentOmnileveler {
e.printStackTrace();
try {
Thread.sleep(100000000);
- } catch (Exception ex) {}
+ } catch (Exception ex) {
+ }
}
-
+
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static String getValue(String token) {
int i, j;
char[] dest;
@@ -104,153 +74,147 @@ public class MapleEquipmentOmnileveler {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
printWriter.println(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void translateLevelCursor(int st) {
String line = null;
-
+
try {
infoTagLevelInfo = false;
while (status >= st && (line = bufferedReader.readLine()) != null) {
translateLevelToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void translateInfoTag(int st) {
infoTagLevel = false;
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) { // skipping directory & canvas definition
+ while (status >= st && (line = bufferedReader.readLine()) != null) { // skipping directory & canvas definition
translateInfoToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
-
+
if (!upgradeable || cash) {
throw new RuntimeException();
}
}
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
+
private static void printUpdatedLevelExp() {
- printWriter.println(" ");
+ printWriter.println(" ");
}
-
+
private static void printDefaultLevel(int level) {
printWriter.println(" ");
printUpdatedLevelExp();
printWriter.println(" ");
}
-
+
private static void printDefaultLevelInfoTag() {
printWriter.println(" ");
- for (int i = 1; i <= maxEqpLevel; i++) printDefaultLevel(i);
+ for (int i = 1; i <= MAX_EQP_LEVEL; i++) {
+ printDefaultLevel(i);
+ }
printWriter.println(" ");
}
-
+
private static void printDefaultLevelTag() {
printWriter.println(" ");
printDefaultLevelInfoTag();
printWriter.println(" ");
}
-
+
private static void processLevelInfoTag(int st) {
String line;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
translateLevelExpToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void processLevelInfoSet(int st) {
- parsedLevels = (1 << maxEqpLevel) - 1;
-
+ parsedLevels = (1 << MAX_EQP_LEVEL) - 1;
+
String line;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
translateLevelInfoSetToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void translateLevelToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
if (status == 3) {
if (!infoTagLevelInfo) {
printDefaultLevelInfoTag();
}
}
printWriter.println(token);
-
+
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
printWriter.println(token);
status += 1;
-
+
if (status == 4) {
String d = getName(token);
- if(d.contentEquals("info")) {
+ if (d.contentEquals("info")) {
infoTagLevelInfo = true;
processLevelInfoSet(status);
} else {
forwardCursor(status);
}
}
- }
- else {
+ } else {
printWriter.println(token);
}
}
-
+
private static void translateLevelInfoSetToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
-
+
if (status == 3) {
if (parsedLevels != 0) {
- for (int i = 0; i < maxEqpLevel; i++) {
+ for (int i = 0; i < MAX_EQP_LEVEL; i++) {
if ((parsedLevels >> i) % 2 != 0) {
int level = i + 1;
printDefaultLevel(level);
@@ -258,47 +222,43 @@ public class MapleEquipmentOmnileveler {
}
}
}
-
+
printWriter.println(token);
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
printWriter.println(token);
status += 1;
-
+
if (status == 5) {
int level = Integer.parseInt(getName(token)) - 1;
parsedLevels ^= (1 << level);
-
+
infoTagLevelExp = false;
infoTagExpState = status; // status: 5
- processLevelInfoTag(status);
+ processLevelInfoTag(status);
infoTagExpState = -1;
}
- }
- else {
+ } else {
printWriter.println(token);
}
}
-
+
private static void translateLevelExpToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
-
+
if (status < infoTagExpState) {
if (!infoTagLevelExp) {
printUpdatedLevelExp();
}
}
-
+
printWriter.println(token);
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
printWriter.println(token);
status += 1;
-
+
forwardCursor(status);
- }
- else {
+ } else {
String name = getName(token);
if (name.contentEquals("exp")) {
infoTagLevelExp = true;
@@ -308,23 +268,22 @@ public class MapleEquipmentOmnileveler {
}
}
}
-
+
private static void translateInfoToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
-
+
if (status < infoTagState) {
if (!infoTagLevel) {
printDefaultLevelTag();
}
}
-
+
printWriter.println(token);
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
printWriter.println(token);
-
+
String d = getName(token);
if (d.contentEquals("level")) {
infoTagLevel = true;
@@ -332,17 +291,16 @@ public class MapleEquipmentOmnileveler {
} else {
forwardCursor(status);
}
- }
- else {
+ } else {
String name = getName(token);
-
- switch(name) {
+
+ switch (name) {
case "cash":
if (!getValue(token).contentEquals("0")) {
cash = true;
}
break;
-
+
case "tuc":
case "incPAD":
case "incMAD":
@@ -363,25 +321,24 @@ public class MapleEquipmentOmnileveler {
}
break;
}
-
+
printWriter.println(token);
}
}
-
+
private static boolean translateToken(String token) {
boolean accessInfoTag = false;
-
- if(token.contains("/imgdir")) {
+
+ if (token.contains("/imgdir")) {
status -= 1;
printWriter.println(token);
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
printWriter.println(token);
status += 1;
-
+
if (status == 2) {
String d = getName(token);
- if(!d.contentEquals("info")) {
+ if (!d.contentEquals("info")) {
forwardCursor(status);
} else {
accessInfoTag = true;
@@ -389,22 +346,21 @@ public class MapleEquipmentOmnileveler {
} else if (status > 2) {
forwardCursor(status);
}
- }
- else {
+ } else {
printWriter.println(token);
}
-
+
return accessInfoTag;
}
-
+
private static void copyCashItemData(File file, String curPath) throws IOException {
- printWriter = new PrintWriter(outputDirectory + curPath + file.getName(), "UTF-8");
-
- fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
+ printWriter = new PrintWriter(new File(OUTPUT_DIRECTORY, curPath + file.getName()), StandardCharsets.UTF_8);
+
+ fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
String line;
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
printWriter.println(line);
}
@@ -413,70 +369,66 @@ public class MapleEquipmentOmnileveler {
printWriter.close();
}
-
+
private static void parseEquipData(File file, String curPath) throws IOException {
- printWriter = new PrintWriter(outputDirectory + curPath + file.getName(), "UTF-8");
-
- fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
+ printWriter = new PrintWriter(new File(OUTPUT_DIRECTORY, curPath + file.getName()), StandardCharsets.UTF_8);
+
+ fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
try {
status = 0;
upgradeable = false;
cash = false;
-
+
String line;
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
if (translateToken(line)) {
infoTagState = status; // status: 2
translateInfoTag(status);
infoTagState = -1;
}
}
-
+
bufferedReader.close();
fileReader.close();
-
+
printFileFooter();
printWriter.close();
} catch (RuntimeException e) {
bufferedReader.close();
fileReader.close();
-
+
printWriter.close();
-
+
copyCashItemData(file, curPath);
}
}
-
+
private static void printFileFooter() {
printWriter.println("");
}
-
+
private static void parseDirectoryEquipData(String curPath) {
- File folder = new File(outputDirectory + curPath);
+ File folder = new File(OUTPUT_DIRECTORY, curPath);
if (!folder.exists()) {
folder.mkdir();
}
-
+
System.out.println("Parsing directory '" + curPath + "'");
- folder = new File(equipDirectory + curPath);
+ folder = new File(INPUT_DIRECTORY, curPath);
for (File file : folder.listFiles()) {
if (file.isFile()) {
try {
parseEquipData(file, curPath);
- }
- catch(FileNotFoundException ex) {
+ } catch (FileNotFoundException ex) {
System.out.println("Unable to open equip file " + file.getAbsolutePath() + ".");
- }
- catch(IOException ex) {
+ } catch (IOException ex) {
System.out.println("Error reading equip file " + file.getAbsolutePath() + ".");
- }
-
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
} else {
@@ -484,9 +436,8 @@ public class MapleEquipmentOmnileveler {
}
}
}
-
+
public static void main(String[] args) {
parseDirectoryEquipData("");
}
-
}
diff --git a/src/main/java/tools/mapletools/EventMethodFiller.java b/src/main/java/tools/mapletools/EventMethodFiller.java
new file mode 100644
index 0000000000..473fbbde75
--- /dev/null
+++ b/src/main/java/tools/mapletools/EventMethodFiller.java
@@ -0,0 +1,102 @@
+package tools.mapletools;
+
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author RonanLana
+ *
+ * This application objective is to read all scripts from the event folder
+ * and fill empty functions for every function name not yet present in the
+ * script.
+ *
+ * Estimated parse time: 10 seconds
+ */
+public class EventMethodFiller {
+ private static boolean foundMatchingDataOnFile(String fileContent, Pattern pattern) {
+ Matcher matcher = pattern.matcher(fileContent);
+ return matcher.find();
+ }
+
+ private static void fileSearchMatchingData(File file, Map functions) {
+ try {
+ String fileContent = FileUtils.readFileToString(file, "UTF-8");
+ List fillFunctions = new LinkedList<>();
+
+ for (Map.Entry f : functions.entrySet()) {
+ if (!foundMatchingDataOnFile(fileContent, f.getKey())) {
+ fillFunctions.add(f.getValue());
+ }
+ }
+
+ if (!fillFunctions.isEmpty()) {
+ System.out.println("Filling out " + file.getName() + "...");
+
+ FileWriter fileWriter = new FileWriter(file, true);
+ PrintWriter printWriter = new PrintWriter(fileWriter);
+
+ printWriter.println();
+ printWriter.println();
+ printWriter.println("// ---------- FILLER FUNCTIONS ----------");
+ printWriter.println();
+
+ for (String s : fillFunctions) {
+ printWriter.println(s);
+ printWriter.println();
+ }
+
+ printWriter.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void filterDirectorySearchMatchingData(String directoryPath, Map functions) {
+ Iterator iter = FileUtils.iterateFiles(new File(directoryPath), new String[]{"sql", "js", "txt", "java"}, true);
+
+ while (iter.hasNext()) {
+ File file = (File) iter.next();
+ fileSearchMatchingData(file, functions);
+ }
+ }
+
+ private static Pattern compileJsFunctionPattern(String function) {
+ String jsFunction = "function(\\s)+";
+ return Pattern.compile(jsFunction + function);
+ }
+
+ private static Map getFunctions() {
+ Map functions = new HashMap<>();
+ functions.put(compileJsFunctionPattern("playerEntry"), "function playerEntry(eim, player) {}");
+ functions.put(compileJsFunctionPattern("playerExit"), "function playerExit(eim, player) {}");
+ functions.put(compileJsFunctionPattern("scheduledTimeout"), "function scheduledTimeout(eim) {}");
+ functions.put(compileJsFunctionPattern("playerUnregistered"), "function playerUnregistered(eim, player) {}");
+ functions.put(compileJsFunctionPattern("changedLeader"), "function changedLeader(eim, leader) {}");
+ functions.put(compileJsFunctionPattern("monsterKilled"), "function monsterKilled(mob, eim) {}");
+ functions.put(compileJsFunctionPattern("allMonstersDead"), "function allMonstersDead(eim) {}");
+ functions.put(compileJsFunctionPattern("playerDisconnected"), "function playerDisconnected(eim, player) {}");
+ functions.put(compileJsFunctionPattern("monsterValue"), "function monsterValue(eim, mobid) {return 0;}");
+ functions.put(compileJsFunctionPattern("dispose"), "function dispose() {}");
+ functions.put(compileJsFunctionPattern("leftParty"), "function leftParty(eim, player) {}");
+ functions.put(compileJsFunctionPattern("disbandParty"), "function disbandParty(eim, player) {}");
+ functions.put(compileJsFunctionPattern("clearPQ"), "function clearPQ(eim) {}");
+ functions.put(compileJsFunctionPattern("afterSetup"), "function afterSetup(eim) {}");
+ functions.put(compileJsFunctionPattern("cancelSchedule"), "function cancelSchedule() {}");
+ functions.put(compileJsFunctionPattern("setup"), "function setup(eim, leaderid) {}");
+ //put(compileJsFunctionPattern("getEligibleParty"), "function getEligibleParty(party) {}"); not really needed
+ return functions;
+ }
+
+ public static void main(String[] args) {
+ filterDirectorySearchMatchingData(ToolConstants.SCRIPTS_PATH + "/event", getFunctions());
+ }
+
+}
diff --git a/tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java b/src/main/java/tools/mapletools/GachaponItemIdRetriever.java
similarity index 67%
rename from tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java
rename to src/main/java/tools/mapletools/GachaponItemIdRetriever.java
index c539bd4f52..0761d804a1 100644
--- a/tools/MapleGachaponItemidRetriever/src/maplegachaponitemidretriever/MapleGachaponItemidRetriever.java
+++ b/src/main/java/tools/mapletools/GachaponItemIdRetriever.java
@@ -1,68 +1,36 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2018 RonanLana
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplegachaponitemidretriever;
+package tools.mapletools;
import java.io.*;
-import java.sql.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
- *
* @author RonanLana
- *
+ *
* This application reads metadata for the gachapons found on the "gachapon_items.txt"
* recipe file, then checks up the Handbook DB (installed through MapleIdRetriever)
* and translates the item names from the recipe file into their respective itemids.
* The translated itemids are then stored in specific gachapon files inside the
* "lib/gachapons" folder.
- *
+ *
* Estimated parse time: 1 minute
*/
-public class MapleGachaponItemidRetriever {
+public class GachaponItemIdRetriever {
+ private static final File INPUT_FILE = ToolConstants.getInputFile("gachapon_items.txt");
+ private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("gachapons");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
+ private static final Pattern pattern = Pattern.compile("(\\d*)%");
+ private static final int[] scrollsChances = new int[]{10, 15, 30, 60, 65, 70, 100};
+ private static final Map> scrollItemids = new HashMap<>();
+
+ private static PrintWriter printWriter = null;
- static String host = "jdbc:mysql://localhost:3306/cosmic";
- static String driver = "com.mysql.jdbc.Driver";
- static String username = "cosmic_server";
- static String password = "snailshell";
-
- static Connection con = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
- static PrintWriter printWriter = null;
-
- // ------- SET-UP section arguments --------
-
- static String directoryName = "./handbook/";
-
- // ------- SEARCH section arguments --------
-
- static String inputName = "lib/gachapon_items.txt";
- static String outputPath = "lib/gachapons/";
-
- static Pattern p = Pattern.compile("(\\d*)%");
- static int[] scrollsChances = new int[]{10, 15, 30, 60, 65, 70, 100};
-
- static Map> scrollItemids = new HashMap<>();
-
private static void insertGachaponScrollItemid(Integer id, String name, String description, boolean both) {
GachaponScroll gachaScroll = getGachaponScroll(name, description, both);
@@ -74,25 +42,25 @@ public class MapleGachaponItemidRetriever {
list.add(id);
}
-
+
private static void loadHandbookUseNames() throws SQLException {
PreparedStatement ps = con.prepareStatement("SELECT * FROM `handbook` WHERE `id` >= 2040000 AND `id` < 2050000 ORDER BY `id` ASC;");
ResultSet rs = ps.executeQuery();
- while(rs.next()) {
+ while (rs.next()) {
Integer id = rs.getInt("id");
String name = rs.getString("name");
-
+
if (isUpgradeScroll(name)) {
String description = rs.getString("description");
insertGachaponScrollItemid(id, name, description, false);
insertGachaponScrollItemid(id, name, description, true);
}
}
-
+
rs.close();
ps.close();
-
+
/*
for (Entry> e : scrollItemids.entrySet()) {
System.out.println(e);
@@ -100,41 +68,41 @@ public class MapleGachaponItemidRetriever {
System.out.println("------------");
*/
}
-
+
private static class GachaponScroll {
private String header;
private String target;
private String buff;
private int prop;
-
+
private GachaponScroll(GachaponScroll from, int prop) {
this.header = from.header;
this.target = from.target;
this.buff = from.buff;
this.prop = prop;
}
-
+
private GachaponScroll(String name, String description, boolean both) {
String[] params = name.split(" for ");
if (params.length < 3) {
return;
}
-
+
String header = both ? "scroll" : " " + params[0];
String target = params[1];
int prop = 0;
String buff = params[2];
- Matcher m = p.matcher(buff);
+ Matcher m = pattern.matcher(buff);
if (m.find()) {
- prop = Integer.valueOf(m.group(1));
+ prop = Integer.parseInt(m.group(1));
buff = buff.substring(0, m.start() - 1).trim();
} else {
- m = p.matcher(description);
-
+ m = pattern.matcher(description);
+
if (m.find()) {
- prop = Integer.valueOf(m.group(1));
+ prop = Integer.parseInt(m.group(1));
}
}
@@ -143,45 +111,54 @@ public class MapleGachaponItemidRetriever {
buff = buff.substring(0, idx);
}
buff = buff.replace(".", "");
-
+
this.header = header;
this.target = target;
this.buff = buff;
this.prop = prop;
}
-
- @Override
+
+ @Override
public int hashCode() {
int result = prop ^ (prop >>> 32);
- result = 31 * result + (header != null ? header.hashCode() : 0);
+ result = 31 * result + (header != null ? header.hashCode() : 0);
result = 31 * result + (target != null ? target.hashCode() : 0);
result = 31 * result + (buff != null ? buff.hashCode() : 0);
- return result;
+ return result;
}
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- GachaponScroll sc = (GachaponScroll) o;
- if (header != null ? !header.equals(sc.header) : sc.header != null) return false;
- if (target != null ? !target.equals(sc.target) : sc.target != null) return false;
- if (buff != null ? !buff.equals(sc.buff) : sc.buff != null) return false;
- if (prop != sc.prop) return false;
- return true;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ GachaponScroll sc = (GachaponScroll) o;
+ if (header != null ? !header.equals(sc.header) : sc.header != null) {
+ return false;
+ }
+ if (target != null ? !target.equals(sc.target) : sc.target != null) {
+ return false;
+ }
+ if (buff != null ? !buff.equals(sc.buff) : sc.buff != null) {
+ return false;
+ }
+ return prop == sc.prop;
}
-
+
@Override
public String toString() {
return header + " for " + target + " for " + buff + " - " + prop + "%";
}
-
+
}
-
+
private static String getGachaponScrollResults(String line, boolean both) {
String str = "";
List gachaScrollList;
-
+
GachaponScroll gachaScroll = getGachaponScroll(line, "", both);
if (gachaScroll.prop != 0) {
gachaScrollList = Collections.singletonList(gachaScroll);
@@ -192,7 +169,7 @@ public class MapleGachaponItemidRetriever {
gachaScrollList.add(new GachaponScroll(gachaScroll, prop));
}
}
-
+
for (GachaponScroll gs : gachaScrollList) {
List gachaItemids = scrollItemids.get(gs);
if (gachaItemids != null) {
@@ -209,10 +186,10 @@ public class MapleGachaponItemidRetriever {
}
}
}
-
+
return str;
}
-
+
private static GachaponScroll getGachaponScroll(String name, String description, boolean both) {
name = name.toLowerCase();
name = name.replace("for acc ", "for accuracy ");
@@ -222,22 +199,22 @@ public class MapleGachaponItemidRetriever {
name = name.replace("for attack", "for att");
name = name.replace("1-handed", "one-handed");
name = name.replace("2-handed", "two-handed");
-
+
return new GachaponScroll(name, description, both);
}
-
+
private static boolean isUpgradeScroll(String name) {
return name.matches("^(([D|d]ark )?[S|s]croll for).*");
}
-
+
private static void fetchLineOnMapleHandbook(String line, String rarity) throws SQLException {
String str = "";
if (!isUpgradeScroll(line)) {
- PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? COLLATE latin1_general_ci ORDER BY `id` ASC;");
+ PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? ORDER BY `id` ASC;");
ps.setString(1, line);
ResultSet rs = ps.executeQuery();
- while(rs.next()) {
+ while (rs.next()) {
int id = rs.getInt("id");
str += Integer.toString(id);
@@ -250,37 +227,37 @@ public class MapleGachaponItemidRetriever {
str += getGachaponScrollResults(line, false);
if (str.isEmpty()) {
str += getGachaponScrollResults(line, true);
-
+
if (str.isEmpty()) {
System.out.println("NONE for '" + line + "' : " + getGachaponScroll(line, "", false));
}
}
}
-
+
if (str.isEmpty()) {
str += line;
}
-
+
if (rarity != null) {
str += ("- " + rarity);
}
printWriter.println(str);
}
-
+
private static void fetchDataOnMapleHandbook() throws SQLException {
String line;
-
+
try {
- fileReader = new InputStreamReader(new FileInputStream(inputName), "UTF-8");
- bufferedReader = new BufferedReader(fileReader);
-
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
int skip = 0;
boolean lineHeader = false;
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
if (skip > 0) {
skip--;
-
+
if (lineHeader) {
if (!line.isEmpty()) {
lineHeader = false;
@@ -291,14 +268,19 @@ public class MapleGachaponItemidRetriever {
} else if (line.isEmpty()) {
printWriter.println("");
} else if (line.startsWith("Gachapon ")) {
- String s[] = line.split("� ");
+ String[] s = line.split("� ");
String gachaponName = s[s.length - 1];
gachaponName = gachaponName.replace(" ", "_");
gachaponName = gachaponName.toLowerCase();
-
- if (printWriter != null) printWriter.close();
- printWriter = new PrintWriter(outputPath + gachaponName + ".txt", "UTF-8");
-
+
+ if (printWriter != null) {
+ printWriter.close();
+ }
+ File outputFile = new File(OUTPUT_DIRECTORY, gachaponName + ".txt");
+ setupDirectories(outputFile);
+
+ printWriter = new PrintWriter(outputFile, StandardCharsets.UTF_8);
+
skip = 2;
lineHeader = true;
} else if (line.startsWith(".")) {
@@ -316,44 +298,33 @@ public class MapleGachaponItemidRetriever {
}
}
- if (printWriter != null) printWriter.close();
+ if (printWriter != null) {
+ printWriter.close();
+ }
bufferedReader.close();
fileReader.close();
- }
- catch(FileNotFoundException ex) {
- System.out.println(ex.getMessage());
- }
- catch(IOException ex) {
+ } catch (IOException ex) {
System.out.println(ex.getMessage());
+ ex.printStackTrace();
}
}
-
+
+ private static void setupDirectories(File file) {
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+ }
+
public static void main(String[] args) {
-
try {
- Class.forName(driver).newInstance();
- con = DriverManager.getConnection(host, username, password);
-
loadHandbookUseNames();
fetchDataOnMapleHandbook();
con.close();
- }
-
- catch(SQLException e) {
+ } catch (SQLException e) {
System.out.println("Error: invalid SQL syntax");
System.out.println(e.getMessage());
}
-
- catch(ClassNotFoundException e) {
- System.out.println("Error: could not find class");
- System.out.println(e.getMessage());
- }
-
- catch(InstantiationException | IllegalAccessException e) {
- System.out.println("Error: instantiation failure");
- System.out.println(e.getMessage());
- }
}
-
}
+
diff --git a/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java b/src/main/java/tools/mapletools/IdRetriever.java
similarity index 50%
rename from tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java
rename to src/main/java/tools/mapletools/IdRetriever.java
index e723de2ac0..58039bc0dc 100644
--- a/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java
+++ b/src/main/java/tools/mapletools/IdRetriever.java
@@ -1,86 +1,56 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package mapleidretriever;
+package tools.mapletools;
import java.io.*;
-import java.sql.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
import java.util.ArrayList;
/**
- *
* @author RonanLana
- *
+ *
* This application acts two-way: first section sets up a table on the SQL Server with all the names used within MapleStory,
* and the second queries all the names placed inside "fetch.txt", returning in the same line order the ids of the elements.
* In case of multiple entries with the same name, multiple ids will be returned in the same line split by a simple space
* in ascending order. An empty line means that no entry with the given name in a line has been found.
- *
+ *
* IMPORTANT: this will fail for fetching MAP ID (you shouldn't be using this program for these, just checking them up in the
* handbook is enough anyway).
- *
- * Set whether you are first installing the handbook on the SQL Server (TRUE) or just fetching whatever is on your "fetch.txt"
+ *
+ * Set whether you are first installing the handbook on the SQL Server (TRUE) or just fetching whatever is on your "fetch_ids.txt"
* file (FALSE) on the INSTALL_SQLTABLE property and build the project. With all done, run the Java executable.
- *
+ *
* Expected installing time: 30 minutes
- *
*/
-public class MapleIdRetriever {
- private final static boolean INSTALL_SQLTABLE = true;
-
- static String host = "jdbc:mysql://localhost:3306/cosmic";
- static String driver = "com.mysql.jdbc.Driver";
- static String username = "cosmic_server";
- static String password = "snailshell";
-
- static Connection con = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
- static PrintWriter printWriter = null;
-
- // ------- SET-UP section arguments --------
-
- static String directoryName = "./handbook/";
-
- // ------- SEARCH section arguments --------
-
- static String inputName = "lib/fetch.txt";
- static String outputName = "lib/result.txt";
-
- private static void listFiles(String directoryName, ArrayList files) {
- File directory = new File(directoryName);
+public class IdRetriever {
+ private static final boolean INSTALL_SQLTABLE = true;
+ private static final File INPUT_FILE = ToolConstants.getInputFile("fetch_ids.txt");
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("fetched_ids.txt");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
- // get all the files from a directory
- File[] fList = directory.listFiles();
- for (File file : fList) {
- if (file.isFile()) {
- files.add(file);
- } else if (file.isDirectory()) {
- listFiles(file.getAbsolutePath(), files);
- }
+ private static InputStreamReader fileReader = null;
+ private static BufferedReader bufferedReader = null;
+
+ private static void listFiles(String directoryName, ArrayList files) {
+ File directory = new File(directoryName);
+
+ // get all the files from a directory
+ File[] fList = directory.listFiles();
+ for (File file : fList) {
+ if (file.isFile()) {
+ files.add(file);
+ } else if (file.isDirectory()) {
+ listFiles(file.getAbsolutePath(), files);
}
+ }
}
-
+
private static void parseMapleHandbookLine(String line) throws SQLException {
String[] tokens = line.split(" - ", 3);
-
- if(tokens.length > 1) {
+
+ if (tokens.length > 1) {
PreparedStatement ps = con.prepareStatement("INSERT INTO `handbook` (`id`, `name`, `description`) VALUES (?, ?, ?)");
try {
ps.setInt(1, Integer.parseInt(tokens[0]));
@@ -91,135 +61,132 @@ public class MapleIdRetriever {
ps.setString(2, tokens[1]);
ps.setString(3, tokens.length > 2 ? tokens[2] : "");
ps.execute();
-
+
ps.close();
}
}
-
+
private static void parseMapleHandbookFile(File fileObj) throws SQLException {
+ if (shouldSkipParsingFile(fileObj.getName())) {
+ return;
+ }
+
String line;
-
+
try {
- fileReader = new InputStreamReader(new FileInputStream(fileObj), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(fileObj), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
System.out.println("Parsing file '" + fileObj.getCanonicalPath() + "'.");
- while((line = bufferedReader.readLine()) != null) {
- parseMapleHandbookLine(line);
+ while ((line = bufferedReader.readLine()) != null) {
+ try {
+ parseMapleHandbookLine(line);
+ } catch (SQLException e) {
+ System.err.println("Failed to parse line: " + line);
+ throw e;
+ }
}
bufferedReader.close();
fileReader.close();
- }
- catch(FileNotFoundException ex) {
- System.out.println(ex.getMessage());
- }
- catch(IOException ex) {
+ } catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
-
+
+ // Quest.txt has different formatting: id is last token on the line, instead of the first
+ private static boolean shouldSkipParsingFile(String fileName) {
+ return "Quest.txt".equals(fileName);
+ }
+
private static void setupSqlTable() throws SQLException {
PreparedStatement ps = con.prepareStatement("DROP TABLE IF EXISTS `handbook`;");
ps.execute();
ps.close();
-
+
ps = con.prepareStatement("CREATE TABLE `handbook` ("
+ "`key` int(10) unsigned NOT NULL AUTO_INCREMENT,"
+ "`id` int(10) DEFAULT NULL,"
+ "`name` varchar(200) DEFAULT NULL,"
+ "`description` varchar(1000) DEFAULT '',"
+ "PRIMARY KEY (`key`)"
- + ") ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;");
+ + ");");
ps.execute();
ps.close();
}
-
+
private static void parseMapleHandbook() throws SQLException {
ArrayList files = new ArrayList<>();
- listFiles(directoryName, files);
- if(files.isEmpty()) return;
+ listFiles(ToolConstants.HANDBOOK_PATH, files);
+ if (files.isEmpty()) {
+ return;
+ }
setupSqlTable();
- for(File f: files) {
+ for (File f : files) {
parseMapleHandbookFile(f);
}
}
-
+
private static void fetchDataOnMapleHandbook() throws SQLException {
String line;
-
+
try {
- fileReader = new InputStreamReader(new FileInputStream(inputName), "UTF-8");
+ fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
- printWriter = new PrintWriter(outputName, "UTF-8");
-
- while((line = bufferedReader.readLine()) != null) {
- if(line.isEmpty()) {
+
+ PrintWriter printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
+ while ((line = bufferedReader.readLine()) != null) {
+ if (line.isEmpty()) {
printWriter.println("");
continue;
}
-
- PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? COLLATE latin1_general_ci ORDER BY `id` ASC;");
+
+ PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? ORDER BY `id` ASC;");
ps.setString(1, line);
-
+
ResultSet rs = ps.executeQuery();
-
+
String str = "";
- while(rs.next()) {
+ while (rs.next()) {
int id = rs.getInt("id");
-
+
str += Integer.toString(id);
str += " ";
}
-
+
rs.close();
ps.close();
-
+
printWriter.println(str);
}
printWriter.close();
bufferedReader.close();
fileReader.close();
- }
- catch(FileNotFoundException ex) {
- System.out.println(ex.getMessage());
- }
- catch(IOException ex) {
+ } catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
-
- public static void main(String[] args) {
-
- try {
- Class.forName(driver).newInstance();
- con = DriverManager.getConnection(host, username, password);
- if(INSTALL_SQLTABLE) parseMapleHandbook();
- else fetchDataOnMapleHandbook();
+ public static void main(String[] args) {
+
+ try {
+ if (INSTALL_SQLTABLE) {
+ parseMapleHandbook();
+ } else {
+ fetchDataOnMapleHandbook();
+ }
con.close();
- }
-
- catch(SQLException e) {
+ } catch (SQLException e) {
System.out.println("Error: invalid SQL syntax");
- System.out.println(e.getMessage());
- }
-
- catch(ClassNotFoundException e) {
- System.out.println("Error: could not find class");
- System.out.println(e.getMessage());
- }
-
- catch(InstantiationException | IllegalAccessException e) {
- System.out.println("Error: instantiation failure");
- System.out.println(e.getMessage());
+ e.printStackTrace();
}
}
}
+
diff --git a/tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleMakerItemEntry.java b/src/main/java/tools/mapletools/MakerItemEntry.java
similarity index 85%
rename from tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleMakerItemEntry.java
rename to src/main/java/tools/mapletools/MakerItemEntry.java
index ae3df80725..c021bfb918 100644
--- a/tools/MapleSkillMakerFetcher/src/mapleskillmakerfetcher/MapleMakerItemEntry.java
+++ b/src/main/java/tools/mapletools/MakerItemEntry.java
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
-package mapleskillmakerfetcher;
+package tools.mapletools;
import java.util.List;
@@ -25,7 +25,7 @@ import java.util.List;
*
* @author RonanLana
*/
-public class MapleMakerItemEntry {
+public class MakerItemEntry {
public int id = -1;
public int itemid = -1;
public int reqLevel = -1;
@@ -43,7 +43,7 @@ public class MapleMakerItemEntry {
public List recipeList = null;
public List randomList = null;
- public MapleMakerItemEntry(int id, int itemid, int reqLevel, int reqMakerLevel, int reqItem, int reqMeso, int reqEquip, int catalyst, int quantity, int tuc, int recipeCount, int recipeItem, List recipeList, List randomList) {
+ MakerItemEntry(int id, int itemid, int reqLevel, int reqMakerLevel, int reqItem, int reqMeso, int reqEquip, int catalyst, int quantity, int tuc, int recipeCount, int recipeItem, List recipeList, List randomList) {
this.id = id;
this.itemid = itemid;
this.reqLevel = reqLevel;
diff --git a/tools/MapleMapFieldLimitChecker/src/maplemapfieldlimitchecker/MapleMapFieldLimitChecker.java b/src/main/java/tools/mapletools/MapFieldLimitChecker.java
similarity index 52%
rename from tools/MapleMapFieldLimitChecker/src/maplemapfieldlimitchecker/MapleMapFieldLimitChecker.java
rename to src/main/java/tools/mapletools/MapFieldLimitChecker.java
index 657ca2ebc4..da54249d97 100644
--- a/tools/MapleMapFieldLimitChecker/src/maplemapfieldlimitchecker/MapleMapFieldLimitChecker.java
+++ b/src/main/java/tools/mapletools/MapFieldLimitChecker.java
@@ -1,56 +1,25 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2018 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplemapfieldlimitchecker;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.io.PrintWriter;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
/**
- *
* @author RonanLana
- *
- This application seeks from the XMLs all mapid entries that holds the specified
- fieldLimit.
+ *
+ * This application seeks from the XMLs all mapid entries that holds the specified
+ * fieldLimit.
*/
-public class MapleMapFieldLimitChecker {
-
- static String newFile = "lib/Report.txt";
- static String outputWzPath = "lib";
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static String wzPath = "../../wz";
- static int initialStringLength = 50;
- static int itemFileNameSize = 13;
-
- static int fieldLimit = 0x400000;
-
- static byte status = 0;
- static int mapid = 0;
-
+public class MapFieldLimitChecker {
+ private static final int INITIAL_STRING_LENGTH = 50;
+ private static final int FIELD_LIMIT = 0x400000;
+
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int mapid = 0;
+
private static String getName(String token) {
int i, j;
char[] dest;
@@ -60,13 +29,13 @@ public class MapleMapFieldLimitChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static String getValue(String token) {
int i, j;
char[] dest;
@@ -76,35 +45,33 @@ public class MapleMapFieldLimitChecker {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- dest = new char[initialStringLength];
+ dest = new char[INITIAL_STRING_LENGTH];
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d.trim());
+ return (d.trim());
}
-
+
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
-
+
private static void listFiles(String directoryName, ArrayList files) {
File directory = new File(directoryName);
@@ -118,65 +85,62 @@ public class MapleMapFieldLimitChecker {
}
}
}
-
+
private static int getMapIdFromFilename(String name) {
try {
- return Integer.valueOf(name.substring(0, name.indexOf('.')));
- } catch(Exception e) {
+ return Integer.parseInt(name.substring(0, name.indexOf('.')));
+ } catch (Exception e) {
return -1;
}
}
-
+
private static void translateToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
-
+
if (status == 2) {
String d = getName(token);
if (!d.contentEquals("info")) {
forwardCursor(status);
}
}
- }
- else {
+ } else {
if (status == 2) {
String d = getName(token);
-
+
if (d.contentEquals("fieldLimit")) {
- int value = Integer.valueOf(getValue(token));
- if ((value & fieldLimit) == fieldLimit) {
+ int value = Integer.parseInt(getValue(token));
+ if ((value & FIELD_LIMIT) == FIELD_LIMIT) {
System.out.println(mapid + " " + value);
}
}
}
}
}
-
+
private static void inspectMapEntry() {
String line = null;
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-
+
private static void loadMapWz() throws IOException {
System.out.println("Reading Map.wz ...");
ArrayList files = new ArrayList<>();
- listFiles(wzPath + "/Map.wz/Map", files);
+ listFiles(WZFiles.MAP.getFilePath() + "/Map", files);
- for(File f : files) {
- fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
+ for (File f : files) {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
mapid = getMapIdFromFilename(f.getName());
inspectMapEntry();
@@ -184,7 +148,7 @@ public class MapleMapFieldLimitChecker {
fileReader.close();
}
}
-
+
public static void main(String[] args) {
try {
loadMapWz();
@@ -193,5 +157,4 @@ public class MapleMapFieldLimitChecker {
ioe.printStackTrace();
}
}
-
}
diff --git a/src/main/java/tools/mapletools/MapInfoRetriever.java b/src/main/java/tools/mapletools/MapInfoRetriever.java
new file mode 100644
index 0000000000..6c35a62a06
--- /dev/null
+++ b/src/main/java/tools/mapletools/MapInfoRetriever.java
@@ -0,0 +1,157 @@
+package tools.mapletools;
+
+import org.apache.commons.io.FileUtils;
+import provider.wz.WZFiles;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author RonanLana
+ *
+ * The main objective of this tool is to locate all mapids that doesn't have
+ * the "info" node in their WZ node tree.
+ */
+public class MapInfoRetriever {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("map_info_report.txt");
+ private static final List missingInfo = new ArrayList<>();
+
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static boolean hasInfo;
+
+ private static String getName(String token) {
+ int i, j;
+ char[] dest;
+ String d;
+
+ i = token.lastIndexOf("name");
+ i = token.indexOf("\"", i) + 1; //lower bound of the string
+ j = token.indexOf("\"", i); //upper bound
+
+ dest = new char[50];
+ token.getChars(i, j, dest, 0);
+
+ d = new String(dest);
+ return (d.trim());
+ }
+
+ private static void forwardCursor(int st) {
+ String line = null;
+
+ try {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
+ simpleToken(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void simpleToken(String token) {
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ status += 1;
+ }
+ }
+
+ private static boolean translateToken(String token) {
+ String d;
+ int temp;
+
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ if (status == 1) {
+ d = getName(token);
+ if (d.contains("info")) {
+ hasInfo = true;
+ return true;
+ }
+
+ temp = status;
+ forwardCursor(temp);
+ }
+
+ status += 1;
+ }
+
+ return false;
+ }
+
+ private static void searchMapDirectory(int mapArea) {
+ final File mapDirectory = new File(WZFiles.MAP.getFilePath() + "/Map/Map" + mapArea);
+ try {
+ Iterator iter = FileUtils.iterateFiles(mapDirectory, new String[]{"xml"}, true);
+ System.out.println("Parsing map area " + mapArea);
+
+ while (iter.hasNext()) {
+ File file = iter.next();
+ searchMapFile(file);
+ }
+ } catch (UncheckedIOException e) {
+ System.err.println("Directory " + mapDirectory.getPath() + " does not exist");
+ }
+ }
+
+ private static void searchMapFile(File file) {
+ // This will reference one line at a time
+ String line = null;
+
+ try {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(fileReader);
+
+ hasInfo = false;
+ status = 0;
+
+ while ((line = bufferedReader.readLine()) != null) {
+ if (translateToken(line)) {
+ break;
+ }
+ }
+
+ if (!hasInfo) {
+ missingInfo.add(Integer.valueOf(file.getName().split(".img.xml")[0]));
+ }
+
+ bufferedReader.close();
+ fileReader.close();
+ } catch (IOException ex) {
+ System.out.println("Error reading file '" + file.getName() + "'");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void writeReport() {
+ try {
+ PrintWriter printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
+ if (!missingInfo.isEmpty()) {
+ for (Integer i : missingInfo) {
+ printWriter.println(i);
+ }
+ } else {
+ printWriter.println("All map files contain 'info' node.");
+ }
+
+ printWriter.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i <= 9; i++) {
+ searchMapDirectory(i);
+ }
+ writeReport();
+ }
+
+}
+
diff --git a/tools/MapleMesoFetcher/src/maplemesofetcher/MapleMesoFetcher.java b/src/main/java/tools/mapletools/MesoFetcher.java
similarity index 57%
rename from tools/MapleMesoFetcher/src/maplemesofetcher/MapleMesoFetcher.java
rename to src/main/java/tools/mapletools/MesoFetcher.java
index 38fd2210d7..e6a98dba38 100644
--- a/tools/MapleMesoFetcher/src/maplemesofetcher/MapleMesoFetcher.java
+++ b/src/main/java/tools/mapletools/MesoFetcher.java
@@ -1,210 +1,184 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplemesofetcher;
-
-import life.MapleLifeFactory;
-import life.MapleMonsterStats;
+import server.life.MapleMonsterStats;
+import tools.Pair;
+import java.io.File;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
-
-import java.io.*;
-
import java.util.ArrayList;
-import java.util.List;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
-import tools.DatabaseConnection;
-import tools.Pair;
/**
- *
* @author RonanLana
- *
+ *
* This application traces missing meso drop data on the underlying DB (that must be
* defined on the DatabaseConnection file of this project) and generates a
* SQL file that proposes missing drop entries for the drop_data table.
- *
+ *
* The meso range is calculated accordingly with the target mob stats, such as level
* and if it's a boss or not, similarly as how it has been done for the actual meso
* drops.
- *
*/
-public class MapleMesoFetcher {
+public class MesoFetcher {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("meso_drop_data.sql");
+ private static final boolean PERMIT_MESOS_ON_DOJO_BOSSES = false;
+ private static final int MESO_ID = 0;
+ private static final int MIN_ITEMS = 4;
+ private static final int CHANCE = 400000;
+ private static final Map> mobRange = new HashMap<>();
private static PrintWriter printWriter;
- private static String newFile = "lib/meso_drop_data.sql";
-
- private static boolean permitMesosOnDojoBosses = false;
-
- private static int minItems = 4;
-
- private static int mesoid = 0;
- private static int chance = 400000;
-
private static Map mobStats;
- private static Map> mobRange = new HashMap<>();
-
+
private static Pair calcMesoRange90(int level, boolean boss) {
int minRange, maxRange;
-
+
// MIN range
- minRange = (int)(72.70814714 * Math.exp(0.02284640619 * level));
-
+ minRange = (int) (72.70814714 * Math.exp(0.02284640619 * level));
+
// MAX range
- maxRange = (int)(133.8194881 * Math.exp(0.02059225059 * level));
-
+ maxRange = (int) (133.8194881 * Math.exp(0.02059225059 * level));
+
// boss perks
- if(boss) {
+ if (boss) {
minRange *= 3;
maxRange *= 10;
}
-
+
return new Pair<>(minRange, maxRange);
}
-
+
private static Pair calcMesoRange(int level, boolean boss) {
int minRange, maxRange;
-
+
// MIN range
- minRange = (int)(30.32032228 * Math.exp(0.03281144930 * level));
-
+ minRange = (int) (30.32032228 * Math.exp(0.03281144930 * level));
+
// MAX range
- maxRange = (int)(44.45878459 * Math.exp(0.03289611686 * level));
-
+ maxRange = (int) (44.45878459 * Math.exp(0.03289611686 * level));
+
// boss perks
- if(boss) {
+ if (boss) {
minRange *= 3;
maxRange *= 10;
}
-
+
return new Pair<>(minRange, maxRange);
}
-
+
private static void calcAllMobsMesoRange() {
System.out.print("Calculating range... ");
-
- for(Entry mobStat : mobStats.entrySet()) {
+
+ for (Map.Entry mobStat : mobStats.entrySet()) {
MapleMonsterStats mms = mobStat.getValue();
Pair mesoRange;
-
- if(mms.getLevel() < 90) {
+
+ if (mms.getLevel() < 90) {
mesoRange = calcMesoRange(mms.getLevel(), mms.isBoss());
} else {
mesoRange = calcMesoRange90(mms.getLevel(), mms.isBoss());
}
-
+
mobRange.put(mobStat.getKey(), mesoRange);
}
-
+
System.out.println("done!");
}
-
+
private static void printSqlHeader() {
printWriter.println(" # SQL File autogenerated from the MapleMesoFetcher feature by Ronan Lana.");
printWriter.println(" # Generated data takes into account mob stats such as level and boss for the meso ranges.");
- printWriter.println(" # Only mobs with " + minItems + " or more items with no meso entry on the DB it was compiled are presented here.");
+ printWriter.println(" # Only mobs with " + MIN_ITEMS + " or more items with no meso entry on the DB it was compiled are presented here.");
printWriter.println();
-
+
printWriter.println(" INSERT IGNORE INTO drop_data (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`) VALUES");
}
-
+
private static void printSqlExceptions() {
- if(!permitMesosOnDojoBosses) {
- printWriter.println("\r\n DELETE FROM drop_data WHERE dropperid >= 9300184 AND dropperid <= 9300215 AND itemid = " + mesoid + ";");
+ if (!PERMIT_MESOS_ON_DOJO_BOSSES) {
+ printWriter.println("\r\n DELETE FROM drop_data WHERE dropperid >= 9300184 AND dropperid <= 9300215 AND itemid = " + MESO_ID + ";");
}
}
-
+
private static void printSqlMobMesoRange(int mobid) {
Pair mobmeso = mobRange.get(mobid);
- printWriter.println("(" + mobid + ", " + mesoid + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + chance + "),");
+ printWriter.println("(" + mobid + ", " + MESO_ID + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + CHANCE + "),");
}
-
+
private static void printSqlMobMesoRangeFinal(int mobid) {
Pair mobmeso = mobRange.get(mobid);
- printWriter.println("(" + mobid + ", " + mesoid + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + chance + ");");
+ printWriter.println("(" + mobid + ", " + MESO_ID + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + CHANCE + ");");
}
-
+
private static void generateMissingMobsMesoRange() {
System.out.print("Generating missing ranges... ");
- Connection con = DatabaseConnection.getConnection();
+ Connection con = SimpleDatabaseConnection.getConnection();
List existingMobs = new ArrayList<>(200);
-
+
try {
// select all mobs which doesn't drop mesos and have a fair amount of items dropping (meaning they are not an event mob)
- PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE dropperid NOT IN (SELECT DISTINCT dropperid FROM drop_data WHERE itemid = 0) GROUP BY dropperid HAVING count(*) >= " + minItems + ";");
+ PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE dropperid NOT IN (SELECT DISTINCT dropperid FROM drop_data WHERE itemid = 0) GROUP BY dropperid HAVING count(*) >= " + MIN_ITEMS + ";");
ResultSet rs = ps.executeQuery();
-
+
if (rs.isBeforeFirst()) {
- while(rs.next()) {
+ while (rs.next()) {
int mobid = rs.getInt(1);
-
- if(mobRange.containsKey(mobid)) {
+
+ if (mobRange.containsKey(mobid)) {
existingMobs.add(mobid);
}
}
-
- if(!existingMobs.isEmpty()) {
- printWriter = new PrintWriter(newFile, "UTF-8");
+
+ if (!existingMobs.isEmpty()) {
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
printSqlHeader();
-
- for(int i = 0; i < existingMobs.size() - 1; i++)
+
+ for (int i = 0; i < existingMobs.size() - 1; i++) {
printSqlMobMesoRange(existingMobs.get(i));
-
+ }
+
printSqlMobMesoRangeFinal(existingMobs.get(existingMobs.size() - 1));
-
+
printSqlExceptions();
-
+
printWriter.close();
} else {
throw new Exception("ALREADY UPDATED");
}
-
+
} else {
throw new Exception("ALREADY UPDATED");
}
-
+
rs.close();
ps.close();
con.close();
-
+
System.out.println("done!");
-
- } catch(Exception e) {
- if(e.getMessage() != null && e.getMessage().equals("ALREADY UPDATED")) {
+
+ } catch (Exception e) {
+ if (e.getMessage() != null && e.getMessage().equals("ALREADY UPDATED")) {
System.out.println("done! The DB is already up-to-date, no file generated.");
} else {
e.printStackTrace();
}
}
}
-
+
public static void main(String[] args) {
// load mob stats from WZ
- mobStats = MapleLifeFactory.getAllMonsterStats();
-
+ mobStats = MonsterStatFetcher.getAllMonsterStats();
+
calcAllMobsMesoRange();
generateMissingMobsMesoRange();
}
-
+
}
+
diff --git a/src/main/java/tools/mapletools/MobBookIndexer.java b/src/main/java/tools/mapletools/MobBookIndexer.java
new file mode 100644
index 0000000000..403b470430
--- /dev/null
+++ b/src/main/java/tools/mapletools/MobBookIndexer.java
@@ -0,0 +1,169 @@
+package tools.mapletools;
+
+import provider.wz.WZFiles;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * @author RonanLana
+ *
+ * This application simply gets from the MonsterBook.img.xml all mobid's and
+ * puts them on a SQL table with the correspondent mob cardid.
+ */
+public class MobBookIndexer {
+ private static final File INPUT_FILE = new File(WZFiles.STRING.getFile(), "MonsterBook.img.xml");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
+
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int mobId = -1;
+
+ private static String getName(String token) {
+ int i, j;
+ char[] dest;
+ String d;
+
+ i = token.lastIndexOf("name");
+ i = token.indexOf("\"", i) + 1; //lower bound of the string
+ j = token.indexOf("\"", i); //upper bound
+
+ if (j - i < 7) {
+ dest = new char[6];
+ } else {
+ dest = new char[7];
+ }
+ token.getChars(i, j, dest, 0);
+
+ d = new String(dest);
+ return (d);
+ }
+
+ private static void forwardCursor(int st) {
+ String line = null;
+
+ try {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
+ simpleToken(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void simpleToken(String token) {
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ status += 1;
+ }
+ }
+
+ private static boolean isCard(int itemId) {
+ return itemId / 10000 == 238;
+ }
+
+ private static void loadPairFromMob() {
+ System.out.println("Loading mob id " + mobId);
+
+ try {
+ PreparedStatement ps, ps2;
+ ResultSet rs;
+
+ ps = con.prepareStatement("SELECT itemid FROM drop_data WHERE (dropperid = ? AND itemid > 0) GROUP BY itemid;");
+ ps.setInt(1, mobId);
+ rs = ps.executeQuery();
+
+ while (rs.next()) {
+ int itemId = rs.getInt("itemid");
+ if (isCard(itemId)) {
+ ps2 = con.prepareStatement("INSERT INTO `monstercardwz` (`cardid`, `mobid`) VALUES (?, ?)");
+ ps2.setInt(1, itemId);
+ ps2.setInt(2, mobId);
+
+ ps2.executeUpdate();
+ }
+ }
+
+ rs.close();
+ ps.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void translateToken(String token) {
+ String d;
+ int temp;
+
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ if (status == 1) { //getting MobId
+ d = getName(token);
+ mobId = Integer.parseInt(d);
+ } else if (status == 2) {
+ d = getName(token);
+
+ if (d.contains("reward")) {
+ temp = status;
+
+ loadPairFromMob();
+ forwardCursor(temp);
+ }
+ }
+
+ status += 1;
+ }
+
+ }
+
+ private static void indexFromDropData() {
+ // This will reference one line at a time
+ String line = null;
+
+ try {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(fileReader);
+
+ PreparedStatement ps = con.prepareStatement("DROP TABLE IF EXISTS monstercardwz;");
+ ps.execute();
+
+ ps = con.prepareStatement("CREATE TABLE `monstercardwz` ("
+ + "`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
+ + "`cardid` int(10) NOT NULL DEFAULT '-1',"
+ + "`mobid` int(10) NOT NULL DEFAULT '-1',"
+ + "PRIMARY KEY (`id`)"
+ + ");");
+ ps.execute();
+
+ while ((line = bufferedReader.readLine()) != null) {
+ translateToken(line);
+ }
+
+ bufferedReader.close();
+ fileReader.close();
+
+ con.close();
+ } catch (FileNotFoundException ex) {
+ System.out.println("Unable to open file '" + INPUT_FILE + "'");
+ } catch (IOException ex) {
+ System.out.println("Error reading file '" + INPUT_FILE + "'");
+ } catch (SQLException e) {
+ System.out.println("Warning: Could not establish connection to database to change card chance rate.");
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ indexFromDropData();
+ }
+}
+
diff --git a/tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java b/src/main/java/tools/mapletools/MobBookUpdate.java
similarity index 52%
rename from tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java
rename to src/main/java/tools/mapletools/MobBookUpdate.java
index 158ce16788..fe5e28743b 100644
--- a/tools/MapleMobBookUpdate/src/maplemobbookupdate/MapleMobBookUpdate.java
+++ b/src/main/java/tools/mapletools/MobBookUpdate.java
@@ -1,65 +1,39 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplemobbookupdate;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
+import provider.wz.WZFiles;
import java.io.*;
-
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
/**
* @author RonanLana
- *
+ *
* This application updates the Monster Book drop data with the actual underlying drop data from
* the Maplestory database specified in the URL below.
- *
+ *
* In other words all items drops from monsters listed inside the Mob Book feature will be patched to match exactly like the item
* drop list specified in the URL's Maplestory database.
- *
+ *
* The original file "MonsterBook.img.xml" from String.wz must be copied to the directory of this application and only then
* executed. This program will generate another file that must replace the original server file to make the effects take place
* to on your server.
- *
+ *
* After replacing on server, this XML must be updated on the client via WZ Editor (HaRepack for instance). Once inside the repack,
* remove the property 'MonsterBook.img' inside 'string.wz' and choose to import the xml generated with this software.
- *
*/
-public class MapleMobBookUpdate {
- static String host = "jdbc:mysql://localhost:3306/cosmic";
- static String driver = "com.mysql.jdbc.Driver";
- static String username = "cosmic_server";
- static String password = "snailshell";
+public class MobBookUpdate {
+ private static final File INPUT_FILE = new File(WZFiles.STRING.getFile(), "MonsterBook.img.xml");
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("MonsterBook_updated.img.xml");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
- static String fileName = "lib/MonsterBook.img.xml";
- static String newFile = "lib/MonsterBook_updated.img.xml";
-
- static Connection con = null;
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
- static byte status = 0;
- static int mobId = -1;
+ private static PrintWriter printWriter = null;
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int mobId = -1;
private static String getName(String token) {
int i, j;
@@ -70,33 +44,36 @@ public class MapleMobBookUpdate {
i = token.indexOf("\"", i) + 1; //lower bound of the string
j = token.indexOf("\"", i); //upper bound
- if(j - i < 7) dest = new char[6];
- else dest = new char[7];
+ if (j - i < 7) {
+ dest = new char[6];
+ } else {
+ dest = new char[7];
+ }
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d);
+ return (d);
}
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- if(line != null) printWriter.println(line);
- }
- catch(Exception e) {
+ if (line != null) {
+ printWriter.println(line);
+ }
+ } catch (Exception e) {
e.printStackTrace();
}
}
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
@@ -112,9 +89,11 @@ public class MapleMobBookUpdate {
ps.setInt(1, mobId);
ResultSet rs = ps.executeQuery();
- while(rs.next()) {
+ while (rs.next()) {
toPrint = "";
- for(int k = 0; k <= status; k++) toPrint += " ";
+ for (int k = 0; k <= status; k++) {
+ toPrint += " ";
+ }
toPrint += "
-Matthias Butz
-Jan Christian Meyer
+package tools.mapletools;
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as
-published by the Free Software Foundation version 3 as published by
-the Free Software Foundation. You may not use, modify or distribute
-this program under any other version of the GNU Affero General Public
-License.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
- */
-package life;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import provider.MapleData;
-import provider.MapleDataDirectoryEntry;
-import provider.MapleDataFileEntry;
-import provider.MapleDataProvider;
-import provider.MapleDataProviderFactory;
-import provider.MapleDataTool;
+import provider.*;
import provider.wz.MapleDataType;
+import provider.wz.WZFiles;
+import server.life.Element;
+import server.life.ElementalEffectiveness;
+import server.life.MapleLifeFactory.BanishInfo;
+import server.life.MapleLifeFactory.loseItem;
+import server.life.MapleLifeFactory.selfDestruction;
+import server.life.MapleMonsterStats;
import tools.Pair;
-public class MapleLifeFactory {
- private static String wzPath = "../../wz";
- private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/Mob.wz"));
- private final static MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/String.wz"));
- private static MapleData mobStringData = stringDataWZ.getData("Mob.img");
- private static MapleData npcStringData = stringDataWZ.getData("Npc.img");
- private static Map monsterStats = new HashMap<>();
+import java.util.*;
- private static int getMonsterId(String fileName) {
- return Integer.parseInt(fileName.substring(0, 7));
- }
-
- public static Map getAllMonsterStats() {
+public class MonsterStatFetcher {
+ private static final MapleDataProvider data = MapleDataProviderFactory.getDataProvider(WZFiles.MOB);
+ private static final MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
+ private static final MapleData mobStringData = stringDataWZ.getData("Mob.img");
+ private static final Map monsterStats = new HashMap<>();
+
+ static Map getAllMonsterStats() {
MapleDataDirectoryEntry root = data.getRoot();
-
+
System.out.print("Parsing mob stats... ");
for (MapleDataFileEntry mFile : root.getFiles()) {
try {
String fileName = mFile.getName();
-
+
//System.out.println("Parsing '" + fileName + "'");
MapleData monsterData = data.getData(fileName);
if (monsterData == null) {
continue;
}
-
+
Integer mid = getMonsterId(fileName);
-
+
MapleData monsterInfoData = monsterData.getChildByPath("info");
MapleMonsterStats stats = new MapleMonsterStats();
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
@@ -71,7 +42,7 @@ public class MapleLifeFactory {
stats.setPADamage(MapleDataTool.getIntConvert("PADamage", monsterInfoData));
stats.setPDDamage(MapleDataTool.getIntConvert("PDDamage", monsterInfoData));
stats.setMADamage(MapleDataTool.getIntConvert("MADamage", monsterInfoData));
- stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
+ stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
stats.setExp(MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
stats.setLevel(MapleDataTool.getIntConvert("level", monsterInfoData));
@@ -139,7 +110,7 @@ public class MapleLifeFactory {
int i = 0;
List> skills = new ArrayList<>();
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
- skills.add(new Pair<>(Integer.valueOf(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0)), Integer.valueOf(MapleDataTool.getInt(i + "/level", monsterSkillData, 0))));
+ skills.add(new Pair<>(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0), MapleDataTool.getInt(i + "/level", monsterSkillData, 0)));
i++;
}
stats.setSkills(skills);
@@ -148,93 +119,25 @@ public class MapleLifeFactory {
if (banishData != null) {
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
}
-
+
monsterStats.put(mid, stats);
} catch(NullPointerException npe) {
//System.out.println("[SEVERE] " + mFile.getName() + " failed to load. Issue: " + npe.getMessage() + "\n\n");
}
}
-
- System.out.println("done!");
+
+ System.out.println("Done parsing mob stats!");
return monsterStats;
}
+ private static int getMonsterId(String fileName) {
+ return Integer.parseInt(fileName.substring(0, 7));
+ }
+
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
for (int i = 0; i < elemAttr.length(); i += 2) {
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
}
}
- public static class BanishInfo {
-
- private int map;
- private String portal, msg;
-
- public BanishInfo(String msg, int map, String portal) {
- this.msg = msg;
- this.map = map;
- this.portal = portal;
- }
-
- public int getMap() {
- return map;
- }
-
- public String getPortal() {
- return portal;
- }
-
- public String getMsg() {
- return msg;
- }
- }
-
- public static class loseItem {
-
- private int id;
- private byte chance, x;
-
- private loseItem(int id, byte chance, byte x) {
- this.id = id;
- this.chance = chance;
- this.x = x;
- }
-
- public int getId() {
- return id;
- }
-
- public byte getChance() {
- return chance;
- }
-
- public byte getX() {
- return x;
- }
- }
-
- public static class selfDestruction {
-
- private byte action;
- private int removeAfter;
- private int hp;
-
- private selfDestruction(byte action, int removeAfter, int hp) {
- this.action = action;
- this.removeAfter = removeAfter;
- this.hp = hp;
- }
-
- public int getHp() {
- return hp;
- }
-
- public byte getAction() {
- return action;
- }
-
- public int removeAfter() {
- return removeAfter;
- }
- }
}
diff --git a/tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java b/src/main/java/tools/mapletools/NoItemIdFetcher.java
similarity index 55%
rename from tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java
rename to src/main/java/tools/mapletools/NoItemIdFetcher.java
index 1647758035..602d5420c2 100644
--- a/tools/MapleInvalidItemIdFetcher/src/maplenoitemidfetcher/MapleNoItemIdFetcher.java
+++ b/src/main/java/tools/mapletools/NoItemIdFetcher.java
@@ -1,70 +1,35 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplenoitemidfetcher;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.sql.Connection;
-import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
/**
- *
* @author RonanLana
- *
+ *
* This application finds inexistent itemids within the drop data from
* the Maplestory database specified in the URL below. This program
* assumes all itemids uses 7 digits.
- *
+ *
* A file is generated listing all the inexistent ids.
*/
-public class MapleNoItemIdFetcher {
- static String host = "jdbc:mysql://localhost:3306/cosmic";
- static String driver = "com.mysql.jdbc.Driver";
- static String username = "cosmic_server";
- static String password = "snailshell";
+public class NoItemIdFetcher {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("no_item_id_report.txt");
+ private static final Connection con = SimpleDatabaseConnection.getConnection();
- static String wzPath = "../../wz";
- static String newFile = "lib/result.txt";
+ private static final Set existingIds = new HashSet<>();
+ private static final Set nonExistingIds = new HashSet<>();
- static Connection con = null;
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
- static byte status = 0;
- static int itemId = -1;
-
- static Set existingIds = new HashSet<>();
- static Set nonExistingIds = new HashSet<>();
+ private static PrintWriter printWriter = null;
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int itemId = -1;
private static String getName(String token) {
int i, j;
@@ -79,42 +44,39 @@ public class MapleNoItemIdFetcher {
token.getChars(i, j, dest, 0);
d = new String(dest);
- return(d);
+ return (d);
}
private static void forwardCursor(int st) {
String line = null;
try {
- while(status >= st && (line = bufferedReader.readLine()) != null) {
+ while (status >= st && (line = bufferedReader.readLine()) != null) {
simpleToken(line);
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
private static void simpleToken(String token) {
- if(token.contains("/imgdir")) {
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
+ } else if (token.contains("imgdir")) {
status += 1;
}
}
private static void translateToken(String token) {
String d;
-
- if(token.contains("/imgdir")) {
+
+ if (token.contains("/imgdir")) {
status -= 1;
- }
- else if(token.contains("imgdir")) {
- if(status == 1) { //getting ItemId
+ } else if (token.contains("imgdir")) {
+ if (status == 1) { //getting ItemId
d = getName(token);
itemId = Integer.parseInt(d.substring(1, 8));
-
+
existingIds.add(itemId);
forwardCursor(status);
}
@@ -127,36 +89,34 @@ public class MapleNoItemIdFetcher {
// This will reference one line at a time
String line = null;
- try {
- fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
+ try {
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
bufferedReader = new BufferedReader(fileReader);
-
+
status = 0;
try {
- while((line = bufferedReader.readLine()) != null) {
+ while ((line = bufferedReader.readLine()) != null) {
translateToken(line);
}
- } catch(NumberFormatException npe) {
+ } catch (NumberFormatException npe) {
// second criteria, itemid is on the name of the file
-
+
try {
itemId = Integer.parseInt(file.getName().substring(0, 7));
existingIds.add(itemId);
- } catch(NumberFormatException npe2) {}
+ } catch (NumberFormatException npe2) {
+ }
}
bufferedReader.close();
fileReader.close();
- }
-
- catch(FileNotFoundException ex) {
+ } catch (FileNotFoundException ex) {
System.out.println("Unable to open file '" + file.getName() + "'");
- }
- catch(IOException ex) {
+ } catch (IOException ex) {
System.out.println("Error reading file '" + file.getName() + "'");
}
}
-
+
private static void readEquipDataDirectory(String dirPath) {
File[] folders = new File(dirPath).listFiles();
//If this pathname does not denote a directory, then listFiles() returns null.
@@ -164,21 +124,22 @@ public class MapleNoItemIdFetcher {
for (File folder : folders) { // enter all subfolders
if (folder.isDirectory()) {
System.out.println("Reading '" + dirPath + "/" + folder.getName() + "'...");
-
+
try {
File[] files = folder.listFiles();
-
+
for (File file : files) { // enter all XML files under subfolders
if (file.isFile()) {
itemId = Integer.parseInt(file.getName().substring(0, 8));
existingIds.add(itemId);
}
}
- } catch (NumberFormatException nfe) {}
+ } catch (NumberFormatException nfe) {
+ }
}
}
}
-
+
private static void readItemDataDirectory(String dirPath) {
File[] folders = new File(dirPath).listFiles();
//If this pathname does not denote a directory, then listFiles() returns null.
@@ -186,9 +147,9 @@ public class MapleNoItemIdFetcher {
for (File folder : folders) { // enter all subfolders
if (folder.isDirectory()) {
System.out.println("Reading '" + dirPath + "/" + folder.getName() + "'...");
-
+
File[] files = folder.listFiles();
-
+
for (File file : files) { // enter all XML files under subfolders
if (file.isFile()) {
readItemDataFile(file);
@@ -197,13 +158,13 @@ public class MapleNoItemIdFetcher {
}
}
}
-
+
private static void evaluateDropsFromTable(String table) throws SQLException {
PreparedStatement ps = con.prepareStatement("SELECT DISTINCT itemid FROM " + table + ";");
ResultSet rs = ps.executeQuery();
- while(rs.next()) {
- if(!existingIds.contains(rs.getInt(1))) {
+ while (rs.next()) {
+ if (!existingIds.contains(rs.getInt(1))) {
nonExistingIds.add(rs.getInt(1));
}
}
@@ -211,64 +172,45 @@ public class MapleNoItemIdFetcher {
rs.close();
ps.close();
}
-
+
private static void evaluateDropsFromDb() {
try {
System.out.println("Evaluating item data on DB...");
-
- Class.forName(driver).newInstance();
- con = DriverManager.getConnection(host, username, password);
-
+
evaluateDropsFromTable("drop_data");
evaluateDropsFromTable("reactordrops");
-
- if(!nonExistingIds.isEmpty()) {
+
+ if (!nonExistingIds.isEmpty()) {
List list = new ArrayList<>(nonExistingIds);
Collections.sort(list);
-
- for(Integer i : list) {
+
+ for (Integer i : list) {
printWriter.println(i);
}
}
-
+
System.out.println("Inexistent itemid count: " + nonExistingIds.size());
System.out.println("Total itemid count: " + existingIds.size());
-
- con.close();
- }
-
- catch(ClassNotFoundException e) {
- System.out.println("Error: could not find class");
- System.out.println(e.getMessage());
- }
- catch(InstantiationException e) {
- System.out.println("Error: instantiation failure");
- System.out.println(e.getMessage());
- }
-
- catch(SQLException e) {
- e.printStackTrace();
- }
-
- catch(Exception e) {
+ con.close();
+ } catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
- printWriter = new PrintWriter(newFile, "UTF-8");
-
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
existingIds.add(0); // meso itemid
- readEquipDataDirectory(wzPath + "/Character.wz");
- readItemDataDirectory(wzPath + "/Item.wz");
-
+ readEquipDataDirectory(WZFiles.CHARACTER.getFilePath());
+ readItemDataDirectory(WZFiles.ITEM.getFilePath());
+
evaluateDropsFromDb();
-
+
printWriter.close();
- } catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
}
-}
+}
\ No newline at end of file
diff --git a/tools/MapleInvalidItemWithNoNameFetcher/src/maplenoitemnamefetcher/MapleNoItemNameFetcher.java b/src/main/java/tools/mapletools/NoItemNameFetcher.java
similarity index 59%
rename from tools/MapleInvalidItemWithNoNameFetcher/src/maplenoitemnamefetcher/MapleNoItemNameFetcher.java
rename to src/main/java/tools/mapletools/NoItemNameFetcher.java
index b47047b256..d1f44bb939 100644
--- a/tools/MapleInvalidItemWithNoNameFetcher/src/maplenoitemnamefetcher/MapleNoItemNameFetcher.java
+++ b/src/main/java/tools/mapletools/NoItemNameFetcher.java
@@ -1,89 +1,51 @@
-/*
- This file is part of the HeavenMS MapleStory Server
- Copyleft (L) 2016 - 2019 RonanLana
+package tools.mapletools;
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation version 3 as published by
- the Free Software Foundation. You may not use, modify or distribute
- this program under any other version of the GNU Affero General Public
- License.
+import provider.*;
+import provider.wz.WZFiles;
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-package maplenoitemnamefetcher;
-
-import java.io.BufferedReader;
import java.io.File;
-import java.io.InputStreamReader;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import provider.MapleData;
-import provider.MapleDataDirectoryEntry;
-import provider.MapleDataFileEntry;
-import provider.MapleDataProvider;
-import provider.MapleDataProviderFactory;
-import provider.MapleDataTool;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
/**
- *
* @author RonanLana
- *
+ *
* This application finds itemids with inexistent name and description from
* within the server-side XMLs, then identify them on a report file along
* with a XML excerpt to be appended on the String.wz xml nodes. This program
* assumes all equipids are depicted using 8 digits and item using 7 digits.
- *
+ *
* Estimated parse time: 2 minutes
*/
-public class MapleNoItemNameFetcher {
- static String wzPath = "../../wz";
- static String newFile = "lib/result.txt";
- static String xmlFile = "lib/output.txt";
+public class NoItemNameFetcher {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("no_item_name_result.txt");
+ private static final File OUTPUT_XML_FILE = ToolConstants.getOutputFile("no_item_name_xml.txt");
- static PrintWriter printWriter = null;
- static InputStreamReader fileReader = null;
- static BufferedReader bufferedReader = null;
-
- static Map itemsWzPath = new HashMap<>();
- static Map