diff --git a/src/main/java/provider/wz/WZFiles.java b/src/main/java/provider/wz/WZFiles.java
index 94b07e668c..e5073d0058 100644
--- a/src/main/java/provider/wz/WZFiles.java
+++ b/src/main/java/provider/wz/WZFiles.java
@@ -21,15 +21,15 @@ public enum WZFiles {
private final String fileName;
- WZFiles(String fileName) {
- this.fileName = fileName;
+ WZFiles(String name) {
+ this.fileName = name + ".wz";
}
public File getFile() {
- return new File(getFilePath());
+ return new File(DIRECTORY, fileName);
}
public String getFilePath() {
- return String.format("%s/%s.wz", DIRECTORY, fileName);
+ return getFile().getPath();
}
}
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..8a19bc919d 100644
--- a/tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/MapleCashCosmeticsChecker.java
+++ b/src/main/java/tools/mapletools/CashCosmeticsChecker.java
@@ -1,77 +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.
-
- 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 HANDBOOK_PATH = "handbook";
+ private static final String SCRIPTS_PATH = "scripts";
+ 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 +55,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 +71,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 +153,7 @@ public class MapleCashCosmeticsChecker {
unusedCosmetics.add(cosmeticid);
}
}
-
+
private static void listFiles(String directoryName, ArrayList files) {
File directory = new File(directoryName);
@@ -196,60 +167,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(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 +228,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 +248,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 +324,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 +351,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 +362,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 +447,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 +455,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 +473,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 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 +497,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 +528,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 +541,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 +576,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 +597,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 +608,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/src/main/java/tools/mapletools/ToolConstants.java b/src/main/java/tools/mapletools/ToolConstants.java
index aa097172cf..f5f4fb9b34 100644
--- a/src/main/java/tools/mapletools/ToolConstants.java
+++ b/src/main/java/tools/mapletools/ToolConstants.java
@@ -6,6 +6,10 @@ public class ToolConstants {
public static final File INPUT_DIRECTORY = new File("tools/input");
public static final File OUTPUT_DIRECTORY = new File("tools/output");
+ public static File getInputFile(String fileName) {
+ return new File(INPUT_DIRECTORY, fileName);
+ }
+
public static File getOutputFile(String fileName) {
return new File(OUTPUT_DIRECTORY, fileName);
}
diff --git a/tools/MapleCashCosmeticsChecker/lib/result.txt b/tools/MapleCashCosmeticsChecker/lib/result.txt
deleted file mode 100644
index 60ce233efb..0000000000
--- a/tools/MapleCashCosmeticsChecker/lib/result.txt
+++ /dev/null
@@ -1,213 +0,0 @@
- # Report File autogenerated from the MapleCashCosmeticsChecker feature by Ronan Lana.
- # Generated data takes into account several data info from the server source files and the server-side WZ.xmls.
-
-Found 42 entries with missing cosmetic entries.
- NPC 1012103:VIP
- 30060, 30140, 30200, 30210, 30310, 33040, 33100
- 31150, 31300, 31350, 31700, 31740, 34050, 34110
-
- NPC 1012104:EXP
- 30030, 30140, 30200, 30210, 30310, 30610, 33040, 33100
- 31070, 31150, 31300, 31350, 31430, 31700, 34050, 34110
-
- NPC 1012104:REG
- 30060, 30140, 30200, 30210, 30310, 30610, 33040, 33100
- 31070, 31080, 31150, 31300, 31350, 31700, 34050, 34110
-
- NPC 1052004:VIP
- 20000, 20001, 20003, 20004, 20005, 20006, 20007, 20008, 20012, 20014, 20015, 20022, 20028, 20031
- 21000, 21001, 21002, 21003, 21004, 21005, 21006, 21007, 21008, 21012, 21013, 21014, 21023, 21026
-
- NPC 1052005:REG
- 20000, 20005, 20008, 20012, 20016, 20022, 20032
- 21000, 21002, 21008, 21014, 21020, 21024, 21029
-
- NPC 1052100:VIP
- 30040, 30130, 30780, 30850, 30860, 30920, 33040
- 31090, 31140, 31330, 31440, 31760, 31880, 34050
-
- NPC 1052101:EXP
- 30130, 30430, 30520, 30770, 30780, 30850, 30920, 33040
- 31060, 31140, 31330, 31520, 31760, 31880, 34010, 34050
-
- NPC 1052101:REG
- 30040, 30130, 30520, 30770, 30780, 30850, 30920, 33040
- 31060, 31140, 31330, 31440, 31520, 31750, 31760, 31880, 34050
-
- NPC 2010001:VIP
- 30230, 30260, 30280, 30340, 30490
- 31110, 31220, 31230, 31630, 31790
-
- NPC 2010002:VIP
- 20000, 20001, 20003, 20004, 20005, 20006, 20007, 20008, 20012, 20014, 20022, 20028, 20031
- 21000, 21001, 21002, 21003, 21004, 21005, 21006, 21007, 21008, 21012, 21014, 21023, 21026
-
- NPC 2012007:EXP
- 30230, 30280, 30340, 30490, 30530, 30740
- 31110, 31220, 31230, 31710, 31790, 31890, 31930
-
- NPC 2012007:REG
- 30230, 30260, 30280, 30340, 30490, 30530, 30630, 30740
- 31110, 31220, 31230, 31630, 31650, 31710, 31790, 31890, 31930
-
- NPC 2012009:REG
- 20003, 20011, 20021, 20022, 20023, 20027, 20031
- 21004, 21007, 21010, 21012, 21020, 21021, 21030
-
- NPC 2040019:REG
- 20001, 20003, 20007, 20013, 20021, 20023, 20025
- 21002, 21004, 21006, 21008, 21022, 21027, 21029
-
- NPC 2041007:VIP
- 30160, 30190, 30250, 30640, 30660, 30840, 30870, 30990
- 31270, 31290, 31550, 31680, 31810, 31830, 31840, 31870
-
- NPC 2041009:EXP
- 30030, 30190, 30220, 30250, 30540, 30610, 30620, 30640, 30650, 30660, 30840, 30990
- 31170, 31270, 31430, 31510, 31540, 31550, 31600, 31680, 31810, 31830, 31840, 31870
-
- NPC 2041009:REG
- 30190, 30220, 30250, 30540, 30610, 30620, 30640, 30650, 30660, 30840, 30870, 30940, 30990
- 31170, 31270, 31290, 31510, 31540, 31550, 31600, 31640, 31680, 31810, 31830, 31840, 31870
-
- NPC 2041010:VIP
- 20000, 20001, 20003, 20004, 20005, 20006, 20007, 20008, 20011, 20012, 20014, 20031
- 21000, 21001, 21002, 21003, 21004, 21005, 21006, 21007, 21008, 21010, 21012, 21014
-
- NPC 2090100:VIP
- 30150, 30240, 30370, 30420, 30640, 30710, 30750, 30810
- 31140, 31160, 31180, 31300, 31460, 31470, 31660, 31910
-
- NPC 2090101:EXP
- 30030, 30150, 30240, 30370, 30420, 30550, 30600, 30640, 30700, 30710, 30720, 30750, 30810, 30830
- 31140, 31160, 31180, 31210, 31300, 31430, 31460, 31470, 31660, 31690, 31800, 31890, 31910, 31940
-
- NPC 2090104:REG
- 20002, 20005, 20007, 20011, 20014, 20017, 20029
- 21001, 21010, 21013, 21018, 21020, 21021, 21030
-
- NPC 2090104:VIP
- 20000, 20001, 20004, 20005, 20006, 20007, 20009, 20012, 20022, 20028, 20031
- 21000, 21003, 21005, 21006, 21008, 21009, 21011, 21012, 21023, 21024, 21026
-
- NPC 2100005:REG
- 30150, 30170, 30180, 30320, 30330, 30410, 30460, 30680, 30800, 30820, 30900
- 31090, 31190, 31330, 31340, 31400, 31420, 31520, 31620, 31650, 31660, 34000
-
- NPC 2100006:VIP
- 30150, 30170, 30180, 30320, 30330, 30410, 30460, 30820, 30900
- 31040, 31090, 31190, 31330, 31340, 31400, 31420, 31620, 31660
-
- NPC 2100008:VIP
- 20000, 20004, 20005, 20012, 20013, 20031
- 21000, 21003, 21006, 21009, 21012, 21024
-
- NPC 2100009:REG
- 20001, 20003, 20009, 20010, 20025, 20031
- 21002, 21009, 21011, 21013, 21016, 21029, 21030
-
- NPC 9120100:VIP
- 30260, 30280, 30340, 30710, 30780, 30800, 30810, 30820, 30920
- 31000, 31030, 31100, 31350, 31460, 31550, 31770, 31790, 31850
-
- NPC 9120101:REG
- 30260, 30280, 30340, 30360, 30710, 30780, 30790, 30800, 30810, 30820, 30920
- 31350, 31410, 31460, 31540, 31550, 31710, 31720, 31770, 31790, 31800, 31850, 34000
-
- NPC 9120102:VIP
- 20000, 20004, 20005, 20012, 20020, 20031
- 21000, 21003, 21006, 21012, 21021, 21024
-
- NPC 9120103:REG
- 20000, 20016, 20019, 20020, 20021, 20024, 20026
- 21000, 21002, 21009, 21016, 21022, 21025, 21027
-
- NPC 9201015:VIP
- 30050, 30300, 30410, 30450, 30510, 30570, 30580, 30590, 30660, 30910
- 31150, 31220, 31260, 31310, 31420, 31480, 31490, 31580, 31590, 31610, 31630
-
- NPC 9201016:EXP
- 30000, 30020, 30110, 30130, 30160, 30190, 30240, 30270, 30430
- 31000, 31030, 31050, 31070, 31090, 31150, 31310, 31910, 34010
-
- NPC 9201018:VIP
- 20000, 20001, 20003, 20004, 20005, 20006, 20007, 20008, 20018, 20019
- 21001, 21002, 21003, 21004, 21005, 21006, 21007, 21012, 21018, 21019
-
- NPC 9201019:REG
- 20002, 20005, 20007, 20011, 20014, 20027, 20029
- 21001, 21005, 21007, 21017, 21018, 21020, 21022
-
- NPC 9201063:EXP
- 30250, 30400, 30430, 30440, 30490, 30730, 30830, 30870, 30880, 33100
- 31320, 31450, 31560, 31570, 31690, 31720, 31730, 31830, 34010
-
- NPC 9201064:VIP
- 30250, 30490, 30730, 30870, 30880, 33100
- 31320, 31450, 31560, 31730, 31830
-
- NPC 9201069:VIP
- 20000, 20001, 20003, 20004, 20005, 20006, 20008, 20012, 20031
- 21001, 21002, 21003, 21004, 21005, 21006, 21008, 21012, 21016
-
- NPC 9201070:REG
- 20001, 20008, 20011, 20013, 20024, 20029, 20032
- 21000, 21007, 21011, 21012, 21017, 21020, 21022
-
- NPC 9270023:REG
- 20002, 20005, 20006, 20013, 20017, 20021, 20024
- 21002, 21003, 21014, 21016, 21017, 21021, 21027
-
- NPC 9270024:VIP
- 20005, 20012, 20013, 20020, 20021, 20026
- 21006, 21009, 21011, 21012, 21021, 21025
-
- NPC 9270036:VIP
- 30000, 30020, 30110, 30120, 30270, 30290, 30310, 30670, 30840
- 31010, 31050, 31110, 31120, 31240, 31250, 31280, 31670, 31810
-
- NPC 9270037:REG
- 30110, 30180, 30260, 30290, 30300, 30350, 30470, 30720, 30840
- 31110, 31200, 31250, 31280, 31600, 31640, 31670, 31810, 34020
-
-Unused cosmetics: 22
-30010 Zeta
-30070 Back
-30080 Buzzcut
-30090 Mohawk
-30100 Fantasy
-30480 Babby Cut
-30560 Grand Lionman
-30690 Metro Man
-30760 Bowling Ball
-30890 Eastern Mystery
-30930 Boy Band Cut
-30950 Volume Cut
-31020 Francesca
-31130 Jolie
-31530 Zessica
-31780 ???? ??
-31820 Grace
-31860 Laguna Beach
-31920 CL Hair
-31950 Vintage Flip
-33000 Prince Cut
-34030 Designer Hair
-
-Missing cosmetic itemids: 15
-Bohemian Hair
-Bow Hair
-Clean-Cut Short Hair
-Dual Blade Hair
-Evan Hair (F)
-Evan Hair (M)
-Explosion
-Lilin Hair
-Low Cut Bob
-Messy Pigtails
-Oh So Windy
-Spiky Shag
-Top Tied Hair
-Updo
-Windy Hair
-
diff --git a/tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/Pair.java b/tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/Pair.java
deleted file mode 100644
index 3e2f924b51..0000000000
--- a/tools/MapleCashCosmeticsChecker/src/maplecashcosmeticschecker/Pair.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-This file is part of the OdinMS Maple Story Server
-Copyright (C) 2008 ~ 2010 Patrick Huy
-Matthias Butz
-Jan Christian Meyer
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License 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;
-
-/**
- * Represents a pair of values.
- *
- * @author Frz
- * @since Revision 333
- * @version 1.0
- *
- * @param The type of the left value.
- * @param The type of the right value.
- */
-public class Pair {
-
- public E left;
- public F right;
-
- /**
- * Class constructor - pairs two objects together.
- *
- * @param left The left object.
- * @param right The right object.
- */
- public Pair(E left, F right) {
- this.left = left;
- this.right = right;
- }
-
- /**
- * Gets the left value.
- *
- * @return The left value.
- */
- public E getLeft() {
- return left;
- }
-
- /**
- * Gets the right value.
- *
- * @return The right value.
- */
- public F getRight() {
- return right;
- }
-
- /**
- * Turns the pair into a string.
- *
- * @return Each value of the pair as a string joined with a colon.
- */
- @Override
- public String toString() {
- return left.toString() + ":" + right.toString();
- }
-
- /**
- * Gets the hash code of this pair.
- */
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((left == null) ? 0 : left.hashCode());
- result = prime * result + ((right == null) ? 0 : right.hashCode());
- return result;
- }
-
- /**
- * Checks to see if two pairs are equal.
- */
- @SuppressWarnings("unchecked")
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final Pair other = (Pair) obj;
- if (left == null) {
- if (other.left != null) {
- return false;
- }
- } else if (!left.equals(other.left)) {
- return false;
- }
- if (right == null) {
- if (other.right != null) {
- return false;
- }
- } else if (!right.equals(other.right)) {
- return false;
- }
- return true;
- }
-}
\ No newline at end of file
diff --git a/tools/input/.gitignore b/tools/input/.gitignore
index c96a04f008..9e88c6e0f0 100644
--- a/tools/input/.gitignore
+++ b/tools/input/.gitignore
@@ -1,2 +1,4 @@
*
+!*/
+!/cosmetics/**
!.gitignore
\ No newline at end of file
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/amoria/face.txt b/tools/input/cosmetics/amoria/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/amoria/face.txt
rename to tools/input/cosmetics/amoria/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/amoria/hair.txt b/tools/input/cosmetics/amoria/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/amoria/hair.txt
rename to tools/input/cosmetics/amoria/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/ariant/face.txt b/tools/input/cosmetics/ariant/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/ariant/face.txt
rename to tools/input/cosmetics/ariant/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/ariant/hair.txt b/tools/input/cosmetics/ariant/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/ariant/hair.txt
rename to tools/input/cosmetics/ariant/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/cbd/face.txt b/tools/input/cosmetics/cbd/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/cbd/face.txt
rename to tools/input/cosmetics/cbd/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/cbd/hair.txt b/tools/input/cosmetics/cbd/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/cbd/hair.txt
rename to tools/input/cosmetics/cbd/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/colors.txt b/tools/input/cosmetics/colors.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/colors.txt
rename to tools/input/cosmetics/colors.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/henesys/face.txt b/tools/input/cosmetics/henesys/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/henesys/face.txt
rename to tools/input/cosmetics/henesys/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/henesys/hair.txt b/tools/input/cosmetics/henesys/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/henesys/hair.txt
rename to tools/input/cosmetics/henesys/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/kerning_city/face.txt b/tools/input/cosmetics/kerning_city/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/kerning_city/face.txt
rename to tools/input/cosmetics/kerning_city/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/kerning_city/hair.txt b/tools/input/cosmetics/kerning_city/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/kerning_city/hair.txt
rename to tools/input/cosmetics/kerning_city/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/ludibrium/face.txt b/tools/input/cosmetics/ludibrium/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/ludibrium/face.txt
rename to tools/input/cosmetics/ludibrium/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/ludibrium/hair.txt b/tools/input/cosmetics/ludibrium/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/ludibrium/hair.txt
rename to tools/input/cosmetics/ludibrium/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/mu_lung/face.txt b/tools/input/cosmetics/mu_lung/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/mu_lung/face.txt
rename to tools/input/cosmetics/mu_lung/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/mu_lung/hair.txt b/tools/input/cosmetics/mu_lung/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/mu_lung/hair.txt
rename to tools/input/cosmetics/mu_lung/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/nlc/face.txt b/tools/input/cosmetics/nlc/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/nlc/face.txt
rename to tools/input/cosmetics/nlc/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/nlc/hair.txt b/tools/input/cosmetics/nlc/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/nlc/hair.txt
rename to tools/input/cosmetics/nlc/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/orbis/face.txt b/tools/input/cosmetics/orbis/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/orbis/face.txt
rename to tools/input/cosmetics/orbis/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/orbis/hair.txt b/tools/input/cosmetics/orbis/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/orbis/hair.txt
rename to tools/input/cosmetics/orbis/hair.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/showa/face.txt b/tools/input/cosmetics/showa/face.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/showa/face.txt
rename to tools/input/cosmetics/showa/face.txt
diff --git a/tools/MapleCashCosmeticsChecker/lib/care/showa/hair.txt b/tools/input/cosmetics/showa/hair.txt
similarity index 100%
rename from tools/MapleCashCosmeticsChecker/lib/care/showa/hair.txt
rename to tools/input/cosmetics/showa/hair.txt