Move MapleCashCosmeticsChecker to main module
This commit is contained in:
@@ -21,15 +21,15 @@ public enum WZFiles {
|
|||||||
|
|
||||||
private final String fileName;
|
private final String fileName;
|
||||||
|
|
||||||
WZFiles(String fileName) {
|
WZFiles(String name) {
|
||||||
this.fileName = fileName;
|
this.fileName = name + ".wz";
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getFile() {
|
public File getFile() {
|
||||||
return new File(getFilePath());
|
return new File(DIRECTORY, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFilePath() {
|
public String getFilePath() {
|
||||||
return String.format("%s/%s.wz", DIRECTORY, fileName);
|
return getFile().getPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +1,50 @@
|
|||||||
/*
|
package tools.mapletools;
|
||||||
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
|
import provider.wz.WZFiles;
|
||||||
it under the terms of the GNU Affero General Public License as
|
import tools.Pair;
|
||||||
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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package maplecashcosmeticschecker;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author RonanLana
|
* @author RonanLana
|
||||||
|
* <p>
|
||||||
This application parses the cosmetic recipes defined within "lib/care" folder, loads
|
* 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
|
* 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
|
* cosmetics within the stylist/surgeon. Results from the search are reported in a report
|
||||||
file.
|
* file.
|
||||||
|
* <p>
|
||||||
Note: to best make use of this feature, set ignoreCurrentScriptCosmetics = true. This
|
* 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.
|
* way, every available cosmetic present on the recipes will be listed on the report.
|
||||||
|
* <p>
|
||||||
Estimated parse time: 1 minute
|
* Estimated parse time: 1 minute
|
||||||
|
|
||||||
*/
|
*/
|
||||||
public class MapleCashCosmeticsChecker {
|
public class CashCosmeticsChecker {
|
||||||
static String libPath = "lib";
|
private static final String HANDBOOK_PATH = "handbook";
|
||||||
static String handbookPath = "../../handbook";
|
private static final String SCRIPTS_PATH = "scripts";
|
||||||
static String wzPath = "../../wz";
|
private static final String INPUT_DIRECTORY_PATH = ToolConstants.getInputFile("care").getPath();
|
||||||
static String scriptPath = "../../scripts";
|
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;
|
||||||
|
|
||||||
static PrintWriter printWriter = null;
|
private static final Map<Integer, Set<Integer>> scriptCosmetics = new HashMap<>();
|
||||||
static InputStreamReader fileReader = null;
|
private static final Map<Integer, String> scriptEntries = new HashMap<>(500);
|
||||||
static BufferedReader bufferedReader = null;
|
private static final Set<Integer> allCosmetics = new HashSet<>();
|
||||||
|
private static final Set<Integer> unusedCosmetics = new HashSet<>();
|
||||||
|
private static final Map<Integer, List<Integer>> usedCosmetics = new HashMap<>();
|
||||||
|
private static final Map<Integer, String> couponNames = new HashMap<>();
|
||||||
|
private static final Map<Integer, Integer> cosmeticNpcs = new HashMap<>(); // expected only 1 NPC per cosmetic coupon (town care/salon)
|
||||||
|
private static final Map<List<String>, Integer> cosmeticNpcids = new HashMap<>();
|
||||||
|
private static final Set<String> missingCosmeticNames = new HashSet<>();
|
||||||
|
private static final Map<String, Integer> cosmeticNameIds = new HashMap<>();
|
||||||
|
private static final Map<Integer, String> cosmeticIdNames = new HashMap<>();
|
||||||
|
private static final Map<Pair<Integer, String>, Set<Integer>> missingCosmeticsNpcTypes = new HashMap<>();
|
||||||
|
|
||||||
static boolean ignoreCurrentScriptCosmetics = false;
|
private static PrintWriter printWriter = null;
|
||||||
|
private static InputStreamReader fileReader = null;
|
||||||
static int initialStringLength = 50;
|
private static BufferedReader bufferedReader = null;
|
||||||
|
private static byte status = 0;
|
||||||
static byte status = 0;
|
|
||||||
|
|
||||||
static Map<Integer, Set<Integer>> scriptCosmetics = new HashMap<>();
|
|
||||||
static Map<Integer, String> scriptEntries = new HashMap<>(500);
|
|
||||||
|
|
||||||
static Set<Integer> allCosmetics = new HashSet<>();
|
|
||||||
|
|
||||||
static Set<Integer> unusedCosmetics = new HashSet<>();
|
|
||||||
static Map<Integer, List<Integer>> usedCosmetics = new HashMap<>();
|
|
||||||
|
|
||||||
static Map<Integer, String> couponNames = new HashMap<>();
|
|
||||||
static Map<Integer, Integer> cosmeticNpcs = new HashMap<>(); // expected only 1 NPC per cosmetic coupon (town care/salon)
|
|
||||||
static Map<List<String>, Integer> cosmeticNpcids = new HashMap<>();
|
|
||||||
|
|
||||||
static Set<String> missingCosmeticNames = new HashSet<>();
|
|
||||||
static Map<String, Integer> cosmeticNameIds = new HashMap<>();
|
|
||||||
static Map<Integer, String> cosmeticIdNames = new HashMap<>();
|
|
||||||
|
|
||||||
static Map<Pair<Integer, String>, Set<Integer>> missingCosmeticsNpcTypes = new HashMap<>();
|
|
||||||
|
|
||||||
private static String getName(String token) {
|
private static String getName(String token) {
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -81,7 +55,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||||
j = token.indexOf("\"", i); //upper bound
|
j = token.indexOf("\"", i); //upper bound
|
||||||
|
|
||||||
dest = new char[initialStringLength];
|
dest = new char[INITIAL_STRING_LENGTH];
|
||||||
token.getChars(i, j, dest, 0);
|
token.getChars(i, j, dest, 0);
|
||||||
|
|
||||||
d = new String(dest);
|
d = new String(dest);
|
||||||
@@ -97,7 +71,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||||
j = token.indexOf("\"", i); //upper bound
|
j = token.indexOf("\"", i); //upper bound
|
||||||
|
|
||||||
dest = new char[initialStringLength];
|
dest = new char[INITIAL_STRING_LENGTH];
|
||||||
token.getChars(i, j, dest, 0);
|
token.getChars(i, j, dest, 0);
|
||||||
|
|
||||||
d = new String(dest);
|
d = new String(dest);
|
||||||
@@ -111,8 +85,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||||
simpleToken(line);
|
simpleToken(line);
|
||||||
}
|
}
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch(Exception e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,8 +93,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
private static void simpleToken(String token) {
|
private static void simpleToken(String token) {
|
||||||
if (token.contains("/imgdir")) {
|
if (token.contains("/imgdir")) {
|
||||||
status -= 1;
|
status -= 1;
|
||||||
}
|
} else if (token.contains("imgdir")) {
|
||||||
else if(token.contains("imgdir")) {
|
|
||||||
status += 1;
|
status += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,8 +101,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
private static void translateToken(String token) {
|
private static void translateToken(String token) {
|
||||||
if (token.contains("/imgdir")) {
|
if (token.contains("/imgdir")) {
|
||||||
status -= 1;
|
status -= 1;
|
||||||
}
|
} else if (token.contains("imgdir")) {
|
||||||
else if(token.contains("imgdir")) {
|
|
||||||
status += 1;
|
status += 1;
|
||||||
|
|
||||||
if (status == 3) {
|
if (status == 3) {
|
||||||
@@ -141,7 +112,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
}
|
}
|
||||||
} else if (status == 4) {
|
} else if (status == 4) {
|
||||||
String d = getName(token);
|
String d = getName(token);
|
||||||
int itemid = Integer.valueOf(d);
|
int itemid = Integer.parseInt(d);
|
||||||
|
|
||||||
int cosmeticid;
|
int cosmeticid;
|
||||||
if (itemid >= 30000) {
|
if (itemid >= 30000) {
|
||||||
@@ -159,7 +130,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
private static void readEqpStringData(String eqpStringDirectory) throws IOException {
|
private static void readEqpStringData(String eqpStringDirectory) throws IOException {
|
||||||
String line;
|
String line;
|
||||||
|
|
||||||
fileReader = new InputStreamReader(new FileInputStream(eqpStringDirectory), "UTF-8");
|
fileReader = new InputStreamReader(new FileInputStream(eqpStringDirectory), StandardCharsets.UTF_8);
|
||||||
bufferedReader = new BufferedReader(fileReader);
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
|
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
@@ -172,7 +143,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
private static void loadCosmeticWzData() throws IOException {
|
private static void loadCosmeticWzData() throws IOException {
|
||||||
System.out.println("Reading String.wz ...");
|
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<Integer> usedByNpcids, int cosmeticid) {
|
private static void setCosmeticUsage(List<Integer> usedByNpcids, int cosmeticid) {
|
||||||
@@ -199,7 +170,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
private static int getNpcIdFromFilename(String name) {
|
private static int getNpcIdFromFilename(String name) {
|
||||||
try {
|
try {
|
||||||
return Integer.valueOf(name.substring(0, name.indexOf('.')));
|
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -207,7 +178,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
private static List<Integer> findCosmeticDataNpcids(int itemid) {
|
private static List<Integer> findCosmeticDataNpcids(int itemid) {
|
||||||
List<Integer> npcids = new LinkedList<>();
|
List<Integer> npcids = new LinkedList<>();
|
||||||
for (Entry<Integer, Set<Integer>> sc : scriptCosmetics.entrySet()) {
|
for (Map.Entry<Integer, Set<Integer>> sc : scriptCosmetics.entrySet()) {
|
||||||
if (sc.getValue().contains(itemid)) {
|
if (sc.getValue().contains(itemid)) {
|
||||||
npcids.add(itemid);
|
npcids.add(itemid);
|
||||||
}
|
}
|
||||||
@@ -218,13 +189,13 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
private static void loadScripts() throws IOException {
|
private static void loadScripts() throws IOException {
|
||||||
ArrayList<File> files = new ArrayList<>();
|
ArrayList<File> 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());
|
Integer npcid = getNpcIdFromFilename(f.getName());
|
||||||
|
|
||||||
//System.out.println("Parsing " + f.getAbsolutePath());
|
//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);
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
@@ -243,7 +214,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
for (String st : s) {
|
for (String st : s) {
|
||||||
if (!st.isEmpty()) {
|
if (!st.isEmpty()) {
|
||||||
int itemid = Integer.valueOf(st);
|
int itemid = Integer.parseInt(st);
|
||||||
cosmeticids.add(itemid);
|
cosmeticids.add(itemid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -257,7 +228,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
for (String st : s) {
|
for (String st : s) {
|
||||||
if (!st.isEmpty()) {
|
if (!st.isEmpty()) {
|
||||||
int itemid = Integer.valueOf(st);
|
int itemid = Integer.parseInt(st);
|
||||||
cosmeticids.add(itemid);
|
cosmeticids.add(itemid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +253,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
System.out.println("Reading script files ...");
|
System.out.println("Reading script files ...");
|
||||||
loadScripts();
|
loadScripts();
|
||||||
|
|
||||||
if (ignoreCurrentScriptCosmetics) {
|
if (IGNORE_CURRENT_SCRIPT_COSMETICS) {
|
||||||
for (Set<Integer> npcCosmetics : scriptCosmetics.values()) {
|
for (Set<Integer> npcCosmetics : scriptCosmetics.values()) {
|
||||||
npcCosmetics.clear();
|
npcCosmetics.clear();
|
||||||
}
|
}
|
||||||
@@ -297,15 +268,17 @@ public class MapleCashCosmeticsChecker {
|
|||||||
private static List<Integer> loadCosmeticCouponids() throws IOException {
|
private static List<Integer> loadCosmeticCouponids() throws IOException {
|
||||||
List<Integer> couponItemids = new LinkedList<>();
|
List<Integer> 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);
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
if (line.isEmpty()) continue;
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String[] s = line.split(" - ", 3);
|
String[] s = line.split(" - ", 3);
|
||||||
|
|
||||||
int itemid = Integer.valueOf(s[0]);
|
int itemid = Integer.parseInt(s[0]);
|
||||||
if (itemid >= 5150000 && itemid < 5160000) {
|
if (itemid >= 5150000 && itemid < 5160000) {
|
||||||
couponItemids.add(itemid);
|
couponItemids.add(itemid);
|
||||||
couponNames.put(itemid, s[1]);
|
couponNames.put(itemid, s[1]);
|
||||||
@@ -322,7 +295,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
List<Integer> files = new LinkedList<>();
|
List<Integer> files = new LinkedList<>();
|
||||||
String t = String.valueOf(itemid);
|
String t = String.valueOf(itemid);
|
||||||
|
|
||||||
for (Entry<Integer, String> text : scriptEntries.entrySet()) {
|
for (Map.Entry<Integer, String> text : scriptEntries.entrySet()) {
|
||||||
if (text.getValue().contains(t)) {
|
if (text.getValue().contains(t)) {
|
||||||
files.add(text.getKey());
|
files.add(text.getKey());
|
||||||
}
|
}
|
||||||
@@ -401,7 +374,9 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
String[] tokens = s[0].split(" ");
|
String[] tokens = s[0].split(" ");
|
||||||
Pair<Integer, CosmeticType> cosmeticData = parseCosmeticCoupon(tokens);
|
Pair<Integer, CosmeticType> cosmeticData = parseCosmeticCoupon(tokens);
|
||||||
if (cosmeticData == null) return null;
|
if (cosmeticData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
town = "";
|
town = "";
|
||||||
for (int i = 0; i < cosmeticData.left; i++) {
|
for (int i = 0; i < cosmeticData.left; i++) {
|
||||||
@@ -426,14 +401,18 @@ public class MapleCashCosmeticsChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void generateCosmeticPlaceNpcs() {
|
private static void generateCosmeticPlaceNpcs() {
|
||||||
for (Entry<Integer, String> e : couponNames.entrySet()) {
|
for (Map.Entry<Integer, String> e : couponNames.entrySet()) {
|
||||||
Integer npcid = cosmeticNpcs.get(e.getKey());
|
Integer npcid = cosmeticNpcs.get(e.getKey());
|
||||||
if (npcid == null) continue;
|
if (npcid == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String couponName = e.getValue();
|
String couponName = e.getValue();
|
||||||
List<String> couponData = parseCosmeticCoupon(couponName);
|
List<String> couponData = parseCosmeticCoupon(couponName);
|
||||||
|
|
||||||
if (couponData == null) continue;
|
if (couponData == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
cosmeticNpcids.put(couponData, npcid);
|
cosmeticNpcids.put(couponData, npcid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,18 +422,18 @@ public class MapleCashCosmeticsChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String getCosmeticName(String name, boolean gender) {
|
private static String getCosmeticName(String name, boolean gender) {
|
||||||
String ret = name + " (" + (gender ? "F" : "M") + ")";
|
final String genderString = gender ? "F" : "M";
|
||||||
return ret;
|
return String.format("%s (%s)", name, genderString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadCosmeticNames(String cosmeticPath) throws IOException {
|
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);
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
String[] s = line.split(" - ", 3);
|
String[] s = line.split(" - ", 3);
|
||||||
int itemid = Integer.valueOf(s[0]);
|
int itemid = Integer.parseInt(s[0]);
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
if (itemid < 30000) {
|
if (itemid < 30000) {
|
||||||
@@ -498,8 +477,12 @@ public class MapleCashCosmeticsChecker {
|
|||||||
private static void loadCosmeticNames() throws IOException {
|
private static void loadCosmeticNames() throws IOException {
|
||||||
System.out.println("Reading cosmetics from handbook ...");
|
System.out.println("Reading cosmetics from handbook ...");
|
||||||
|
|
||||||
loadCosmeticNames(handbookPath + "/Equip/Face.txt");
|
loadCosmeticNames(getHandbookFileName("/Equip/Face.txt"));
|
||||||
loadCosmeticNames(handbookPath + "/Equip/Hair.txt");
|
loadCosmeticNames(getHandbookFileName("/Equip/Hair.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getHandbookFileName(String fileName) {
|
||||||
|
return HANDBOOK_PATH + fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Integer> fetchExpectedCosmetics(String[] cosmeticList, boolean gender) {
|
private static List<Integer> fetchExpectedCosmetics(String[] cosmeticList, boolean gender) {
|
||||||
@@ -522,7 +505,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
String townName = f.getParent().substring(f.getParent().lastIndexOf("\\") + 1);
|
String townName = f.getParent().substring(f.getParent().lastIndexOf("\\") + 1);
|
||||||
String typeCosmetic = f.getName().substring(0, f.getName().indexOf("."));
|
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);
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
@@ -567,7 +550,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
System.out.println("Analyzing cosmetic NPC scripts ...");
|
System.out.println("Analyzing cosmetic NPC scripts ...");
|
||||||
|
|
||||||
ArrayList<File> cosmeticRecipes = new ArrayList<>();
|
ArrayList<File> cosmeticRecipes = new ArrayList<>();
|
||||||
listFiles(libPath + "/care", cosmeticRecipes);
|
listFiles(INPUT_DIRECTORY_PATH, cosmeticRecipes);
|
||||||
|
|
||||||
for (File f : cosmeticRecipes) {
|
for (File f : cosmeticRecipes) {
|
||||||
verifyCosmeticExpectedFile(f);
|
verifyCosmeticExpectedFile(f);
|
||||||
@@ -576,16 +559,16 @@ public class MapleCashCosmeticsChecker {
|
|||||||
|
|
||||||
private static List<Pair<Pair<Integer, String>, List<Integer>>> getSortedMapEntries(Map<Pair<Integer, String>, Set<Integer>> map) {
|
private static List<Pair<Pair<Integer, String>, List<Integer>>> getSortedMapEntries(Map<Pair<Integer, String>, Set<Integer>> map) {
|
||||||
List<Pair<Pair<Integer, String>, List<Integer>>> list = new ArrayList<>(map.size());
|
List<Pair<Pair<Integer, String>, List<Integer>>> list = new ArrayList<>(map.size());
|
||||||
for(Entry<Pair<Integer, String>, Set<Integer>> e : map.entrySet()) {
|
for (Map.Entry<Pair<Integer, String>, Set<Integer>> e : map.entrySet()) {
|
||||||
List<Integer> il = new ArrayList<>(2);
|
List<Integer> il = new ArrayList<>(2);
|
||||||
il.addAll(e.getValue());
|
il.addAll(e.getValue());
|
||||||
|
|
||||||
Collections.sort(il, (o1, o2) -> o1 - o2);
|
il.sort((o1, o2) -> o1 - o2);
|
||||||
|
|
||||||
list.add(new Pair<>(e.getKey(), il));
|
list.add(new Pair<>(e.getKey(), il));
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(list, (o1, o2) -> {
|
list.sort((o1, o2) -> {
|
||||||
int cmp = o1.getLeft().getLeft() - o2.getLeft().getLeft();
|
int cmp = o1.getLeft().getLeft() - o2.getLeft().getLeft();
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
return o1.getLeft().getRight().compareTo(o2.getLeft().getRight());
|
return o1.getLeft().getRight().compareTo(o2.getLeft().getRight());
|
||||||
@@ -633,7 +616,7 @@ public class MapleCashCosmeticsChecker {
|
|||||||
private static void reportCosmeticResults() throws IOException {
|
private static void reportCosmeticResults() throws IOException {
|
||||||
System.out.println("Reporting results ...");
|
System.out.println("Reporting results ...");
|
||||||
|
|
||||||
printWriter = new PrintWriter("lib/result.txt", "UTF-8");
|
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
printReportFileHeader();
|
printReportFileHeader();
|
||||||
|
|
||||||
@@ -6,6 +6,10 @@ public class ToolConstants {
|
|||||||
public static final File INPUT_DIRECTORY = new File("tools/input");
|
public static final File INPUT_DIRECTORY = new File("tools/input");
|
||||||
public static final File OUTPUT_DIRECTORY = new File("tools/output");
|
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) {
|
public static File getOutputFile(String fileName) {
|
||||||
return new File(OUTPUT_DIRECTORY, fileName);
|
return new File(OUTPUT_DIRECTORY, fileName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of the OdinMS Maple Story Server
|
|
||||||
Copyright (C) 2008 ~ 2010 Patrick Huy <patrick.huy@frz.cc>
|
|
||||||
Matthias Butz <matze@odinms.de>
|
|
||||||
Jan Christian Meyer <vimes@odinms.de>
|
|
||||||
|
|
||||||
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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package maplecashcosmeticschecker;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a pair of values.
|
|
||||||
*
|
|
||||||
* @author Frz
|
|
||||||
* @since Revision 333
|
|
||||||
* @version 1.0
|
|
||||||
*
|
|
||||||
* @param <E> The type of the left value.
|
|
||||||
* @param <F> The type of the right value.
|
|
||||||
*/
|
|
||||||
public class Pair<E, F> {
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
tools/input/.gitignore
vendored
2
tools/input/.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
*
|
*
|
||||||
|
!*/
|
||||||
|
!/cosmetics/**
|
||||||
!.gitignore
|
!.gitignore
|
||||||
Reference in New Issue
Block a user