Move MapleNoItemNameFetcher to main module
This commit is contained in:
473
src/main/java/tools/mapletools/NoItemNameFetcher.java
Normal file
473
src/main/java/tools/mapletools/NoItemNameFetcher.java
Normal file
@@ -0,0 +1,473 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.*;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application finds itemids with inexistent name and description from
|
||||
* within the server-side XMLs, then identify them on a report file along
|
||||
* with a XML excerpt to be appended on the String.wz xml nodes. This program
|
||||
* assumes all equipids are depicted using 8 digits and item using 7 digits.
|
||||
* <p>
|
||||
* Estimated parse time: 2 minutes
|
||||
*/
|
||||
public class NoItemNameFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("no_item_name_result.txt");
|
||||
private static final File OUTPUT_XML_FILE = ToolConstants.getOutputFile("no_item_name_xml.txt");
|
||||
|
||||
private static final Map<Integer, String> itemsWzPath = new HashMap<>();
|
||||
private static final Map<Integer, EquipType> equipTypes = new HashMap<>();
|
||||
private static final Map<Integer, ItemType> itemsWithNoNameProperty = new HashMap<>();
|
||||
private static final Set<Integer> equipsWithNoCashProperty = new HashSet<>();
|
||||
private static final Map<Integer, String> nameContentCache = new HashMap<>();
|
||||
private static final Map<Integer, String> descContentCache = new HashMap<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static ItemType curType = ItemType.UNDEF;
|
||||
|
||||
private enum ItemType {
|
||||
UNDEF, CASH, CONSUME, EQP, ETC, INS, PET
|
||||
}
|
||||
|
||||
private enum EquipType {
|
||||
UNDEF, ACCESSORY, CAP, CAPE, COAT, FACE, GLOVE, HAIR, LONGCOAT, PANTS, PETEQUIP, RING, SHIELD, SHOES, TAMING, WEAPON
|
||||
}
|
||||
|
||||
private static void processStringSubdirectoryData(MapleData subdirData, String subdirPath) {
|
||||
for (MapleData md : subdirData.getChildren()) {
|
||||
try {
|
||||
MapleData nameData = md.getChildByPath("name");
|
||||
MapleData descData = md.getChildByPath("desc");
|
||||
|
||||
int itemId = Integer.parseInt(md.getName());
|
||||
if (nameData != null && descData != null) {
|
||||
itemsWithNoNameProperty.remove(itemId);
|
||||
} else {
|
||||
if (nameData != null) {
|
||||
nameContentCache.put(itemId, MapleDataTool.getString("name", md));
|
||||
} else if (descData != null) {
|
||||
descContentCache.put(itemId, MapleDataTool.getString("desc", md));
|
||||
}
|
||||
|
||||
System.out.println("Found itemid on String.wz with no full property: " + subdirPath + subdirData.getName() + "/" + md.getName());
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
System.out.println("Error reading string image: " + subdirPath + subdirData.getName() + "/" + md.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void readStringSubdirectoryData(MapleData subdirData, int depth, String subdirPath) {
|
||||
if (depth > 0) {
|
||||
for (MapleData mDir : subdirData.getChildren()) {
|
||||
readStringSubdirectoryData(mDir, depth - 1, subdirPath + mDir.getName() + "/");
|
||||
}
|
||||
} else {
|
||||
processStringSubdirectoryData(subdirData, subdirPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readStringSubdirectoryData(MapleData subdirData, int depth) {
|
||||
readStringSubdirectoryData(subdirData, depth, "");
|
||||
}
|
||||
|
||||
private static void readStringWZData() {
|
||||
System.out.println("Parsing String.wz...");
|
||||
MapleDataProvider stringData = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
|
||||
MapleData cashStringData = stringData.getData("Cash.img");
|
||||
readStringSubdirectoryData(cashStringData, 0);
|
||||
|
||||
MapleData consumeStringData = stringData.getData("Consume.img");
|
||||
readStringSubdirectoryData(consumeStringData, 0);
|
||||
|
||||
MapleData eqpStringData = stringData.getData("Eqp.img");
|
||||
readStringSubdirectoryData(eqpStringData, 2);
|
||||
|
||||
MapleData etcStringData = stringData.getData("Etc.img");
|
||||
readStringSubdirectoryData(etcStringData, 1);
|
||||
|
||||
MapleData insStringData = stringData.getData("Ins.img");
|
||||
readStringSubdirectoryData(insStringData, 0);
|
||||
|
||||
MapleData petStringData = stringData.getData("Pet.img");
|
||||
readStringSubdirectoryData(petStringData, 0);
|
||||
}
|
||||
|
||||
private static boolean isTamingMob(int itemId) {
|
||||
int itemType = itemId / 1000;
|
||||
return itemType == 1902 || itemType == 1912;
|
||||
}
|
||||
|
||||
private static boolean isAccessory(int itemId) {
|
||||
return itemId >= 1110000 && itemId < 1140000;
|
||||
}
|
||||
|
||||
private static ItemType getItemTypeFromDirectoryName(String dirName) {
|
||||
return switch (dirName) {
|
||||
case "Cash" -> ItemType.CASH;
|
||||
case "Consume" -> ItemType.CONSUME;
|
||||
case "Etc" -> ItemType.ETC;
|
||||
case "Install" -> ItemType.INS;
|
||||
case "Pet" -> ItemType.PET;
|
||||
default -> ItemType.UNDEF;
|
||||
};
|
||||
}
|
||||
|
||||
private static EquipType getEquipTypeFromDirectoryName(String dirName) {
|
||||
return switch (dirName) {
|
||||
case "Accessory" -> EquipType.ACCESSORY;
|
||||
case "Cap" -> EquipType.CAP;
|
||||
case "Cape" -> EquipType.CAPE;
|
||||
case "Coat" -> EquipType.COAT;
|
||||
case "Face" -> EquipType.FACE;
|
||||
case "Glove" -> EquipType.GLOVE;
|
||||
case "Hair" -> EquipType.HAIR;
|
||||
case "Longcoat" -> EquipType.LONGCOAT;
|
||||
case "Pants" -> EquipType.PANTS;
|
||||
case "PetEquip" -> EquipType.PETEQUIP;
|
||||
case "Ring" -> EquipType.RING;
|
||||
case "Shield" -> EquipType.SHIELD;
|
||||
case "Shoes" -> EquipType.SHOES;
|
||||
case "TamingMob" -> EquipType.TAMING;
|
||||
case "Weapon" -> EquipType.WEAPON;
|
||||
default -> EquipType.UNDEF;
|
||||
};
|
||||
}
|
||||
|
||||
private static String getStringDirectoryNameFromEquipType(EquipType eType) {
|
||||
return switch (eType) {
|
||||
case ACCESSORY -> "Accessory";
|
||||
case CAP -> "Cap";
|
||||
case CAPE -> "Cape";
|
||||
case COAT -> "Coat";
|
||||
case FACE -> "Face";
|
||||
case GLOVE -> "Glove";
|
||||
case HAIR -> "Hair";
|
||||
case LONGCOAT -> "Longcoat";
|
||||
case PANTS -> "Pants";
|
||||
case PETEQUIP -> "PetEquip";
|
||||
case RING -> "Ring";
|
||||
case SHIELD -> "Shield";
|
||||
case SHOES -> "Shoes";
|
||||
case TAMING -> "Taming";
|
||||
case WEAPON -> "Weapon";
|
||||
default -> "Undefined";
|
||||
};
|
||||
}
|
||||
|
||||
private static void readEquipNodeData(MapleDataProvider data, MapleDataDirectoryEntry mDir, String wzFileName, String dirName) {
|
||||
EquipType eqType = getEquipTypeFromDirectoryName(dirName);
|
||||
|
||||
for (MapleDataFileEntry mFile : mDir.getFiles()) {
|
||||
String fileName = mFile.getName();
|
||||
|
||||
try {
|
||||
int itemId = Integer.parseInt(fileName.substring(0, 8));
|
||||
itemsWithNoNameProperty.put(itemId, curType);
|
||||
equipTypes.put(itemId, eqType);
|
||||
|
||||
itemsWzPath.put(itemId, wzFileName + "/" + dirName + "/" + fileName);
|
||||
|
||||
if (!isAccessory(itemId) && !isTamingMob(itemId)) {
|
||||
try {
|
||||
MapleData fileData = data.getData(dirName + "/" + fileName);
|
||||
MapleData mdinfo = fileData.getChildByPath("info");
|
||||
if (mdinfo.getChildByPath("cash") == null) {
|
||||
equipsWithNoCashProperty.add(itemId);
|
||||
}
|
||||
} catch (NullPointerException npe) {
|
||||
System.out.println("[SEVERE] " + mFile.getName() + " failed to load. Issue: " + npe.getMessage() + "\n\n");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void readEquipWZData() {
|
||||
String wzFileName = "Character.wz";
|
||||
|
||||
MapleDataProvider data = MapleDataProviderFactory.getDataProvider(WZFiles.CHARACTER);
|
||||
MapleDataDirectoryEntry root = data.getRoot();
|
||||
|
||||
System.out.println("Parsing " + wzFileName + "...");
|
||||
for (MapleDataDirectoryEntry mDir : root.getSubdirectories()) {
|
||||
String dirName = mDir.getName();
|
||||
if (dirName.contentEquals("Dragon")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
readEquipNodeData(data, mDir, wzFileName, dirName);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readItemWZData() {
|
||||
String wzFileName = "Item.wz";
|
||||
|
||||
MapleDataProvider data = MapleDataProviderFactory.getDataProvider(WZFiles.ITEM);
|
||||
MapleDataDirectoryEntry root = data.getRoot();
|
||||
|
||||
System.out.println("Parsing " + wzFileName + "...");
|
||||
for (MapleDataDirectoryEntry mDir : root.getSubdirectories()) {
|
||||
String dirName = mDir.getName();
|
||||
if (dirName.contentEquals("Special")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
curType = getItemTypeFromDirectoryName(dirName);
|
||||
if (!dirName.contentEquals("Pet")) {
|
||||
for (MapleDataFileEntry mFile : mDir.getFiles()) {
|
||||
String fileName = mFile.getName();
|
||||
|
||||
MapleData fileData = data.getData(dirName + "/" + fileName);
|
||||
for (MapleData mData : fileData.getChildren()) {
|
||||
try {
|
||||
int itemId = Integer.parseInt(mData.getName());
|
||||
itemsWithNoNameProperty.put(itemId, curType);
|
||||
itemsWzPath.put(itemId, wzFileName + "/" + dirName + "/" + fileName);
|
||||
} catch (Exception e) {
|
||||
System.out.println("EXCEPTION on '" + mData.getName() + "' " + wzFileName + "/" + dirName + "/" + fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
readEquipNodeData(data, mDir, wzFileName, dirName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleInvalidItemWithNoNameFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
private static void printReportFileResults() {
|
||||
if (!itemsWithNoNameProperty.isEmpty()) {
|
||||
printWriter.println("Itemids with missing 'name' property: ");
|
||||
|
||||
List<Integer> itemids = new ArrayList<>(itemsWithNoNameProperty.keySet());
|
||||
Collections.sort(itemids);
|
||||
|
||||
for (Integer itemid : itemids) {
|
||||
printWriter.println(" " + itemid + " " + itemsWzPath.get(itemid));
|
||||
}
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
if (!equipsWithNoCashProperty.isEmpty()) {
|
||||
printWriter.println("Equipids with missing 'cash' property: ");
|
||||
|
||||
List<Integer> itemids = new ArrayList<>(equipsWithNoCashProperty);
|
||||
Collections.sort(itemids);
|
||||
|
||||
for (Integer itemid : itemids) {
|
||||
printWriter.println(" " + itemid + " " + itemsWzPath.get(itemid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, List<Integer>> filterMissingItemNames() {
|
||||
List<Integer> cashList = new ArrayList<>(20);
|
||||
List<Integer> consList = new ArrayList<>(20);
|
||||
List<Integer> eqpList = new ArrayList<>(20);
|
||||
List<Integer> etcList = new ArrayList<>(20);
|
||||
List<Integer> insList = new ArrayList<>(20);
|
||||
List<Integer> petList = new ArrayList<>(20);
|
||||
|
||||
for (Map.Entry<Integer, ItemType> ids : itemsWithNoNameProperty.entrySet()) {
|
||||
switch (ids.getValue()) {
|
||||
case CASH -> cashList.add(ids.getKey());
|
||||
case CONSUME -> consList.add(ids.getKey());
|
||||
case EQP -> eqpList.add(ids.getKey());
|
||||
case ETC -> etcList.add(ids.getKey());
|
||||
case INS -> insList.add(ids.getKey());
|
||||
case PET -> petList.add(ids.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, List<Integer>> nameTags = new HashMap<>();
|
||||
nameTags.put("Cash.img", cashList);
|
||||
nameTags.put("Consume.img", consList);
|
||||
nameTags.put("Eqp.img", eqpList);
|
||||
nameTags.put("Etc.img", etcList);
|
||||
nameTags.put("Ins.img", insList);
|
||||
nameTags.put("Pet.img", petList);
|
||||
|
||||
return nameTags;
|
||||
}
|
||||
|
||||
private static void printOutputFileHeader() {
|
||||
printWriter.println(" # XML File autogenerated from the MapleInvalidItemWithNoNameFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
private static String getMissingEquipName(int itemid) {
|
||||
String s = nameContentCache.get(itemid);
|
||||
if (s == null) {
|
||||
s = "MISSING NAME " + itemid;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static String getMissingEquipDesc(int itemid) {
|
||||
String s = descContentCache.get(itemid);
|
||||
if (s == null && itemid >= 2000000) { // thanks Halcyon for noticing "missing info" on equips
|
||||
s = "MISSING INFO " + itemid;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static void writeMissingEquipInfo(Integer itemid) {
|
||||
printWriter.println(" <imgdir name=\"" + itemid + "\">");
|
||||
|
||||
String s;
|
||||
s = getMissingEquipName(itemid);
|
||||
printWriter.println(" <string name=\"name\" value=\"" + s + "\"/>");
|
||||
|
||||
s = getMissingEquipDesc(itemid);
|
||||
printWriter.println(" <string name=\"desc\" value=\"" + s + "\"/>");
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
private static void writeEquipSubdirectoryHeader(EquipType eType) {
|
||||
printWriter.println(" <imgdir name=\"" + getStringDirectoryNameFromEquipType(eType) + "\">");
|
||||
}
|
||||
|
||||
private static void writeEquipSubdirectoryFooter() {
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
private static void writeEquipXMLHeader() {
|
||||
printWriter.println(" <imgdir name=\"Eqp\">");
|
||||
}
|
||||
|
||||
private static void writeEquipXMLFooter() {
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
private static void writeMissingItemInfo(Integer itemid) {
|
||||
printWriter.println(" <imgdir name=\"" + itemid + "\">");
|
||||
printWriter.println(" <string name=\"name\" value=\"MISSING NAME\"/>");
|
||||
printWriter.println(" <string name=\"desc\" value=\"MISSING INFO\"/>");
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
private static void writeXMLHeader(String fileName) {
|
||||
printWriter.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
|
||||
printWriter.println("<imgdir name=\"" + fileName + "\">");
|
||||
}
|
||||
|
||||
private static void writeXMLFooter() {
|
||||
printWriter.println("</imgdir>");
|
||||
}
|
||||
|
||||
private static void writeMissingEquipWZNode(EquipType eType, List<Integer> missingNames) {
|
||||
if (!missingNames.isEmpty()) {
|
||||
Collections.sort(missingNames);
|
||||
writeEquipSubdirectoryHeader(eType);
|
||||
|
||||
for (Integer equipid : missingNames) {
|
||||
writeMissingEquipInfo(equipid);
|
||||
}
|
||||
|
||||
writeEquipSubdirectoryFooter();
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeMissingStringWZNode(String nodePath, List<Integer> missingNames, boolean isEquip) {
|
||||
if (!missingNames.isEmpty()) {
|
||||
if (!isEquip) {
|
||||
Collections.sort(missingNames);
|
||||
|
||||
printWriter.println(nodePath + ":");
|
||||
printWriter.println();
|
||||
|
||||
writeXMLHeader(nodePath);
|
||||
|
||||
for (Integer i : missingNames) {
|
||||
writeMissingItemInfo(i);
|
||||
}
|
||||
|
||||
writeXMLFooter();
|
||||
|
||||
printWriter.println();
|
||||
} else {
|
||||
int arraySize = EquipType.values().length;
|
||||
|
||||
List<Integer>[] equips = new List[arraySize];
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
equips[i] = new ArrayList<>(42);
|
||||
}
|
||||
|
||||
for (Integer itemid : missingNames) {
|
||||
equips[equipTypes.get(itemid).ordinal()].add(itemid);
|
||||
}
|
||||
|
||||
printWriter.println(nodePath + ":");
|
||||
printWriter.println();
|
||||
|
||||
writeXMLHeader(nodePath);
|
||||
writeEquipXMLHeader();
|
||||
|
||||
for (EquipType eType : EquipType.values()) {
|
||||
writeMissingEquipWZNode(eType, equips[eType.ordinal()]);
|
||||
}
|
||||
|
||||
writeEquipXMLFooter();
|
||||
writeXMLFooter();
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeMissingStringWZNames(Map<String, List<Integer>> missingNames) throws Exception {
|
||||
System.out.println("Writing remaining 'String.wz' names...");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_XML_FILE, StandardCharsets.UTF_8);
|
||||
printOutputFileHeader();
|
||||
|
||||
String[] nodePaths = {"Cash.img", "Consume.img", "Eqp.img", "Etc.img", "Ins.img", "Pet.img"};
|
||||
for (int i = 0; i < nodePaths.length; i++) {
|
||||
writeMissingStringWZNode(nodePaths[i], missingNames.get(nodePaths[i]), i == 2);
|
||||
}
|
||||
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
curType = ItemType.EQP;
|
||||
readEquipWZData();
|
||||
|
||||
curType = ItemType.UNDEF;
|
||||
readItemWZData();
|
||||
readStringWZData(); // calculates the diff and effectively holds all items with no name property on the WZ
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
printReportFileHeader();
|
||||
printReportFileResults();
|
||||
printWriter.close();
|
||||
|
||||
Map<String, List<Integer>> missingNames = filterMissingItemNames();
|
||||
writeMissingStringWZNames(missingNames);
|
||||
|
||||
System.out.println("Done!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user