Move MapleCashCosmeticsChecker to main module
This commit is contained in:
1 parent
fdd2ef7b3a
commit
da66e7614d
27 files changed
+94
-439
No files matched your search
@@ -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();
|
||||
}
|
||||
}
|
||||
+84
-101
@@ -1,76 +1,50 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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
|
||||
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* Estimated parse time: 1 minute
|
||||
*/
|
||||
public class MapleCashCosmeticsChecker {
|
||||
static String libPath = "lib";
|
||||
static String handbookPath = "../../handbook";
|
||||
static String wzPath = "../../wz";
|
||||
static String scriptPath = "../../scripts";
|
||||
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;
|
||||
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
private static final Map<Integer, Set<Integer>> scriptCosmetics = new HashMap<>();
|
||||
private static final Map<Integer, String> scriptEntries = new HashMap<>(500);
|
||||
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;
|
||||
|
||||
static int initialStringLength = 50;
|
||||
|
||||
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 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;
|
||||
@@ -81,7 +55,7 @@ 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);
|
||||
@@ -97,7 +71,7 @@ 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);
|
||||
@@ -111,8 +85,7 @@ public class MapleCashCosmeticsChecker {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -120,8 +93,7 @@ public class MapleCashCosmeticsChecker {
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
@@ -129,8 +101,7 @@ public class MapleCashCosmeticsChecker {
|
||||
private static void translateToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
if (status == 3) {
|
||||
@@ -141,7 +112,7 @@ public class MapleCashCosmeticsChecker {
|
||||
}
|
||||
} else if (status == 4) {
|
||||
String d = getName(token);
|
||||
int itemid = Integer.valueOf(d);
|
||||
int itemid = Integer.parseInt(d);
|
||||
|
||||
int cosmeticid;
|
||||
if (itemid >= 30000) {
|
||||
@@ -159,7 +130,7 @@ public class MapleCashCosmeticsChecker {
|
||||
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) {
|
||||
@@ -172,7 +143,7 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
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<Integer> usedByNpcids, int cosmeticid) {
|
||||
@@ -199,7 +170,7 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
private static int getNpcIdFromFilename(String name) {
|
||||
try {
|
||||
return Integer.valueOf(name.substring(0, name.indexOf('.')));
|
||||
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
@@ -207,7 +178,7 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
private static List<Integer> findCosmeticDataNpcids(int itemid) {
|
||||
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)) {
|
||||
npcids.add(itemid);
|
||||
}
|
||||
@@ -218,13 +189,13 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
private static void loadScripts() throws IOException {
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(scriptPath + "/npc", files);
|
||||
listFiles(SCRIPTS_PATH + "/npc", files);
|
||||
|
||||
for (File f : files) {
|
||||
Integer npcid = getNpcIdFromFilename(f.getName());
|
||||
|
||||
//System.out.println("Parsing " + f.getAbsolutePath());
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
@@ -243,7 +214,7 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
for (String st : s) {
|
||||
if (!st.isEmpty()) {
|
||||
int itemid = Integer.valueOf(st);
|
||||
int itemid = Integer.parseInt(st);
|
||||
cosmeticids.add(itemid);
|
||||
}
|
||||
}
|
||||
@@ -257,7 +228,7 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
for (String st : s) {
|
||||
if (!st.isEmpty()) {
|
||||
int itemid = Integer.valueOf(st);
|
||||
int itemid = Integer.parseInt(st);
|
||||
cosmeticids.add(itemid);
|
||||
}
|
||||
}
|
||||
@@ -282,7 +253,7 @@ public class MapleCashCosmeticsChecker {
|
||||
System.out.println("Reading script files ...");
|
||||
loadScripts();
|
||||
|
||||
if (ignoreCurrentScriptCosmetics) {
|
||||
if (IGNORE_CURRENT_SCRIPT_COSMETICS) {
|
||||
for (Set<Integer> npcCosmetics : scriptCosmetics.values()) {
|
||||
npcCosmetics.clear();
|
||||
}
|
||||
@@ -297,15 +268,17 @@ public class MapleCashCosmeticsChecker {
|
||||
private static List<Integer> loadCosmeticCouponids() throws IOException {
|
||||
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);
|
||||
|
||||
String line;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (line.isEmpty()) continue;
|
||||
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]);
|
||||
@@ -322,7 +295,7 @@ public class MapleCashCosmeticsChecker {
|
||||
List<Integer> files = new LinkedList<>();
|
||||
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)) {
|
||||
files.add(text.getKey());
|
||||
}
|
||||
@@ -401,7 +374,9 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
String[] tokens = s[0].split(" ");
|
||||
Pair<Integer, CosmeticType> cosmeticData = parseCosmeticCoupon(tokens);
|
||||
if (cosmeticData == null) return null;
|
||||
if (cosmeticData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
town = "";
|
||||
for (int i = 0; i < cosmeticData.left; i++) {
|
||||
@@ -426,14 +401,18 @@ public class MapleCashCosmeticsChecker {
|
||||
}
|
||||
|
||||
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());
|
||||
if (npcid == null) continue;
|
||||
if (npcid == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String couponName = e.getValue();
|
||||
List<String> couponData = parseCosmeticCoupon(couponName);
|
||||
|
||||
if (couponData == null) continue;
|
||||
if (couponData == null) {
|
||||
continue;
|
||||
}
|
||||
cosmeticNpcids.put(couponData, npcid);
|
||||
}
|
||||
}
|
||||
@@ -443,18 +422,18 @@ public class MapleCashCosmeticsChecker {
|
||||
}
|
||||
|
||||
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) {
|
||||
String[] s = line.split(" - ", 3);
|
||||
int itemid = Integer.valueOf(s[0]);
|
||||
int itemid = Integer.parseInt(s[0]);
|
||||
|
||||
String name;
|
||||
if (itemid < 30000) {
|
||||
@@ -498,8 +477,12 @@ public class MapleCashCosmeticsChecker {
|
||||
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<Integer> fetchExpectedCosmetics(String[] cosmeticList, boolean gender) {
|
||||
@@ -522,7 +505,7 @@ public class MapleCashCosmeticsChecker {
|
||||
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;
|
||||
@@ -567,7 +550,7 @@ public class MapleCashCosmeticsChecker {
|
||||
System.out.println("Analyzing cosmetic NPC scripts ...");
|
||||
|
||||
ArrayList<File> cosmeticRecipes = new ArrayList<>();
|
||||
listFiles(libPath + "/care", cosmeticRecipes);
|
||||
listFiles(INPUT_DIRECTORY_PATH, cosmeticRecipes);
|
||||
|
||||
for (File f : cosmeticRecipes) {
|
||||
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) {
|
||||
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);
|
||||
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());
|
||||
@@ -633,7 +616,7 @@ public class MapleCashCosmeticsChecker {
|
||||
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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 <[email protected]>
|
||||
Matthias Butz <[email protected]>
|
||||
Jan Christian Meyer <[email protected]>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
*
|
||||
!*/
|
||||
!/cosmetics/**
|
||||
!.gitignore
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user