diff --git a/src/main/java/tools/mapletools/QuestMesoFetcher.java b/src/main/java/tools/mapletools/QuestMesoFetcher.java
new file mode 100644
index 0000000000..4bf1a8da95
--- /dev/null
+++ b/src/main/java/tools/mapletools/QuestMesoFetcher.java
@@ -0,0 +1,263 @@
+package tools.mapletools;
+
+import provider.wz.WZFiles;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * @author RonanLana
+ *
+ * This application parses the Quest.wz file inputted and generates a report showing
+ * all cases where a quest takes a meso fee to complete a quest, but it doesn't
+ * properly checks the player for the needed amount before completing it.
+ *
+ * Running it should generate a report file under "output" folder with the search results.
+ */
+public class QuestMesoFetcher {
+ private static final File OUTPUT_FILE = ToolConstants.getOutputFile("quest_meso_report.txt");
+ private static final boolean PRINT_FEES = true; // print missing values as additional info report
+ private static final int INITIAL_STRING_LENGTH = 50;
+
+ private static final Map checkedMesoQuests = new HashMap<>();
+ private static final Map appliedMesoQuests = new HashMap<>();
+ private static final Set checkedEndscriptQuests = new HashSet<>();
+
+ private static PrintWriter printWriter = null;
+ private static BufferedReader bufferedReader = null;
+ private static byte status = 0;
+ private static int questId = -1;
+ private static int isCompleteState = 0;
+ private static int currentMeso = 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
+
+ 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 translateTokenAct(String token) {
+ String d;
+
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ if (status == 1) { //getting QuestId
+ d = getName(token);
+ questId = Integer.parseInt(d);
+ } else if (status == 2) { //start/complete
+ d = getName(token);
+ isCompleteState = Integer.parseInt(d);
+ } else if (status == 3) {
+ forwardCursor(status);
+ }
+
+ status += 1;
+ } else {
+ if (token.contains("money")) {
+ if (isCompleteState != 0) {
+ d = getValue(token);
+
+ currentMeso = -1 * Integer.parseInt(d);
+
+ if (currentMeso > 0) {
+ appliedMesoQuests.put(questId, currentMeso);
+ }
+ }
+ }
+ }
+ }
+
+ private static void translateTokenCheck(String token) {
+ String d;
+
+ if (token.contains("/imgdir")) {
+ status -= 1;
+ } else if (token.contains("imgdir")) {
+ if (status == 1) { //getting QuestId
+ d = getName(token);
+ questId = Integer.parseInt(d);
+ } else if (status == 2) { //start/complete
+ d = getName(token);
+ isCompleteState = Integer.parseInt(d);
+ } else if (status == 3) {
+ forwardCursor(status);
+ }
+
+ status += 1;
+ } else {
+ if (token.contains("endmeso")) {
+ d = getValue(token);
+ currentMeso = Integer.parseInt(d);
+
+ checkedMesoQuests.put(questId, currentMeso);
+ } else if (token.contains("endscript")) {
+ checkedEndscriptQuests.add(questId);
+ }
+ }
+ }
+
+ private static void readQuestMesoData() throws IOException {
+ String line;
+
+ InputStreamReader fileReader = new InputStreamReader(new FileInputStream(WZFiles.QUEST.getFilePath() + "/Act.img.xml"), StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(fileReader);
+
+ while ((line = bufferedReader.readLine()) != null) {
+ translateTokenAct(line);
+ }
+
+ bufferedReader.close();
+ fileReader.close();
+
+ fileReader = new InputStreamReader(new FileInputStream(WZFiles.QUEST.getFilePath() + "/Check.img.xml"), StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(fileReader);
+
+ while ((line = bufferedReader.readLine()) != null) {
+ translateTokenCheck(line);
+ }
+
+ bufferedReader.close();
+ fileReader.close();
+ }
+
+ private static void printReportFileHeader() {
+ printWriter.println(" # Report File autogenerated from the MapleQuestMesoFetcher 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 printReportFileResults(Map target, Map base, boolean testingCheck) {
+ List result = new ArrayList<>();
+ List error = new ArrayList<>();
+
+ Map questFee = new HashMap<>();
+
+ for (Map.Entry e : base.entrySet()) {
+ Integer v = target.get(e.getKey());
+
+ if (v == null) {
+ if (testingCheck || !checkedEndscriptQuests.contains(e.getKey())) {
+ result.add(e.getKey());
+ questFee.put(e.getKey(), e.getValue());
+ }
+ } else if (v.intValue() != e.getValue().intValue()) {
+ error.add(e.getKey());
+ }
+ }
+
+ if (!result.isEmpty() || !error.isEmpty()) {
+ printWriter.println("MISMATCH INFORMATION ON '" + (testingCheck ? "check" : "act") + "':");
+ if (!result.isEmpty()) {
+ result.sort((o1, o2) -> o1 - o2);
+
+ printWriter.println("# MISSING");
+
+ if (!PRINT_FEES) {
+ for (Integer i : result) {
+ printWriter.println(i);
+ }
+ } else {
+ for (Integer i : result) {
+ printWriter.println(i + " " + questFee.get(i));
+ }
+ }
+
+ printWriter.println();
+ }
+
+ if (!error.isEmpty() && testingCheck) {
+ error.sort((o1, o2) -> o1 - o2);
+
+ printWriter.println("# WRONG VALUE");
+
+ for (Integer i : error) {
+ printWriter.println(i);
+ }
+
+ printWriter.println();
+ }
+
+ printWriter.println("\r\n");
+ }
+ }
+
+ private static void reportQuestMesoData() {
+ // This will reference one line at a time
+
+ try {
+ System.out.println("Reading WZs...");
+ readQuestMesoData();
+
+ System.out.println("Reporting results...");
+ // report missing meso checks on quest completes
+ printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
+
+ printReportFileHeader();
+
+ printReportFileResults(checkedMesoQuests, appliedMesoQuests, true);
+ printReportFileResults(appliedMesoQuests, checkedMesoQuests, false);
+
+ printWriter.close();
+ System.out.println("Done!");
+ } catch (FileNotFoundException ex) {
+ System.out.println("Unable to open quest file.");
+ } catch (IOException ex) {
+ System.out.println("Error reading quest file.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ reportQuestMesoData();
+ }
+}
+
diff --git a/tools/MapleQuestMesoFetcher/lib/QuestReport.txt b/tools/MapleQuestMesoFetcher/lib/QuestReport.txt
deleted file mode 100644
index a72a1d58cd..0000000000
--- a/tools/MapleQuestMesoFetcher/lib/QuestReport.txt
+++ /dev/null
@@ -1,42 +0,0 @@
- # Report File autogenerated from the MapleQuestMesoFetcher feature by Ronan Lana.
- # Generated data takes into account several data info from the server-side WZ.xmls.
-
-MISMATCH INFORMATION ON 'check':
-# MISSING
-2215 2000
-3046 10000
-3048 20000
-3069 10000
-3079 300000
-3095 10000
-3305 10000
-3306 10000
-3377 20000
-3612 1000
-3613 1000
-3614 1000
-3623 5000
-5009 50
-5010 50
-5011 50
-5012 50
-6000 1000000
-8078 1000000
-8079 5000000
-8207 2500
-9310 1000
-9311 2500
-9340 1000
-9341 2500
-20504 10000000
-20511 25000000
-20512 15000000
-20532 50000000
-20534 100000000
-21605 20000000
-21606 10000000
-21611 80000000
-21617 100000000
-
-
-
diff --git a/tools/MapleQuestMesoFetcher/src/maplequestmesofetcher/MapleQuestMesoFetcher.java b/tools/MapleQuestMesoFetcher/src/maplequestmesofetcher/MapleQuestMesoFetcher.java
deleted file mode 100644
index 28b039024f..0000000000
--- a/tools/MapleQuestMesoFetcher/src/maplequestmesofetcher/MapleQuestMesoFetcher.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- 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 maplequestmesofetcher;
-
-import java.io.*;
-import java.sql.Connection;
-import java.util.*;
-import java.util.Map.Entry;
-
-/**
- *
- * @author RonanLana
-
- This application parses the Quest.wz file inputted and generates a report showing
- all cases where a quest takes a meso fee to complete a quest, but it doesn't
- properly checks the player for the needed amount before completing it.
-
- Running it should generate a report file under "lib" folder with the search results.
-
- */
-public class MapleQuestMesoFetcher {
- static boolean printFees = true; // print missing values as additional info report
-
- static String actName = "../../wz/Quest.wz/Act.img.xml";
- static String checkName = "../../wz/Quest.wz/Check.img.xml";
- static String directoryName = "../..";
- static String newFile = "lib/QuestReport.txt";
-
- 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 byte status = 0;
- static int questId = -1;
- static int isCompleteState = 0;
-
- static int currentMeso = 0;
-
- static Map checkedMesoQuests = new HashMap<>();
- static Map appliedMesoQuests = new HashMap<>();
- static Set checkedEndscriptQuests = new HashSet<>();
-
- 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];
- 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[initialStringLength];
- 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 translateTokenAct(String token) {
- String d;
-
- if(token.contains("/imgdir")) {
- status -= 1;
- }
- else if(token.contains("imgdir")) {
- if(status == 1) { //getting QuestId
- d = getName(token);
- questId = Integer.parseInt(d);
- }
- else if(status == 2) { //start/complete
- d = getName(token);
- isCompleteState = Integer.parseInt(d);
- }
- else if(status == 3) {
- forwardCursor(status);
- }
-
- status += 1;
- }
- else {
- if(token.contains("money")) {
- if(isCompleteState != 0) {
- d = getValue(token);
-
- currentMeso = -1 * Integer.valueOf(d);
-
- if(currentMeso > 0) {
- appliedMesoQuests.put(questId, currentMeso);
- }
- }
- }
- }
- }
-
- private static void translateTokenCheck(String token) {
- String d;
-
- if(token.contains("/imgdir")) {
- status -= 1;
- }
- else if(token.contains("imgdir")) {
- if(status == 1) { //getting QuestId
- d = getName(token);
- questId = Integer.parseInt(d);
- }
- else if(status == 2) { //start/complete
- d = getName(token);
- isCompleteState = Integer.parseInt(d);
- }
- else if(status == 3) {
- forwardCursor(status);
- }
-
- status += 1;
- }
- else {
- if(token.contains("endmeso")) {
- d = getValue(token);
- currentMeso = Integer.valueOf(d);
-
- checkedMesoQuests.put(questId, currentMeso);
- } else if(token.contains("endscript")) {
- checkedEndscriptQuests.add(questId);
- }
- }
- }
-
- private static void readQuestMesoData() throws IOException {
- String line;
-
- fileReader = new InputStreamReader(new FileInputStream(actName), "UTF-8");
- bufferedReader = new BufferedReader(fileReader);
-
- while((line = bufferedReader.readLine()) != null) {
- translateTokenAct(line);
- }
-
- bufferedReader.close();
- fileReader.close();
-
- fileReader = new InputStreamReader(new FileInputStream(checkName), "UTF-8");
- bufferedReader = new BufferedReader(fileReader);
-
- while((line = bufferedReader.readLine()) != null) {
- translateTokenCheck(line);
- }
-
- bufferedReader.close();
- fileReader.close();
- }
-
- private static void printReportFileHeader() {
- printWriter.println(" # Report File autogenerated from the MapleQuestMesoFetcher 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 printReportFileResults(Map target, Map base, boolean testingCheck) {
- List result = new ArrayList<>();
- List error = new ArrayList<>();
-
- Map questFee = new HashMap<>();
-
- for(Entry e : base.entrySet()) {
- Integer v = target.get(e.getKey());
-
- if(v == null) {
- if(testingCheck || !checkedEndscriptQuests.contains(e.getKey())) {
- result.add(e.getKey());
- questFee.put(e.getKey(), e.getValue());
- }
- } else if(v.intValue() != e.getValue().intValue()) {
- error.add(e.getKey());
- }
- }
-
- if(!result.isEmpty() || !error.isEmpty()) {
- printWriter.println("MISMATCH INFORMATION ON '" + (testingCheck ? "check" : "act") + "':");
- if(!result.isEmpty()) {
- Collections.sort(result, (o1, o2) -> o1 - o2);
-
- printWriter.println("# MISSING");
-
- if(!printFees) {
- for(Integer i : result) {
- printWriter.println(i);
- }
- } else {
- for(Integer i : result) {
- printWriter.println(i + " " + questFee.get(i));
- }
- }
-
- printWriter.println();
- }
-
- if(!error.isEmpty() && testingCheck) {
- Collections.sort(error, (o1, o2) -> o1 - o2);
-
- printWriter.println("# WRONG VALUE");
-
- for(Integer i : error) {
- printWriter.println(i);
- }
-
- printWriter.println();
- }
-
- printWriter.println("\r\n");
- }
- }
-
- private static void ReportQuestMesoData() {
- // This will reference one line at a time
-
- try {
- System.out.println("Reading WZs...");
- readQuestMesoData();
-
- System.out.println("Reporting results...");
- // report missing meso checks on quest completes
- printWriter = new PrintWriter(newFile, "UTF-8");
-
- printReportFileHeader();
-
- printReportFileResults(checkedMesoQuests, appliedMesoQuests, true);
- printReportFileResults(appliedMesoQuests, checkedMesoQuests, false);
-
- printWriter.close();
- System.out.println("Done!");
- }
-
- catch(FileNotFoundException ex) {
- System.out.println("Unable to open quest file.");
- }
- catch(IOException ex) {
- System.out.println("Error reading quest file.");
- }
-
- catch(Exception e) {
- e.printStackTrace();
- }
- }
-
- public static void main(String[] args) {
- ReportQuestMesoData();
- }
-
-}