[Add-On]Preload Item Information / Organized MapleItemInformationProvider
Notes:
~ You will have to alter some of the existing methods in MapleItemInformationProvider (see examples below).
~ This will point out properties in the WZ files that you may be missing. (Useful if you're upgrading versions or something ...)
~ Make sure you review the properties I have ignored (Also take a look at the ToDos).
~ This was done using v55/v75 WZ files as a guide, so you may need to add/alter some things. (In particular, I think the String.wz is different. In v55, all the names are in Item.img but v75+ splits it into Eqp.img, Consume.img, Cash.img, etc)
~ Adds about 15 seconds to startup.
~ No more 50 different HashMaps :D
Might be useless to you, but oh well. Enjoy ~
In MapleItemInformationProvider.java:
PHP Code:
protected static MapleDataProvider itemData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/Item.wz"));
protected static MapleDataProvider equipData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/Character.wz"));
protected static MapleData stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz")).getData("Item.img");
protected static MapleDataProvider strData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("net.sf.odinms.wzpath") + "/String.wz"));
protected static Map<Integer, MapleItemInfo> itemCache = new HashMap<Integer, MapleItemInfo>();
protected static Map<Integer, Equip> equipCache = new HashMap<Integer, Equip>(); //We'll cache Equips for fast copying.
protected static Map<Integer, MapleStatEffect> itemEffects = new HashMap<Integer, MapleStatEffect>(); //Convert ...
protected static Map<Integer, String> itemNameCache = new LinkedHashMap<Integer, String>(); //We keep this copy so we can do !search more easily
protected static Map<Integer, String> itemDescCache = new LinkedHashMap<Integer, String>();
protected static Map<Integer, String> itemMsgCache = new LinkedHashMap<Integer, String>();
public static class MapleItemInfo {
public static class MapleItemInfoException extends RuntimeException {
MapleItemInfoException(String s) {
super(s);
}
}
/**
* I think this is an awful way to do it ... Must figure out better solution ... ~ Emilyx3
*/
// <editor-fold defaultstate="collapsed" desc="Value Wrappers">
public static abstract class MapleItemPropertyValue {
public boolean getBooleanValue() {
throw new MapleItemInfoException("Tried to get Boolean from " + this.getClass());
}
public int getIntegerValue() {
throw new MapleItemInfoException("Tried to get Integer from " + this.getClass());
}
public double getDoubleValue() {
throw new MapleItemInfoException("Tried to get Double from " + this.getClass());
}
public float getFloatValue() {
throw new MapleItemInfoException("Tried to get Float from " + this.getClass());
}
}
//We could just shove this float into a Double...
public static class FloatMapleItemPropertyValue extends MapleItemPropertyValue {
private float val;
public FloatMapleItemPropertyValue(float f) {
val = f;
}
@Override
public float getFloatValue() {
return val;
}
}
public static class BooleanMapleItemPropertyValue extends MapleItemPropertyValue {
private boolean val;
public BooleanMapleItemPropertyValue(boolean b) {
val = b;
}
@Override
public boolean getBooleanValue() {
return val;
}
}
public static class IntegerMapleItemPropertyValue extends MapleItemPropertyValue {
private int val;
public IntegerMapleItemPropertyValue(int i) {
val = i;
}
@Override
public int getIntegerValue() {
return val;
}
}
public static class DoubleMapleItemPropertyValue extends MapleItemPropertyValue {
private double val;
public DoubleMapleItemPropertyValue(double d) {
val = d;
}
@Override
public double getDoubleValue() {
return val;
}
}// </editor-fold>
public static enum MapleItemProperty {
// <editor-fold defaultstate="collapsed" desc="All Properties">
type("type", new IntegerMapleItemPropertyValue(-1)), //I totally don't know what this is... But it's a pretty common prop
isQuestItem("quest", new BooleanMapleItemPropertyValue(false)),
maximumSlotCapacity("slotMax", new IntegerMapleItemPropertyValue(1)), //Dunno if Default should be 1
shopSellingPrice("price", new IntegerMapleItemPropertyValue(0)),
isPickupBlocked("pickUpBlock", new BooleanMapleItemPropertyValue(false)),
isOneOfAKind("only", new BooleanMapleItemPropertyValue(false)),
isUntradeable("tradeBlock", new BooleanMapleItemPropertyValue(false)),
isPartyQuestItem("pquest", new BooleanMapleItemPropertyValue(false)),
isCashItem("cash", new BooleanMapleItemPropertyValue(false)),
isNotForSaleToNPCs("notSale", new BooleanMapleItemPropertyValue(false)),
requiredLevel("reqLevel", new IntegerMapleItemPropertyValue(0)), //Ex: Throwing Stars
unitPrice("unitPrice", new DoubleMapleItemPropertyValue(-1)), //For recharging bullets, 0 standard? iono....
//ToDo: Give the things beyond this point more descriptive names. These will suffice for now.
//Mostly used for scrolls. incPAD also appears in throwing stars (Lulwut). I think some buff pots too.
incPAD("incPAD", new IntegerMapleItemPropertyValue(0)), //Wep Atk
incMAD("incMAD", new IntegerMapleItemPropertyValue(0)), //Mag Atk
incPDD("incPDD", new IntegerMapleItemPropertyValue(0)), //Wep Def
incMDD("incMDD", new IntegerMapleItemPropertyValue(0)), //Mag Def
incACC("incACC", new IntegerMapleItemPropertyValue(0)),
incEVA("incEVA", new IntegerMapleItemPropertyValue(0)),
incSpeed("incSpeed", new IntegerMapleItemPropertyValue(0)),
incJump("incJump", new IntegerMapleItemPropertyValue(0)),
incMHP("incMHP", new IntegerMapleItemPropertyValue(0)),
incMMP("incMMP", new IntegerMapleItemPropertyValue(0)),
incSTR("incSTR", new IntegerMapleItemPropertyValue(0)),
incINT("incINT", new IntegerMapleItemPropertyValue(0)),
incDEX("incDEX", new IntegerMapleItemPropertyValue(0)),
incLUK("incLUK", new IntegerMapleItemPropertyValue(0)),
incReqLevel("incReqLevel", new IntegerMapleItemPropertyValue(0)),
//Purely used in scrolls.
success("success", new IntegerMapleItemPropertyValue(0)),
cursed("cursed", new IntegerMapleItemPropertyValue(0)), //Compare with "curse" below
//The following appear largely in Consume(Use) Potions
mp("mp", new IntegerMapleItemPropertyValue(0)), //(HP Recover)
hp("hp", new IntegerMapleItemPropertyValue(0)), //(MP Recover)
hpR("hpR", new IntegerMapleItemPropertyValue(0)), //(HP Percentage Recover(Or Decrease if negative))
mpR("mpR", new IntegerMapleItemPropertyValue(0)), //(MP Percentage Recover(Or Decrease if negative))
time("time", new IntegerMapleItemPropertyValue(-1)), //(Duration for Pot [Milliseconds])
eva("eva", new IntegerMapleItemPropertyValue(0)), //Avoid
speed("speed", new IntegerMapleItemPropertyValue(0)),
jump("jump", new IntegerMapleItemPropertyValue(0)),
mad("mad", new IntegerMapleItemPropertyValue(0)), //Matk
pad("pad", new IntegerMapleItemPropertyValue(0)), //Watk
acc("acc", new IntegerMapleItemPropertyValue(0)),
pdd("pdd", new IntegerMapleItemPropertyValue(0)), //WDef
mdd("mdd", new IntegerMapleItemPropertyValue(0)), //MDef
thaw("thaw", new IntegerMapleItemPropertyValue(0)), //(Cold Time Damage Reduction [Positive Number?]) (Negative Number? - Air Bubble)
moveTo("moveTo", new IntegerMapleItemPropertyValue(999999999)), //Return Scrolls [val: 999999999 (nearest town)]
// The following are Monster Carnival things. We don't have MC yet, but let's put these properties in anyway.
consumeOnPickup("consumeOnPickup", new BooleanMapleItemPropertyValue(false)), //Might also be in some Non-Monster Carnival things
cp("cp", new IntegerMapleItemPropertyValue(0)),
party("party", new BooleanMapleItemPropertyValue(false)), //(Effect on entire party)
//The following are debuff removal things. They appear in other pots besides the Monster Carnival ones.
poison("poison", new BooleanMapleItemPropertyValue(false)), //If 1/True, this item will REMOVE poison
seal("seal", new BooleanMapleItemPropertyValue(false)), //If 1/True, this item will REMOVE seal
darkness("darkness", new BooleanMapleItemPropertyValue(false)),
weakness("weakness", new BooleanMapleItemPropertyValue(false)),
curse("curse", new BooleanMapleItemPropertyValue(false)), //Compare with "cursed" above
nuffSkill("nuffSkill", new IntegerMapleItemPropertyValue(0)), //If 1/True, this item will REMOVE helpful buffs.
/*
val = 8 (Dispel buffs for one person [in other party])
val = 9 (Dispel buffs for entire opposing party)
val = 3 (Stun 1 person in opposing party)
*/
//Chair recover rates
recoveryHP("recoveryHP", new IntegerMapleItemPropertyValue(0)),
recoveryMP("recoveryMP", new IntegerMapleItemPropertyValue(0)),
// === Equip Properties ===
reqJob("reqJob", new IntegerMapleItemPropertyValue(0)),
reqSTR("reqSTR", new IntegerMapleItemPropertyValue(0)),
reqINT("reqINT", new IntegerMapleItemPropertyValue(0)),
reqDEX("reqDEX", new IntegerMapleItemPropertyValue(0)),
reqLUK("reqLUK", new IntegerMapleItemPropertyValue(0)),
reqFame("reqPOP", new IntegerMapleItemPropertyValue(0)),
upgradeSlots("tuc", new IntegerMapleItemPropertyValue(0)),
recovery("recovery", new FloatMapleItemPropertyValue(0)),
tamingMob("tamingMob", new IntegerMapleItemPropertyValue(-1)),
expireOnLogout("expireOnLogout", new BooleanMapleItemPropertyValue(false)), //Kewl?
knockback("knockback", new IntegerMapleItemPropertyValue(0)), //Yes, integer percentage. Bow thingy...
attackSpeed("attackSpeed", new IntegerMapleItemPropertyValue(0)), //Weapon thing... Might be useful. Seems to be integer
fs("fs", new IntegerMapleItemPropertyValue(0)), //Something to do with not slipping on ice... 'Flags' perhaps?
;// </editor-fold>
public static final Map<String, MapleItemProperty> namePropertyMap = new HashMap<String, MapleItemProperty>();
static {
for (MapleItemProperty prop : MapleItemProperty.values()) {
namePropertyMap.put(prop.propNameInXML.toLowerCase(), prop);
}
}
private String propNameInXML;
private MapleItemPropertyValue def;
public static MapleItemProperty getPropertyByXMLName(String xmlName) {
return namePropertyMap.get(xmlName.toLowerCase());
}
MapleItemProperty(String propName, MapleItemPropertyValue defaultVal) {
propNameInXML = propName;
def = defaultVal;
}
public MapleItemPropertyValue getDefaultValue() {
return def;
}
}
private MapleInventoryType invType;
private String itemName;
private int itemId;
private Map<MapleItemProperty, MapleItemPropertyValue> itemProperties = new EnumMap<MapleItemProperty, MapleItemPropertyValue>(MapleItemProperty.class);
private static final HashSet<String> ignoreProp = new HashSet<String>();
static {
//We don't care about these properties, kekeke
//// <editor-fold defaultstate="collapsed" desc="!!! Ignored Property Explanations !!!">
// if (!prop.getName().equalsIgnoreCase("icon") //Image
// && !prop.getName().equalsIgnoreCase("iconRaw") //Image
// && !prop.getName().equalsIgnoreCase("noFlip") //No flipping idea ... >_>;;
// && !prop.getName().equalsIgnoreCase("soldInform") //Cash Player Shop NPC Info ... Don't care
// && !prop.getName().equalsIgnoreCase("path") //Seems to point to a path in the WZ files ... Don't care
//
// && !prop.getName().equalsIgnoreCase("floattype") //Has something to do with weather (Related to "path")
// && !prop.getName().equalsIgnoreCase("direction") //Also has something to do with weather... I think it's also in some chairs
// && !prop.getName().equalsIgnoreCase("speed") //Another weather thing. Also appears in some other places too.
//
// //Pet equip stuff I think
// && !prop.getName().equalsIgnoreCase("pickupItem")
// && !prop.getName().equalsIgnoreCase("add")
// && !prop.getName().equalsIgnoreCase("consumeHP")
// && !prop.getName().equalsIgnoreCase("consumeMP")
// && !prop.getName().equalsIgnoreCase("dropSweep")
// && !prop.getName().equalsIgnoreCase("longRange")
// && !prop.getName().equalsIgnoreCase("pickupAll")
// && !prop.getName().equalsIgnoreCase("ignorePickup")
// && !prop.getName().equalsIgnoreCase("meso") //Bronze, silver, gold meso sacks value =P
//
// && !prop.getName().equalsIgnoreCase("rate") //Double Exp/Meso Coupon related thingy
//
// && !prop.getName().equalsIgnoreCase("timeLimited") //Dunno
//
// //Pet Food
// && !prop.getName().equalsIgnoreCase("0")
// && !prop.getName().equalsIgnoreCase("1")
// && !prop.getName().equalsIgnoreCase("2")
// && !prop.getName().equalsIgnoreCase("3")
// && !prop.getName().equalsIgnoreCase("4")
// && !prop.getName().equalsIgnoreCase("5")
// && !prop.getName().equalsIgnoreCase("6")
// && !prop.getName().equalsIgnoreCase("7")
// && !prop.getName().equalsIgnoreCase("8")
// && !prop.getName().equalsIgnoreCase("9")
// && !prop.getName().equalsIgnoreCase("inc")
// && !prop.getName().equalsIgnoreCase("life") //Water Of Life
// && !prop.getName().equalsIgnoreCase("pachinko") //Something for pachinko... dun care
// && !prop.getName().equalsIgnoreCase("morph") //Morphs.. dun care
// && !prop.getName().equalsIgnoreCase("mcType") //Something with Monster Carnivals?
// && !prop.getName().equalsIgnoreCase("sample") //An image thingy.. I think
// && !prop.getName().equalsIgnoreCase("emotion") //Smega's emotion
//
// //Skill book stuff I think
// && !prop.getName().equalsIgnoreCase("masterLevel")
// && !prop.getName().equalsIgnoreCase("skill")
// && !prop.getName().equalsIgnoreCase("reqSkillLevel")
//
//
// && !prop.getName().equalsIgnoreCase("iconReward") //Wtf?
// && !prop.getName().equalsIgnoreCase("distanceX") //Chair thingy
// && !prop.getName().equalsIgnoreCase("distanceY") //Chair thingy
// && !prop.getName().equalsIgnoreCase("maxDiff") //Chair thingy
//
// )// </editor-fold>
String[] ignore = new String[]{
"icon", "iconRaw", "noFlip", "soldInform", "path", "floattype", "direction", "speed", "pickupItem", "add", "consumeHP", "consumeMP", "dropSweep", "longRange", "pickupAll", "ignorePickup", "meso", "rate", "timeLimited", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "inc", "life", "pachinko", "morph", "mcType", "sample", "emotion", "masterLevel", "skill", "reqSkillLevel", "iconReward", "distanceX", "distanceY", "maxDiff", //See above
"islot", "vslot", //In equips, this probably indicates what slot the equip goes in. We don't care, we hardcode these.
"effect", //Some equips link to effect images ...
"nametag", "chatBalloon", //Related to Equip name label/chat balloon rings.
"pickupMeso", "pickupOthers", "sweepForDrop", //Related to some pet equips
"incSwim", "incFatigue", "hpRecovery", "mpRecovery", //Mount things...
"sfx", "walk", "afterImage", "attack", "stand", //Weapon Stuff
};
for (String s : ignore) {
ignoreProp.add(s.toLowerCase());
}
}
public MapleItemPropertyValue getPropertyValue(MapleItemProperty prop) {
MapleItemPropertyValue val = itemProperties.get(prop);
if (val == null) {
val = prop.getDefaultValue();
}
return val;
}
public MapleItemInfo(int itemID, String name, MapleInventoryType iType, MapleData data) {
itemId = itemID;
itemName = name;
invType = iType;
for (MapleData imgDir : data.getChildren()) {
//Info - Contains general info
//Spec - Extra data, usually for Consume(Use) items
if (imgDir.getName().equalsIgnoreCase("info") || imgDir.getName().equalsIgnoreCase("spec")) {
for (MapleData prop : imgDir.getChildren()) {
MapleItemProperty propertyKey = MapleItemProperty.getPropertyByXMLName(prop.getName());
if (propertyKey != null) {
if (prop.getData() instanceof Integer || prop.getData() instanceof Double || prop.getData() instanceof String || prop.getData() instanceof Float) {
MapleItemPropertyValue propertyValue = null; // = new MapleItemPropertyValue(prop.getData());
if (propertyKey.getDefaultValue() instanceof BooleanMapleItemPropertyValue) { //HACKY~! T-T
int i = MapleDataTool.getIntConvert(prop);
if (i == 0) {
propertyValue = new BooleanMapleItemPropertyValue(Boolean.FALSE);
} else if (i == 1) {
propertyValue = new BooleanMapleItemPropertyValue(Boolean.TRUE);
} else {
throw new MapleItemInfoException("Boolean property expected for prop " + prop.getName() + " in Item " + itemId + ". Got integer: " + i);
}
} else if (propertyKey.getDefaultValue() instanceof IntegerMapleItemPropertyValue) {
propertyValue = new IntegerMapleItemPropertyValue(MapleDataTool.getIntConvert(prop));
} else if (propertyKey.getDefaultValue() instanceof DoubleMapleItemPropertyValue) {
propertyValue = new DoubleMapleItemPropertyValue(MapleDataTool.getDoubleConvert(prop));
} else if (propertyKey.getDefaultValue() instanceof FloatMapleItemPropertyValue) {
propertyValue = new FloatMapleItemPropertyValue((Float) prop.getData());
}
if (propertyValue != null) {
itemProperties.put(propertyKey, propertyValue);
}
} else if (prop.getData() == null) {
if (propertyKey.propNameInXML.equalsIgnoreCase("time")) {
//2x Coupons have this funky "time" imgdir >_>;;
} else if (propertyKey.propNameInXML.equalsIgnoreCase("jump")) {
//Some items have an imgDir with this... wtf?!
} else {
System.out.println("[MapleItemInformation Warning] Null Data for Item " + itemId + " (Prop: " + propertyKey.propNameInXML + ")");
}
} else {
System.out.println("Interesting Data Type " + prop.getData().getClass() + " (Prop: " + propertyKey.propNameInXML + ")");
}
} else {
if (!ignoreProp.contains(prop.getName().toLowerCase()))
{
System.out.println("Missing Enumeration for MapleItemProperty " + prop.getName());
}
}
}
} else if (imgDir.getName().equalsIgnoreCase("bullet")) { //If exists, is a bullet
} else if (imgDir.getName().equalsIgnoreCase("mob")) { //Contains info for summoning bags
} else if (imgDir.getName().equalsIgnoreCase("effect")) { //Seems to contain images for effect items (Like the star or moon floating over your head)
} else if (imgDir.getName().equalsIgnoreCase("effect2")) { //Effect2 ? Luls.
} else if (imgDir.getName().equalsIgnoreCase("hit")) { //Image information (For things like bullets or throwing stars)
} else if (imgDir.getName().equalsIgnoreCase("employee")) { //Information for the Cash Player Shop NPCs
} else if (imgDir.getName().equalsIgnoreCase("skin")) { //Information for the Cash Player Shop NPCs Too (I think)
} else if (imgDir.getName().equalsIgnoreCase("iconReward")) { //Probably more image information ... We just don't care ;D
} else if (imgDir.getName().equalsIgnoreCase("book")) { //Dun care..?
} else if (imgDir.getName().equalsIgnoreCase("req")) { //Something....
} else {
if (iType == MapleInventoryType.EQUIP) {
//Equips have a crap load of weird imgDirs ... Probably image data.
//TODO: Put these into a HashSet
if (!imgDir.getName().equalsIgnoreCase("default")
&& !imgDir.getName().equalsIgnoreCase("blink")
&& !imgDir.getName().equalsIgnoreCase("smile")
&& !imgDir.getName().equalsIgnoreCase("troubled")
&& !imgDir.getName().equalsIgnoreCase("cry")
&& !imgDir.getName().equalsIgnoreCase("ngry")
&& !imgDir.getName().equalsIgnoreCase("bewildered")
&& !imgDir.getName().equalsIgnoreCase("stunned")
&& !imgDir.getName().equalsIgnoreCase("vomit")
&& !imgDir.getName().equalsIgnoreCase("oops")
&& !imgDir.getName().equalsIgnoreCase("cheers")
&& !imgDir.getName().equalsIgnoreCase("chu")
&& !imgDir.getName().equalsIgnoreCase("wink")
&& !imgDir.getName().equalsIgnoreCase("pain")
&& !imgDir.getName().equalsIgnoreCase("glitter")
&& !imgDir.getName().equalsIgnoreCase("shine")
&& !imgDir.getName().equalsIgnoreCase("blaze")
&& !imgDir.getName().equalsIgnoreCase("love")
&& !imgDir.getName().equalsIgnoreCase("despair")
&& !imgDir.getName().equalsIgnoreCase("hum")
&& !imgDir.getName().equalsIgnoreCase("bowing")
&& !imgDir.getName().equalsIgnoreCase("hot")
&& !imgDir.getName().equalsIgnoreCase("dam")
&& !imgDir.getName().equalsIgnoreCase("angry")
//Movement image stuff X-x
&& !imgDir.getName().equalsIgnoreCase("prone")
&& !imgDir.getName().equalsIgnoreCase("heal")
&& !imgDir.getName().equalsIgnoreCase("fly")
&& !imgDir.getName().equalsIgnoreCase("jump")
&& !imgDir.getName().equalsIgnoreCase("sit")
&& !imgDir.getName().equalsIgnoreCase("walk1")
&& !imgDir.getName().equalsIgnoreCase("walk2")
&& !imgDir.getName().equalsIgnoreCase("stand1")
&& !imgDir.getName().equalsIgnoreCase("stand2")
&& !imgDir.getName().equalsIgnoreCase("alert")
&& !imgDir.getName().equalsIgnoreCase("swingO1")
&& !imgDir.getName().equalsIgnoreCase("swingO2")
&& !imgDir.getName().equalsIgnoreCase("swingO3")
&& !imgDir.getName().equalsIgnoreCase("swingOF")
&& !imgDir.getName().equalsIgnoreCase("swingT1")
&& !imgDir.getName().equalsIgnoreCase("swingT2")
&& !imgDir.getName().equalsIgnoreCase("swingT3")
&& !imgDir.getName().equalsIgnoreCase("swingTF")
&& !imgDir.getName().equalsIgnoreCase("swingP1")
&& !imgDir.getName().equalsIgnoreCase("swingP2")
&& !imgDir.getName().equalsIgnoreCase("swingPF")
&& !imgDir.getName().equalsIgnoreCase("stabO1")
&& !imgDir.getName().equalsIgnoreCase("stabO2")
&& !imgDir.getName().equalsIgnoreCase("stabOF")
&& !imgDir.getName().equalsIgnoreCase("stabT1")
&& !imgDir.getName().equalsIgnoreCase("stabT2")
&& !imgDir.getName().equalsIgnoreCase("stabTF")
&& !imgDir.getName().equalsIgnoreCase("shoot1")
&& !imgDir.getName().equalsIgnoreCase("shoot2")
&& !imgDir.getName().equalsIgnoreCase("shootF")
&& !imgDir.getName().equalsIgnoreCase("proneStab")
&& !imgDir.getName().equalsIgnoreCase("rope")
&& !imgDir.getName().equalsIgnoreCase("backDefault")
&& !imgDir.getName().equalsIgnoreCase("ladder")
&& !imgDir.getName().equalsIgnoreCase("tired") //Mount thingy.
//&& !imgDir.getName().startsWith("5000") //In pet equips, there are a whole bunch of pet related data. We don't care.
&& !(Character.isDigit(imgDir.getName().charAt(0)) || Character.isDigit(imgDir.getName().charAt(1))) //The above is also covered by this.
//Also covers the imgDirs "30"-"50", Which iono what those are for..
) {
System.out.println("[MapleItemInformationProvider Warning] Unhandeled Equip imgDir Type " + imgDir.getName());
}
} else {
System.out.println("[MapleItemInformationProvider Warning] Unhandeled imgDir Type " + imgDir.getName());
}
}
}
}
}
public static String stripLeadingZeroes(String in) {
int index = 0;
while (in.charAt(index) == '0') {
index++;
}
if (index > 0) {
return in.substring(index, in.length());
}
return in;
}
private static void loadStringDataCache(Map<Integer, String> store) {
//String.wz/Item.img.xml
for (MapleData data : stringData.getChildren()) {
//QQ... I can't think of better names than data1, data2, data3... Sowwiess
//Equips go deeper F3.
if (data.getName().equalsIgnoreCase("Eqp")) {
int minID = Integer.parseInt(data.getChildren().get(0).getChildren().get(0).getName()); //Lol Hacky :D
int maxID = Integer.parseInt(data.getChildren().get(0).getChildren().get(0).getName());
for (MapleData data2 : data.getChildren()) {
int innerMinID = Integer.parseInt(data2.getChildren().get(0).getName());
int innerMaxID = Integer.parseInt(data2.getChildren().get(0).getName());
for (MapleData data3 : data2.getChildren()) {
int itemId = Integer.parseInt(data3.getName());
if (itemId < minID) {
minID = itemId;
}
if (itemId > maxID) {
maxID = itemId;
}
if (itemId < innerMinID) {
innerMinID = itemId;
}
if (itemId > innerMaxID) {
innerMaxID = itemId;
}
for (MapleData stringInfo : data3.getChildren()) {
if (stringInfo.getName().equals("name")) { //Item Name
String name = (String) stringInfo.getData();
store.put(itemId, name);
} else if (stringInfo.getName().equals("desc")) { //Item Description
String desc = (String) stringInfo.getData();
itemDescCache.put(itemId, desc);
} else if (stringInfo.getName().equals("msg")) { //Item Description
String msg = (String) stringInfo.getData();
itemMsgCache.put(itemId, msg);
}
}
}
System.out.println("[MapleItemInformationProvider] Eqp/" + data2.getName() + " range: [" + innerMinID + " - " + innerMaxID + "]");
}
System.out.println("[MapleItemInformationProvider] " + data.getName() + " range: [" + minID + " - " + maxID + "]");
} else {
int minID = Integer.parseInt(data.getChildren().get(0).getName());
int maxID = Integer.parseInt(data.getChildren().get(0).getName());
for (MapleData data2 : data.getChildren()) {
int itemId = Integer.parseInt(data2.getName());
if (itemId < minID) {
minID = itemId;
}
if (itemId > maxID) {
maxID = itemId;
}
for (MapleData stringInfo : data2.getChildren()) {
if (stringInfo.getName().equals("name")) { //Item Name
String name = (String) stringInfo.getData();
store.put(itemId, name);
} else if (stringInfo.getName().equals("desc")) { //Item Description
//We don't use item descriptions... so...
}
}
}
System.out.println("[MapleItemInformationProvider] " + data.getName() + " range: [" + minID + " - " + maxID + "]");
}
}
}
public static void loadCache() {
System.out.println("[MapleItemInformationProvider] Caching item properties ...");
long timeStart = System.currentTimeMillis();
//Load item names first ...
loadStringDataCache(itemNameCache);
//Load non-Equip Items.
MapleDataDirectoryEntry itemWZDir = itemData.getRoot();
for (MapleDataDirectoryEntry itemTypeDir : itemWZDir.getSubdirectories()) {
if (itemTypeDir.getName().equals("Special")) { //This has some funky stuff... Ignore..
continue;
}
//Folders: Cash, Consume, Etc, Install, Pet
System.out.println("[MapleItemInformationProvider] Caching directory : " + itemTypeDir.getName());
for (MapleDataFileEntry xmlFile : itemTypeDir.getFiles()) {
MapleData xmlData = itemData.getData(itemTypeDir.getName() + "\\" + xmlFile.getName());
// //Skip Item.wz/Special/MaplePoint.img.xml
// //It doesn't seem to have meaningful data.
// if (xmlData.getName().equalsIgnoreCase("MaplePoint.img")) {
// continue;
// }
//The Pet folder is different.
//Pets are directly put in as 5000XXX.img.xml - Each contains 1 Pet
//The other folders are done as XXX.img.xml - Each (usually) contains multiple items.
if (itemTypeDir.getName().equalsIgnoreCase("Pet")) {
//ToDo: Do we care about pet data?
} else {
System.out.println("[MapleItemInformationProvider] Caching " + xmlData.getName() + " ...");
for (MapleData itmData : xmlData.getChildren()) {
int itemid;
try {
itemid = Integer.parseInt(stripLeadingZeroes(itmData.getName()));
String name = itemNameCache.get(itemid);
if (name == null) {
name = "";
System.out.println("[MapleItemInformationProvider Warning] Item Name information not found for item " + itemid);
}
itemCache.put(itemid, new MapleItemInfo(itemid, name, getInventoryType(itemid), itmData));
} catch (NumberFormatException nfe) {
System.out.println("[MapleItemInformationProvider Error] Could not parse itemid from " + itemTypeDir.getName() + "\\" + xmlFile.getName() + " " + itmData.getName());
}
}
}
}
}
//Load Equips
MapleDataDirectoryEntry equipWZDir = equipData.getRoot();
for (MapleDataDirectoryEntry equipTypeDir : equipWZDir.getSubdirectories()) {
if (equipTypeDir.getName().equalsIgnoreCase("Afterimage")
|| equipTypeDir.getName().equalsIgnoreCase("Hair")
|| equipTypeDir.getName().equalsIgnoreCase("Face")) { //These are not equips ;D
continue;
}
System.out.println("[MapleItemInformationProvider] Caching Equip directory : " + equipTypeDir.getName() + " ...");
for (MapleDataFileEntry xmlFile : equipTypeDir.getFiles()) {
MapleData xmlData = equipData.getData(equipTypeDir.getName() + "\\" + xmlFile.getName());
int itemid;
try {
itemid = Integer.parseInt(stripLeadingZeroes(xmlData.getName().substring(0, xmlData.getName().indexOf(".img")))); //Stupid Nexon... They add a ".img" inside the XML
String name = itemNameCache.get(itemid);
if (name == null) {
name = "";
System.out.println("[MapleItemInformationProvider Warning] Equip Name information not found for equip " + itemid);
}
MapleItemInfo eqInf = new MapleItemInfo(itemid, name, getInventoryType(itemid), xmlData);
itemCache.put(itemid, eqInf);
Equip nEquip = new Equip(itemid, (byte) 0, -1);
nEquip.setQuantity((short) 1);
nEquip.setStr((short) (eqInf.getPropertyValue(MapleItemProperty.incSTR).getIntegerValue()));
nEquip.setDex((short) (eqInf.getPropertyValue(MapleItemProperty.incDEX).getIntegerValue()));
nEquip.setInt((short) (eqInf.getPropertyValue(MapleItemProperty.incINT).getIntegerValue()));
nEquip.setLuk((short) (eqInf.getPropertyValue(MapleItemProperty.incLUK).getIntegerValue()));
nEquip.setWatk((short) (eqInf.getPropertyValue(MapleItemProperty.incPAD).getIntegerValue()));
nEquip.setWdef((short) (eqInf.getPropertyValue(MapleItemProperty.incPDD).getIntegerValue()));
nEquip.setMatk((short) (eqInf.getPropertyValue(MapleItemProperty.incMAD).getIntegerValue()));
nEquip.setMdef((short) (eqInf.getPropertyValue(MapleItemProperty.incMDD).getIntegerValue()));
nEquip.setAcc((short) (eqInf.getPropertyValue(MapleItemProperty.incACC).getIntegerValue()));
nEquip.setAvoid((short) (eqInf.getPropertyValue(MapleItemProperty.incEVA).getIntegerValue()));
nEquip.setSpeed((short) (eqInf.getPropertyValue(MapleItemProperty.incSpeed).getIntegerValue()));
nEquip.setJump((short) (eqInf.getPropertyValue(MapleItemProperty.incJump).getIntegerValue()));
nEquip.setHp((short) (eqInf.getPropertyValue(MapleItemProperty.incMHP).getIntegerValue()));
nEquip.setMp((short) (eqInf.getPropertyValue(MapleItemProperty.incMMP).getIntegerValue()));
nEquip.setUpgradeSlots((byte) (eqInf.getPropertyValue(MapleItemProperty.upgradeSlots).getIntegerValue()));
equipCache.put(itemid, nEquip);
} catch (NumberFormatException nfe) {
System.out.println("[MapleItemInformationProvider Error] Could not parse equip itemid from " + equipTypeDir.getName() + "\\" + xmlData.getName());
}
}
}
System.out.println("[MapleItemInformationProvider] Items Loaded: " + itemCache.size() + " | Time Taken: " + (System.currentTimeMillis() - timeStart));
}
/* returns the inventory type for the specified item id */
public static MapleInventoryType getInventoryType(final int itemId) {
final byte type = (byte) (itemId / 1000000);
if (type < 1 || type > 5) {
return MapleInventoryType.UNDEFINED;
}
return MapleInventoryType.getByType(type);
}
In ChannelServer.java (Or shove this into where your ChannelServer startsup [Only call this method once btw!!!]):
PHP Code:
static {
MapleItemInformationProvider.loadCache();
}
Example Usage (in MapleItemInformationProvider):
PHP Code:
public Item scrollEquipWithId(Item equip, int scrollId, boolean usingWhiteScroll, boolean checkIfGM) {
if (equip instanceof Equip) {
Equip nEquip = (Equip) equip;
MapleItemInfo stats = itemCache.get(scrollId);
if (nEquip.getUpgradeSlots() > 0 && (((Randomizer.getInstance().nextInt(100)) <= stats.getPropertyValue(MapleItemProperty.success).getIntegerValue()) || (checkIfGM == true))) {
nEquip.setStr((short) (nEquip.getStr() + stats.getPropertyValue(MapleItemProperty.incSTR).getIntegerValue()));
nEquip.setDex((short) (nEquip.getDex() + stats.getPropertyValue(MapleItemProperty.incDEX).getIntegerValue()));
nEquip.setInt((short) (nEquip.getInt() + stats.getPropertyValue(MapleItemProperty.incINT).getIntegerValue()));
nEquip.setLuk((short) (nEquip.getLuk() + stats.getPropertyValue(MapleItemProperty.incLUK).getIntegerValue()));
nEquip.setWatk((short) (nEquip.getWatk() + stats.getPropertyValue(MapleItemProperty.incPAD).getIntegerValue()));
nEquip.setWdef((short) (nEquip.getWdef() + stats.getPropertyValue(MapleItemProperty.incPDD).getIntegerValue()));
nEquip.setMatk((short) (nEquip.getMatk() + stats.getPropertyValue(MapleItemProperty.incMAD).getIntegerValue()));
nEquip.setMdef((short) (nEquip.getMdef() + stats.getPropertyValue(MapleItemProperty.incMDD).getIntegerValue()));
nEquip.setAcc((short) (nEquip.getAcc() + stats.getPropertyValue(MapleItemProperty.incACC).getIntegerValue()));
nEquip.setAvoid((short) (nEquip.getAvoid() + stats.getPropertyValue(MapleItemProperty.incEVA).getIntegerValue()));
nEquip.setSpeed((short) (nEquip.getSpeed() + stats.getPropertyValue(MapleItemProperty.incSpeed).getIntegerValue()));
nEquip.setJump((short) (nEquip.getJump() + stats.getPropertyValue(MapleItemProperty.incJump).getIntegerValue()));
nEquip.setHp((short) (nEquip.getHp() + stats.getPropertyValue(MapleItemProperty.incMHP).getIntegerValue()));
nEquip.setMp((short) (nEquip.getMp() + stats.getPropertyValue(MapleItemProperty.incMMP).getIntegerValue()));
if (checkIfGM == false) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
}
nEquip.setLevel((byte) (nEquip.getLevel() + 1));
} else {
if (!usingWhiteScroll) {
nEquip.setUpgradeSlots((byte) (nEquip.getUpgradeSlots() - 1));
}
if (Math.ceil(1.0 + Randomizer.getInstance().nextInt(100)) < stats.getPropertyValue(MapleItemProperty.cursed).getIntegerValue()) {
// DESTROY :) (O.O!)
return null;
}
}
}
return equip;
}
public String getName(int itemId) {
String name = itemNameCache.get(itemId);
if (name != null) {
return name;
}
System.out.println("[MapleItemInformationWarning] Tried to retrieve non-existant item NAME entry. (Possible missing entry in String.wz) ItemID: "+itemId);
return null;
}
public boolean isCashItem(int itemId) {
MapleItemInfo inf = itemCache.get(itemId);
if (inf == null) {
return false;
}
return inf.getPropertyValue(MapleItemProperty.isCashItem).getBooleanValue();
}
Re: Preload Item Information / Organized MapleItemInformationProvider
So basically this will load all the item stats during startup and put them into a HashMap so that it doesn't need to be loaded everytime?
Re: Preload Item Information / Organized MapleItemInformationProvider
Not sure if I understand hashmap alot or what you did, but you get info from xml load 'necessary' property not load all of them and cache the needed items at startup that are inside hashmap o.O?
lmao your coding is belong my knowledge as I read :]
Re: Preload Item Information / Organized MapleItemInformationProvider
I tho it always have been like this, I mean, cached.
Re: Preload Item Information / Organized MapleItemInformationProvider
Quote:
Originally Posted by
XxОsirisxX
I tho it always have been like this, I mean, cached.
It's not :( Look at MapleItemInformationProvider. Each part goes through and gets a new property of the item. Example: isCash or something.
Nice job Emilyx3 though. Looks interesting, but too time-consuming to implement. Nothing is wrong with the old system anyways.