Merge pull request #45 from P0nk/fix-tools
Rework tools: All tools are now part of the main module, thereby avoiding copies of required class files. This should result in quicker builds and searches, since there are no longer a bunch of redundant files to process.
This commit is contained in:
133
.gitignore
vendored
133
.gitignore
vendored
@@ -4,142 +4,9 @@
|
||||
/target
|
||||
|
||||
# build files
|
||||
|
||||
/build/
|
||||
/dist/
|
||||
/nbproject/
|
||||
|
||||
/tools/MapleArrowFetcher/build/
|
||||
/tools/MapleArrowFetcher/dist/
|
||||
/tools/MapleArrowFetcher/nbproject/
|
||||
|
||||
/tools/MapleBossHpBarFetcher/build/
|
||||
/tools/MapleBossHpBarFetcher/dist/
|
||||
/tools/MapleBossHpBarFetcher/nbproject/
|
||||
|
||||
/tools/MapleCashCosmeticsChecker/build/
|
||||
/tools/MapleCashCosmeticsChecker/dist/
|
||||
/tools/MapleCashCosmeticsChecker/nbproject/
|
||||
|
||||
/tools/MapleCashCosmeticsFetcher/build/
|
||||
/tools/MapleCashCosmeticsFetcher/dist/
|
||||
/tools/MapleCashCosmeticsFetcher/nbproject/
|
||||
|
||||
/tools/MapleCashDropFetcher/build/
|
||||
/tools/MapleCashDropFetcher/dist/
|
||||
/tools/MapleCashDropFetcher/nbproject/
|
||||
|
||||
/tools/MapleCashVegaChecker/build/
|
||||
/tools/MapleCashVegaChecker/dist/
|
||||
/tools/MapleCashVegaChecker/nbproject/
|
||||
|
||||
/tools/MapleCodeCouponGenerator/build/
|
||||
/tools/MapleCodeCouponGenerator/dist/
|
||||
/tools/MapleCodeCouponGenerator/nbproject/
|
||||
|
||||
/tools/MapleCouponInstaller/build/
|
||||
/tools/MapleCouponInstaller/dist/
|
||||
/tools/MapleCouponInstaller/nbproject/
|
||||
|
||||
/tools/MapleDojoUpdater/build/
|
||||
/tools/MapleDojoUpdater/dist/
|
||||
/tools/MapleDojoUpdater/nbproject/
|
||||
|
||||
/tools/MapleEmptyItemWzChecker/build/
|
||||
/tools/MapleEmptyItemWzChecker/dist/
|
||||
/tools/MapleEmptyItemWzChecker/nbproject/
|
||||
|
||||
/tools/MapleEquipmentOmnileveler/build/
|
||||
/tools/MapleEquipmentOmnileveler/dist/
|
||||
/tools/MapleEquipmentOmnileveler/nbproject/
|
||||
|
||||
/tools/MapleEventMethodFiller/build/
|
||||
/tools/MapleEventMethodFiller/dist/
|
||||
/tools/MapleEventMethodFiller/nbproject/
|
||||
|
||||
/tools/MapleGachaponItemidRetriever/build/
|
||||
/tools/MapleGachaponItemidRetriever/dist/
|
||||
/tools/MapleGachaponItemidRetriever/nbproject/
|
||||
|
||||
/tools/MapleIdRetriever/build/
|
||||
/tools/MapleIdRetriever/dist/
|
||||
/tools/MapleIdRetriever/nbproject/
|
||||
|
||||
/tools/MapleInvalidItemIdFetcher/build/
|
||||
/tools/MapleInvalidItemIdFetcher/dist/
|
||||
/tools/MapleInvalidItemIdFetcher/nbproject/
|
||||
|
||||
/tools/MapleInvalidItemWithNoNameFetcher/build/
|
||||
/tools/MapleInvalidItemWithNoNameFetcher/dist/
|
||||
/tools/MapleInvalidItemWithNoNameFetcher/nbproject/
|
||||
|
||||
/tools/MapleMapFieldLimitChecker/build/
|
||||
/tools/MapleMapFieldLimitChecker/dist/
|
||||
/tools/MapleMapFieldLimitChecker/nbproject/
|
||||
|
||||
/tools/MapleMapInfoRetriever/build/
|
||||
/tools/MapleMapInfoRetriever/dist/
|
||||
/tools/MapleMapInfoRetriever/nbproject/
|
||||
|
||||
/tools/MapleMapLootLimitChecker/build/
|
||||
/tools/MapleMapLootLimitChecker/dist/
|
||||
/tools/MapleMapLootLimitChecker/nbproject/
|
||||
|
||||
/tools/MapleMesoFetcher/build/
|
||||
/tools/MapleMesoFetcher/dist/
|
||||
/tools/MapleMesoFetcher/nbproject/
|
||||
|
||||
/tools/MapleMobBookIndexer/build/
|
||||
/tools/MapleMobBookIndexer/dist/
|
||||
/tools/MapleMobBookIndexer/nbproject/
|
||||
|
||||
/tools/MapleMobBookUpdate/build/
|
||||
/tools/MapleMobBookUpdate/dist/
|
||||
/tools/MapleMobBookUpdate/nbproject/
|
||||
|
||||
/tools/MapleQuestItemCountFetcher/build/
|
||||
/tools/MapleQuestItemCountFetcher/dist/
|
||||
/tools/MapleQuestItemCountFetcher/nbproject/
|
||||
|
||||
/tools/MapleQuestItemFetcher/build/
|
||||
/tools/MapleQuestItemFetcher/dist/
|
||||
/tools/MapleQuestItemFetcher/nbproject/
|
||||
|
||||
/tools/MapleQuestlineFetcher/build/
|
||||
/tools/MapleQuestlineFetcher/dist/
|
||||
/tools/MapleQuestlineFetcher/nbproject/
|
||||
|
||||
/tools/MapleQuestMesoFetcher/build/
|
||||
/tools/MapleQuestMesoFetcher/dist/
|
||||
/tools/MapleQuestMesoFetcher/nbproject/
|
||||
|
||||
/tools/MapleReactorDropFetcher/build/
|
||||
/tools/MapleReactorDropFetcher/dist/
|
||||
/tools/MapleReactorDropFetcher/nbproject/
|
||||
|
||||
/tools/MapleSkillbookChanceFetcher/build/
|
||||
/tools/MapleSkillbookChanceFetcher/dist/
|
||||
/tools/MapleSkillbookChanceFetcher/nbproject/
|
||||
|
||||
/tools/MapleSkillbookStackUpdate/build/
|
||||
/tools/MapleSkillbookStackUpdate/dist/
|
||||
/tools/MapleSkillbookStackUpdate/nbproject/
|
||||
|
||||
/tools/MapleSkillMakerFetcher/build/
|
||||
/tools/MapleSkillMakerFetcher/dist/
|
||||
/tools/MapleSkillMakerFetcher/nbproject/
|
||||
|
||||
/tools/MapleSkillMakerReagentIndexer/build/
|
||||
/tools/MapleSkillMakerReagentIndexer/dist/
|
||||
/tools/MapleSkillMakerReagentIndexer/nbproject/
|
||||
|
||||
/tools/MapleWorldmapChecker/build/
|
||||
/tools/MapleWorldmapChecker/dist/
|
||||
/tools/MapleWorldmapChecker/nbproject/
|
||||
|
||||
/tools/SpiderDropFetcher/build/
|
||||
/tools/SpiderDropFetcher/dist/
|
||||
/tools/SpiderDropFetcher/nbproject/
|
||||
|
||||
/out
|
||||
*.onetoc2
|
||||
|
||||
5
pom.xml
5
pom.xml
@@ -47,6 +47,11 @@
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency> <!-- only used for some tools -->
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
|
||||
@@ -23,16 +23,16 @@ package client;
|
||||
|
||||
import constants.skills.*;
|
||||
import provider.*;
|
||||
import provider.wz.WZFiles;
|
||||
import server.MapleStatEffect;
|
||||
import server.life.Element;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SkillFactory {
|
||||
private static volatile Map<Integer, Skill> skills = new HashMap<>();
|
||||
private static final MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz"));
|
||||
private static final MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(WZFiles.SKILL);
|
||||
|
||||
public static Skill getSkill(int id) {
|
||||
return skills.get(id);
|
||||
@@ -330,7 +330,7 @@ public class SkillFactory {
|
||||
}
|
||||
|
||||
public static String getSkillName(int skillid) {
|
||||
MapleData data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img");
|
||||
MapleData data = MapleDataProviderFactory.getDataProvider(WZFiles.STRING).getData("Skill.img");
|
||||
StringBuilder skill = new StringBuilder();
|
||||
skill.append(skillid);
|
||||
if (skill.length() == 4) {
|
||||
|
||||
@@ -27,8 +27,7 @@ import client.*;
|
||||
import client.command.Command;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProviderFactory;
|
||||
|
||||
import java.io.File;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
public class MaxSkillCommand extends Command {
|
||||
{
|
||||
@@ -38,7 +37,7 @@ public class MaxSkillCommand extends Command {
|
||||
@Override
|
||||
public void execute(MapleClient c, String[] params) {
|
||||
MapleCharacter player = c.getPlayer();
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(WZFiles.STRING).getData("Skill.img").getChildren()) {
|
||||
try {
|
||||
Skill skill = SkillFactory.getSkill(Integer.parseInt(skill_.getName()));
|
||||
player.changeSkillLevel(skill, (byte) skill.getMaxLevel(), skill.getMaxLevel(), -1);
|
||||
|
||||
@@ -27,8 +27,7 @@ import client.*;
|
||||
import client.command.Command;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProviderFactory;
|
||||
|
||||
import java.io.File;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
public class ResetSkillCommand extends Command {
|
||||
{
|
||||
@@ -38,7 +37,7 @@ public class ResetSkillCommand extends Command {
|
||||
@Override
|
||||
public void execute(MapleClient c, String[] params) {
|
||||
MapleCharacter player = c.getPlayer();
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(WZFiles.STRING).getData("Skill.img").getChildren()) {
|
||||
try {
|
||||
Skill skill = SkillFactory.getSkill(Integer.parseInt(skill_.getName()));
|
||||
player.changeSkillLevel(skill, (byte) 0, skill.getMaxLevel(), -1);
|
||||
|
||||
@@ -30,12 +30,11 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.quest.MapleQuest;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class SearchCommand extends Command {
|
||||
private static MapleData npcStringData;
|
||||
private static MapleData mobStringData;
|
||||
@@ -45,7 +44,7 @@ public class SearchCommand extends Command {
|
||||
{
|
||||
setDescription("Search String.wz.");
|
||||
|
||||
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
|
||||
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
npcStringData = dataProvider.getData("Npc.img");
|
||||
mobStringData = dataProvider.getData("Mob.img");
|
||||
skillStringData = dataProvider.getData("Skill.img");
|
||||
|
||||
@@ -25,8 +25,8 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.Map;
|
||||
* @author Danny (Leifde)
|
||||
*/
|
||||
public class PetDataFactory {
|
||||
private static MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Item.wz"));
|
||||
private static MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(WZFiles.ITEM);
|
||||
private static Map<String, PetCommand> petCommands = new HashMap<>();
|
||||
private static Map<Integer, Integer> petHunger = new HashMap<>();
|
||||
|
||||
|
||||
@@ -20,24 +20,25 @@
|
||||
package client.processor.action;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import java.awt.Point;
|
||||
import client.MapleClient;
|
||||
import client.SkillFactory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.SkillFactory;
|
||||
import provider.MapleDataTool;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import java.io.File;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana - just added locking on OdinMS' SpawnPetHandler method body
|
||||
*/
|
||||
public class SpawnPetProcessor {
|
||||
private static MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Item.wz"));
|
||||
private static final MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(WZFiles.ITEM);
|
||||
|
||||
public static void processSpawnPet(MapleClient c, byte slot, boolean lead) {
|
||||
if (c.tryacquireClient()) {
|
||||
|
||||
@@ -5,11 +5,11 @@ import client.MapleJob;
|
||||
import config.YamlConfig;
|
||||
import constants.skills.Aran;
|
||||
import provider.*;
|
||||
import provider.wz.WZFiles;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.MapleMap;
|
||||
import server.quest.MapleQuest;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
@@ -676,7 +676,7 @@ public class GameConstants {
|
||||
}
|
||||
|
||||
private static int getMaxObstacleMobDamageFromWz() {
|
||||
MapleDataProvider mapSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz"));
|
||||
MapleDataProvider mapSource = MapleDataProviderFactory.getDataProvider(WZFiles.MAP);
|
||||
int maxMobDmg = 0;
|
||||
|
||||
MapleDataDirectoryEntry root = mapSource.getRoot();
|
||||
|
||||
@@ -969,7 +969,6 @@ public class Server {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("wzpath", "wz");
|
||||
Security.setProperty("crypto.policy", "unlimited");
|
||||
AutoJCE.removeCryptographyRestrictions();
|
||||
Server.getInstance().init();
|
||||
|
||||
@@ -34,10 +34,10 @@ import net.server.world.MapleParty;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -68,7 +68,7 @@ public class MaplePartySearchCoordinator {
|
||||
private static Map<Integer, Set<Integer>> fetchNeighbouringMaps() {
|
||||
Map<Integer, Set<Integer>> mapLinks = new HashMap<>();
|
||||
|
||||
MapleData data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "Etc.wz")).getData("MapNeighbors.img");
|
||||
MapleData data = MapleDataProviderFactory.getDataProvider(WZFiles.ETC).getData("MapNeighbors.img");
|
||||
if (data != null) {
|
||||
for (MapleData mapdata : data.getChildren()) {
|
||||
int mapid = Integer.parseInt(mapdata.getName());
|
||||
|
||||
@@ -21,18 +21,18 @@
|
||||
*/
|
||||
package provider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import provider.wz.WZFile;
|
||||
import provider.wz.WZFiles;
|
||||
import provider.wz.XMLWZFile;
|
||||
|
||||
public class MapleDataProviderFactory {
|
||||
private final static String wzPath = System.getProperty("wzpath");
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
private static MapleDataProvider getWZ(File in, boolean provideImages) {
|
||||
public class MapleDataProviderFactory {
|
||||
private static MapleDataProvider getWZ(File in) {
|
||||
if (in.getName().toLowerCase().endsWith("wz") && !in.isDirectory()) {
|
||||
try {
|
||||
return new WZFile(in, provideImages);
|
||||
return new WZFile(in, false);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Loading WZ File failed", e);
|
||||
}
|
||||
@@ -41,15 +41,7 @@ public class MapleDataProviderFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public static MapleDataProvider getDataProvider(File in) {
|
||||
return getWZ(in, false);
|
||||
}
|
||||
|
||||
public static MapleDataProvider getImageProvidingDataProvider(File in) {
|
||||
return getWZ(in, true);
|
||||
}
|
||||
|
||||
public static File fileInWZPath(String filename) {
|
||||
return new File(wzPath, filename);
|
||||
public static MapleDataProvider getDataProvider(WZFiles in) {
|
||||
return getWZ(in.getFile());
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@
|
||||
*/
|
||||
package provider.wz;
|
||||
|
||||
import provider.MapleDataProviderFactory;
|
||||
import tools.data.input.GenericLittleEndianAccessor;
|
||||
import tools.data.input.InputStreamByteStream;
|
||||
import tools.data.input.LittleEndianAccessor;
|
||||
@@ -69,7 +68,7 @@ public class ListWZFile {
|
||||
if (listWz != null) {
|
||||
ListWZFile listwz;
|
||||
try {
|
||||
listwz = new ListWZFile(MapleDataProviderFactory.fileInWZPath("List.wz"));
|
||||
listwz = new ListWZFile(WZFiles.LIST.getFile());
|
||||
modernImgs = new HashSet<>(listwz.getEntries());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
35
src/main/java/provider/wz/WZFiles.java
Normal file
35
src/main/java/provider/wz/WZFiles.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package provider.wz;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public enum WZFiles {
|
||||
QUEST("Quest"),
|
||||
ETC("Etc"),
|
||||
ITEM("Item"),
|
||||
CHARACTER("Character"),
|
||||
STRING("String"),
|
||||
LIST("List"),
|
||||
MOB("Mob"),
|
||||
MAP("Map"),
|
||||
NPC("Npc"),
|
||||
REACTOR("Reactor"),
|
||||
SKILL("Skill"),
|
||||
SOUND("Sound"),
|
||||
UI("UI");
|
||||
|
||||
public static final String DIRECTORY = "wz";
|
||||
|
||||
private final String fileName;
|
||||
|
||||
WZFiles(String name) {
|
||||
this.fileName = name + ".wz";
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return new File(DIRECTORY, fileName);
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return getFile().getPath();
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import net.server.world.MapleParty;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.wz.WZFiles;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import server.*;
|
||||
import server.MapleSkillbookInformationProvider.SkillBookEntry;
|
||||
@@ -62,7 +63,6 @@ import tools.MaplePacketCreator;
|
||||
import tools.packets.Wedding;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
@@ -382,7 +382,7 @@ public class NPCConversationManager extends AbstractPlayerInteraction {
|
||||
}
|
||||
|
||||
public void maxMastery() {
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {
|
||||
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(WZFiles.STRING).getData("Skill.img").getChildren()) {
|
||||
try {
|
||||
Skill skill = SkillFactory.getSkill(Integer.parseInt(skill_.getName()));
|
||||
getPlayer().changeSkillLevel(skill, (byte) 0, skill.getMaxLevel(), -1);
|
||||
|
||||
@@ -31,10 +31,10 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -149,7 +149,7 @@ public class CashShop {
|
||||
private static volatile List<SpecialCashItem> specialcashitems = new ArrayList<>();
|
||||
|
||||
public static void loadAllCashItems() {
|
||||
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
|
||||
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(WZFiles.ETC);
|
||||
|
||||
Map<Integer, CashItem> loadedItems = new HashMap<>();
|
||||
List<Integer> onSaleItems = new ArrayList<>();
|
||||
|
||||
@@ -32,12 +32,12 @@ import constants.skills.Gunslinger;
|
||||
import constants.skills.NightWalker;
|
||||
import net.server.Server;
|
||||
import provider.*;
|
||||
import provider.wz.WZFiles;
|
||||
import server.MakerItemFactory.MakerItemCreateEntry;
|
||||
import server.life.MapleLifeFactory;
|
||||
import server.life.MapleMonsterInformationProvider;
|
||||
import tools.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -116,10 +116,10 @@ public class MapleItemInformationProvider {
|
||||
|
||||
private MapleItemInformationProvider() {
|
||||
loadCardIdData();
|
||||
itemData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Item.wz"));
|
||||
equipData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Character.wz"));
|
||||
stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz"));
|
||||
etcData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Etc.wz"));
|
||||
itemData = MapleDataProviderFactory.getDataProvider(WZFiles.ITEM);
|
||||
equipData = MapleDataProviderFactory.getDataProvider(WZFiles.CHARACTER);
|
||||
stringData = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
etcData = MapleDataProviderFactory.getDataProvider(WZFiles.ETC);
|
||||
cashStringData = stringData.getData("Cash.img");
|
||||
consumeStringData = stringData.getData("Consume.img");
|
||||
eqpStringData = stringData.getData("Eqp.img");
|
||||
|
||||
@@ -24,6 +24,7 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import java.io.File;
|
||||
@@ -115,7 +116,7 @@ public class MapleSkillbookInformationProvider {
|
||||
}
|
||||
|
||||
private static Map<Integer, SkillBookEntry> fetchSkillbooksFromQuests() {
|
||||
MapleDataProvider questDataProvider = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "Quest.wz"));
|
||||
MapleDataProvider questDataProvider = MapleDataProviderFactory.getDataProvider(WZFiles.QUEST);
|
||||
MapleData actData = questDataProvider.getData("Act.img");
|
||||
MapleData checkData = questDataProvider.getData("Check.img");
|
||||
|
||||
|
||||
@@ -29,12 +29,12 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -310,7 +310,7 @@ public class MapleStorage {
|
||||
if(fee == null) {
|
||||
fee = 100;
|
||||
|
||||
MapleDataProvider npc = MapleDataProviderFactory.getDataProvider(new File("wz/Npc.wz"));
|
||||
MapleDataProvider npc = MapleDataProviderFactory.getDataProvider(WZFiles.NPC);
|
||||
MapleData npcData = npc.getData(npcId + ".img");
|
||||
if(npcData != null) {
|
||||
fee = MapleDataTool.getIntConvert("info/trunkPut", npcData, 100);
|
||||
@@ -328,7 +328,7 @@ public class MapleStorage {
|
||||
if(fee == null) {
|
||||
fee = 0;
|
||||
|
||||
MapleDataProvider npc = MapleDataProviderFactory.getDataProvider(new File("wz/Npc.wz"));
|
||||
MapleDataProvider npc = MapleDataProviderFactory.getDataProvider(WZFiles.NPC);
|
||||
MapleData npcData = npc.getData(npcId + ".img");
|
||||
if(npcData != null) {
|
||||
fee = MapleDataTool.getIntConvert("info/trunkGet", npcData, 0);
|
||||
|
||||
@@ -25,12 +25,12 @@ import client.MapleCharacter;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.TimerManager;
|
||||
import server.maps.MapleMap;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Randomizer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class MapleOxQuiz {
|
||||
private int question = 1;
|
||||
private MapleMap map = null;
|
||||
private int expGain = 200;
|
||||
private static MapleDataProvider stringData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Etc.wz"));
|
||||
private static MapleDataProvider stringData = MapleDataProviderFactory.getDataProvider(WZFiles.ETC);
|
||||
|
||||
public MapleOxQuiz(MapleMap map) {
|
||||
this.map = map;
|
||||
|
||||
@@ -26,18 +26,18 @@ import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.MapleDataType;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.Pair;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class MapleLifeFactory {
|
||||
|
||||
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Mob.wz"));
|
||||
private final static MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz"));
|
||||
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(WZFiles.MOB);
|
||||
private final static MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
private static MapleData mobStringData = stringDataWZ.getData("Mob.img");
|
||||
private static MapleData npcStringData = stringDataWZ.getData("Npc.img");
|
||||
private static Map<Integer, MapleMonsterStats> monsterStats = new HashMap<>();
|
||||
@@ -46,7 +46,7 @@ public class MapleLifeFactory {
|
||||
private static Set<Integer> getHpBarBosses() {
|
||||
Set<Integer> ret = new HashSet<>();
|
||||
|
||||
MapleDataProvider uiDataWZ = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/UI.wz"));
|
||||
MapleDataProvider uiDataWZ = MapleDataProviderFactory.getDataProvider(WZFiles.UI);
|
||||
for (MapleData bossData : uiDataWZ.getData("UIWindow.img").getChildByPath("MobGage/Mob").getChildren()) {
|
||||
ret.add(Integer.valueOf(bossData.getName()));
|
||||
}
|
||||
@@ -322,7 +322,7 @@ public class MapleLifeFactory {
|
||||
private int id;
|
||||
private byte chance, x;
|
||||
|
||||
private loseItem(int id, byte chance, byte x) {
|
||||
public loseItem(int id, byte chance, byte x) {
|
||||
this.id = id;
|
||||
this.chance = chance;
|
||||
this.x = x;
|
||||
@@ -347,7 +347,7 @@ public class MapleLifeFactory {
|
||||
private int removeAfter;
|
||||
private int hp;
|
||||
|
||||
private selfDestruction(byte action, int removeAfter, int hp) {
|
||||
public selfDestruction(byte action, int removeAfter, int hp) {
|
||||
this.action = action;
|
||||
this.removeAfter = removeAfter;
|
||||
this.hp = hp;
|
||||
|
||||
@@ -26,12 +26,12 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.Pair;
|
||||
import tools.Randomizer;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -227,7 +227,7 @@ public class MapleMonsterInformationProvider {
|
||||
}
|
||||
|
||||
public static ArrayList<Pair<Integer, String>> getMobsIDsFromName(String search) {
|
||||
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
|
||||
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
ArrayList<Pair<Integer, String>> retMobs = new ArrayList<>();
|
||||
MapleData data = dataProvider.getData("Mob.img");
|
||||
List<Pair<Integer, String>> mobPairList = new LinkedList<>();
|
||||
@@ -267,7 +267,7 @@ public class MapleMonsterInformationProvider {
|
||||
public String getMobNameFromId(int id) {
|
||||
String mobName = mobNameCache.get(id);
|
||||
if (mobName == null) {
|
||||
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
|
||||
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
MapleData mobData = dataProvider.getData("Mob.img");
|
||||
|
||||
mobName = MapleDataTool.getString(mobData.getChildByPath(id + "/name"), "");
|
||||
|
||||
@@ -24,8 +24,8 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -37,7 +37,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class MaplePlayerNPCFactory {
|
||||
|
||||
private static MapleDataProvider npcData = MapleDataProviderFactory.getDataProvider(new File("wz/Npc.wz"));
|
||||
private static MapleDataProvider npcData = MapleDataProviderFactory.getDataProvider(WZFiles.NPC);
|
||||
|
||||
private static final Map<Integer, List<MaplePlayerNPC>> dnpcMaps = new HashMap<>();
|
||||
private static Integer runningDeveloperOid = 2147483000; // 647 slots, long enough
|
||||
@@ -49,11 +49,11 @@ public class MaplePlayerNPCFactory {
|
||||
private static void loadDeveloperRoomMetadata(MapleDataProvider npc) {
|
||||
MapleData thisData = npc.getData("9977777.img");
|
||||
if(thisData != null) {
|
||||
MapleDataProvider map = MapleDataProviderFactory.getDataProvider(new File("wz/Map.wz"));
|
||||
MapleDataProvider map = MapleDataProviderFactory.getDataProvider(WZFiles.MAP);
|
||||
|
||||
thisData = map.getData("Map/Map7/777777777.img");
|
||||
if(thisData != null) {
|
||||
MapleDataProvider sound = MapleDataProviderFactory.getDataProvider(new File("wz/Sound.wz"));
|
||||
MapleDataProvider sound = MapleDataProviderFactory.getDataProvider(WZFiles.SOUND);
|
||||
|
||||
thisData = sound.getData("Field.img");
|
||||
if(thisData != null) {
|
||||
@@ -70,7 +70,7 @@ public class MaplePlayerNPCFactory {
|
||||
MapleDataProvider npc = npcData;
|
||||
loadDeveloperRoomMetadata(npc);
|
||||
|
||||
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(new File("wz/Etc.wz"));
|
||||
MapleDataProvider etc = MapleDataProviderFactory.getDataProvider(WZFiles.ETC);
|
||||
MapleData dnpcData = etc.getData("DeveloperNpc.img");
|
||||
if(dnpcData != null) {
|
||||
for (MapleData data : dnpcData.getChildren()) {
|
||||
|
||||
@@ -25,9 +25,9 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class MobAttackInfoFactory {
|
||||
private static Map<String, MobAttackInfo> mobAttacks = new HashMap<>();
|
||||
private static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Mob.wz"));
|
||||
private static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(WZFiles.MOB);
|
||||
|
||||
public static MobAttackInfo getMobAttackInfo(MapleMonster mob, int attack) {
|
||||
MobAttackInfo ret = mobAttacks.get(mob.getId() + "" + attack);
|
||||
|
||||
@@ -31,9 +31,9 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -46,7 +46,7 @@ import java.util.Map;
|
||||
public class MobSkillFactory {
|
||||
|
||||
private static Map<String, MobSkill> mobSkills = new HashMap<>();
|
||||
private final static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Skill.wz"));
|
||||
private final static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(WZFiles.SKILL);
|
||||
private static MapleData skillRoot = dataSource.getData("MobSkill.img");
|
||||
private final static MonitoredReentrantReadWriteLock dataLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MOBSKILL_FACTORY);
|
||||
private final static MonitoredReadLock rL = MonitoredReadLockFactory.createLock(dataLock);
|
||||
|
||||
@@ -25,6 +25,7 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import server.life.*;
|
||||
import server.partyquest.GuardianSpawnPoint;
|
||||
@@ -32,7 +33,6 @@ import tools.DatabaseConnection;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -47,8 +47,8 @@ public class MapleMapFactory {
|
||||
private static MapleDataProvider mapSource;
|
||||
|
||||
static {
|
||||
nameData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")).getData("Map.img");
|
||||
mapSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz"));
|
||||
nameData = MapleDataProviderFactory.getDataProvider(WZFiles.STRING).getData("Map.img");
|
||||
mapSource = MapleDataProviderFactory.getDataProvider(WZFiles.MAP);
|
||||
}
|
||||
|
||||
private static void loadLifeFromWz(MapleMap map, MapleData mapData) {
|
||||
|
||||
@@ -25,18 +25,18 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.maps.MapleReactorStats.StateData;
|
||||
import tools.Pair;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MapleReactorFactory {
|
||||
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Reactor.wz"));
|
||||
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(WZFiles.REACTOR);
|
||||
private static Map<Integer, MapleReactorStats> reactorStats = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -22,7 +22,7 @@ public class MapleCarnivalFactory {
|
||||
private final static MapleCarnivalFactory instance = new MapleCarnivalFactory();
|
||||
private final Map<Integer, MCSkill> skills = new HashMap<>();
|
||||
private final Map<Integer, MCSkill> guardians = new HashMap<>();
|
||||
private final MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Skill.wz"));
|
||||
private final MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(WZFiles.SKILL);
|
||||
|
||||
private final List<Integer> singleTargetedSkills = new ArrayList<>();
|
||||
private final List<Integer> multiTargetedSkills = new ArrayList<>();
|
||||
|
||||
@@ -29,12 +29,12 @@ import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.WZFiles;
|
||||
import server.quest.actions.*;
|
||||
import server.quest.requirements.*;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -68,7 +68,7 @@ public class MapleQuest {
|
||||
private boolean autoPreComplete, autoComplete;
|
||||
private boolean repeatable = false;
|
||||
private String name = "", parent = "";
|
||||
private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Quest.wz"));
|
||||
private final static MapleDataProvider questData = MapleDataProviderFactory.getDataProvider(WZFiles.QUEST);
|
||||
private final static MapleData questInfo = questData.getData("QuestInfo.img");
|
||||
private final static MapleData questAct = questData.getData("Act.img");
|
||||
private final static MapleData questReq = questData.getData("Check.img");
|
||||
|
||||
@@ -63,6 +63,10 @@ public class DatabaseConnection {
|
||||
* @return true if connection to the database initiated successfully, false if not successful
|
||||
*/
|
||||
public static boolean initializeConnectionPool() {
|
||||
if (dataSource != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
log.info("Initializing connection pool...");
|
||||
final HikariConfig config = getConfig();
|
||||
Instant initStart = Instant.now();
|
||||
|
||||
@@ -17,205 +17,203 @@
|
||||
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 maplearrowfetcher;
|
||||
package tools.mapletools;
|
||||
|
||||
import life.MapleLifeFactory;
|
||||
import life.MapleMonsterStats;
|
||||
import tools.DatabaseConnection;
|
||||
import server.life.MapleMonsterStats;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application traces arrow drop data on the underlying DB (that must be
|
||||
* defined on the DatabaseConnection file of this project) and generates a SQL file
|
||||
* that proposes updated arrow quantitty on drop entries for the drop_data table.
|
||||
*
|
||||
* <p>
|
||||
* The arrow quantity range is calculated accordingly with the target mob stats, such
|
||||
* as level and if it's a boss or not.
|
||||
*
|
||||
*/
|
||||
|
||||
public class MapleArrowFetcher {
|
||||
|
||||
public class ArrowFetcher {
|
||||
private static final String OUTPUT_FILE_NAME = "arrow_drop_data.sql";
|
||||
private static final int MIN_ARROW_ID = 2060000;
|
||||
private static final int MAX_ARROW_ID = 2061004;
|
||||
private static final float CORRECTION_FACTOR = 2.2f;
|
||||
|
||||
private static final Map<Integer, Pair<Integer, Integer>> mobRange = new HashMap<>();
|
||||
private static PrintWriter printWriter;
|
||||
private static String newFile = "lib/arrow_drop_data.sql";
|
||||
|
||||
private static int minArrowId = 2060000;
|
||||
private static int maxArrowId = 2061004;
|
||||
|
||||
private static float correctionFactor = 2.2f;
|
||||
|
||||
private static Map<Integer, MapleMonsterStats> mobStats;
|
||||
private static Map<Integer, Pair<Integer, Integer>> mobRange = new HashMap<>();
|
||||
|
||||
|
||||
private static Pair<Integer, Integer> calcArrowRange(int level, boolean boss) {
|
||||
int minRange, maxRange;
|
||||
|
||||
|
||||
// MIN range
|
||||
minRange = (int)Math.ceil(((2.870503597 * level) - 1.870503597) * (boss ? 1.4 : 1.0) / correctionFactor);
|
||||
|
||||
minRange = (int) Math.ceil(((2.870503597 * level) - 1.870503597) * (boss ? 1.4 : 1.0) / CORRECTION_FACTOR);
|
||||
|
||||
// MAX range
|
||||
maxRange = (int)Math.ceil(1.25 * minRange);
|
||||
|
||||
maxRange = (int) Math.ceil(1.25 * minRange);
|
||||
|
||||
return new Pair<>(minRange, maxRange);
|
||||
}
|
||||
|
||||
|
||||
private static void calcAllMobsArrowRange() {
|
||||
System.out.print("Calculating range... ");
|
||||
|
||||
for(Entry<Integer, MapleMonsterStats> mobStat : mobStats.entrySet()) {
|
||||
|
||||
for (Entry<Integer, MapleMonsterStats> mobStat : mobStats.entrySet()) {
|
||||
MapleMonsterStats mms = mobStat.getValue();
|
||||
Pair<Integer, Integer> arrowRange;
|
||||
|
||||
|
||||
arrowRange = calcArrowRange(mms.getLevel(), mms.isBoss());
|
||||
mobRange.put(mobStat.getKey(), arrowRange);
|
||||
}
|
||||
|
||||
|
||||
System.out.println("done!");
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlHeader() {
|
||||
printWriter.println(" # SQL File autogenerated from the MapleArrowFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account mob stats such as level and boss for the raw arrow ranges.");
|
||||
printWriter.println(" # Only current arrows entries on the DB it was compiled are being updated here.");
|
||||
printWriter.println();
|
||||
|
||||
|
||||
printWriter.println("UPDATE drop_data");
|
||||
printWriter.println("SET minimum_quantity = CASE");
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlMiddle() {
|
||||
printWriter.println(" ELSE minimum_quantity END,");
|
||||
printWriter.println(" maximum_quantity = CASE");
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlFooter() {
|
||||
printWriter.println(" ELSE maximum_quantity END");
|
||||
printWriter.println(";");
|
||||
}
|
||||
|
||||
|
||||
private static void updateSqlMobArrowMinEntry(int[] entry) {
|
||||
printWriter.println(" WHEN dropperid = " + entry[0] + " AND itemid = " + entry[1] + " THEN " + entry[2]);
|
||||
}
|
||||
|
||||
|
||||
private static void updateSqlMobArrowMaxEntry(int[] entry) {
|
||||
printWriter.println(" WHEN dropperid = " + entry[0] + " AND itemid = " + entry[1] + " THEN " + entry[3]);
|
||||
}
|
||||
|
||||
|
||||
private static List<int[]> getArrowEntryValues(Map<Integer, List<Integer>> existingEntries) {
|
||||
List<int[]> entryValues = new ArrayList<>(200);
|
||||
|
||||
|
||||
List<Entry<Integer, List<Integer>>> listEntries = new ArrayList<>(existingEntries.entrySet());
|
||||
|
||||
Collections.sort(listEntries, (o1, o2) -> {
|
||||
int val1 = o1.getKey();
|
||||
int val2 = o2.getKey();
|
||||
return (val1 < val2 ? -1 : (val1 == val2 ? 0 : 1));
|
||||
|
||||
listEntries.sort((o1, o2) -> {
|
||||
int val1 = o1.getKey();
|
||||
int val2 = o2.getKey();
|
||||
return Integer.compare(val1, val2);
|
||||
});
|
||||
|
||||
for(Entry<Integer, List<Integer>> ee : listEntries) {
|
||||
|
||||
for (Entry<Integer, List<Integer>> ee : listEntries) {
|
||||
int mobid = ee.getKey();
|
||||
Pair<Integer, Integer> mr = mobRange.get(mobid);
|
||||
|
||||
for(Integer itemid : ee.getValue()) {
|
||||
|
||||
for (Integer itemid : ee.getValue()) {
|
||||
int itemWeight = (itemid % 10) + 1;
|
||||
|
||||
|
||||
int[] values = new int[4];
|
||||
values[0] = mobid;
|
||||
values[1] = itemid;
|
||||
|
||||
values[2] = (int) Math.ceil(mr.getLeft() / itemWeight); // weighted min quantity
|
||||
|
||||
values[2] = (int) Math.ceil(mr.getLeft() / itemWeight); // weighted min quantity
|
||||
values[3] = (int) Math.ceil(mr.getRight() / itemWeight); // weighted max quantity
|
||||
|
||||
|
||||
entryValues.add(values);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return entryValues;
|
||||
}
|
||||
|
||||
|
||||
private static void updateMobsArrowRange() {
|
||||
System.out.print("Generating updated ranges... ");
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
Map<Integer, List<Integer>> existingEntries = new HashMap<>(200);
|
||||
|
||||
|
||||
try {
|
||||
// select all arrow drop entries on the DB, to update their values
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid, itemid FROM drop_data WHERE itemid >= " + minArrowId + " AND itemid <= " + maxArrowId + " ORDER BY itemid;");
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid, itemid FROM drop_data WHERE itemid >= " + MIN_ARROW_ID + " AND itemid <= " + MAX_ARROW_ID + " ORDER BY itemid;");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
|
||||
if (rs.isBeforeFirst()) {
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
int mobid = rs.getInt(1);
|
||||
int itemid = rs.getInt(2);
|
||||
|
||||
if(mobRange.containsKey(mobid)) {
|
||||
|
||||
if (mobRange.containsKey(mobid)) {
|
||||
List<Integer> em = existingEntries.get(mobid);
|
||||
|
||||
if(em == null) {
|
||||
|
||||
if (em == null) {
|
||||
em = new ArrayList<>(2);
|
||||
existingEntries.put(mobid, em);
|
||||
}
|
||||
|
||||
|
||||
em.add(itemid);
|
||||
}
|
||||
}
|
||||
|
||||
if(!existingEntries.isEmpty()) {
|
||||
|
||||
if (!existingEntries.isEmpty()) {
|
||||
List<int[]> entryValues = getArrowEntryValues(existingEntries);
|
||||
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(ToolConstants.getOutputFile(OUTPUT_FILE_NAME), StandardCharsets.UTF_8);
|
||||
printSqlHeader();
|
||||
|
||||
for(int[] arrowEntry : entryValues) {
|
||||
|
||||
for (int[] arrowEntry : entryValues) {
|
||||
updateSqlMobArrowMinEntry(arrowEntry);
|
||||
}
|
||||
|
||||
|
||||
printSqlMiddle();
|
||||
|
||||
for(int[] arrowEntry : entryValues) {
|
||||
|
||||
for (int[] arrowEntry : entryValues) {
|
||||
updateSqlMobArrowMaxEntry(arrowEntry);
|
||||
}
|
||||
|
||||
|
||||
printSqlFooter();
|
||||
|
||||
|
||||
printWriter.close();
|
||||
} else {
|
||||
throw new Exception("NO DATA");
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
throw new Exception("NO DATA");
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
|
||||
|
||||
System.out.println("done!");
|
||||
|
||||
} catch(Exception e) {
|
||||
if(e.getMessage() != null && e.getMessage().equals("NO DATA")) {
|
||||
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage() != null && e.getMessage().equals("NO DATA")) {
|
||||
System.out.println("failed! The DB has no arrow entry to be updated.");
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// load mob stats from WZ
|
||||
mobStats = MapleLifeFactory.getAllMonsterStats();
|
||||
|
||||
mobStats = MonsterStatFetcher.getAllMonsterStats();
|
||||
|
||||
calcAllMobsArrowRange();
|
||||
updateMobsArrowRange();
|
||||
}
|
||||
190
src/main/java/tools/mapletools/BossHpBarFetcher.java
Normal file
190
src/main/java/tools/mapletools/BossHpBarFetcher.java
Normal file
@@ -0,0 +1,190 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application parses the Mob.wz file inputted and generates a report showing
|
||||
* all cases where a mob has a boss HP bar and doesn't have a "boss" label.
|
||||
* <p>
|
||||
* Running it should generate a report file under "lib" folder with the search results.
|
||||
*/
|
||||
public class BossHpBarFetcher {
|
||||
private static final String OUTPUT_FILE_NAME = "boss_hp_bar_report.txt";
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final List<Integer> missingBosses = new ArrayList<>();
|
||||
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int curBoss;
|
||||
private static int curHpTag;
|
||||
private static int curMobId;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("value");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void readMobLabel(String token) {
|
||||
String name = getName(token);
|
||||
String value = getValue(token);
|
||||
|
||||
switch (name) {
|
||||
case "boss" -> curBoss = Integer.parseInt(value);
|
||||
case "hpTagColor" -> curHpTag = Integer.parseInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processMobData() {
|
||||
if (curHpTag != Integer.MAX_VALUE && curBoss == Integer.MAX_VALUE) {
|
||||
missingBosses.add(curMobId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
if (status == 1) {
|
||||
processMobData();
|
||||
}
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 0) {
|
||||
String mobText = getName(token);
|
||||
curMobId = Integer.parseInt(mobText.substring(0, mobText.lastIndexOf('.')));
|
||||
} else if (status == 1) { //getting info
|
||||
d = getName(token);
|
||||
|
||||
if (!d.contentEquals("info")) {
|
||||
forwardCursor(status);
|
||||
} else {
|
||||
curBoss = Integer.MAX_VALUE;
|
||||
curHpTag = Integer.MAX_VALUE;
|
||||
}
|
||||
} else if (status == 2) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if (status == 2) { //info tags
|
||||
readMobLabel(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void readBossHpBarData() throws IOException {
|
||||
String line;
|
||||
|
||||
final File mobDirectory = WZFiles.MOB.getFile();
|
||||
for (File file : mobDirectory.listFiles()) {
|
||||
if (file.isFile()) {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void printReportFileHeader(PrintWriter writer) {
|
||||
writer.println(" # Report File autogenerated from the MapleBossHpBarFetcher feature by Ronan Lana.");
|
||||
writer.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
|
||||
writer.println();
|
||||
}
|
||||
|
||||
private static void printReportFileResults(PrintWriter writer) {
|
||||
for (int mobId : missingBosses) {
|
||||
writer.println("Missing 'isBoss' on id: " + mobId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportBossHpBarData() {
|
||||
// This will reference one line at a time
|
||||
|
||||
try {
|
||||
System.out.println("Reading WZs...");
|
||||
readBossHpBarData();
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
final PrintWriter printWriter = new PrintWriter(ToolConstants.getOutputFile(OUTPUT_FILE_NAME), StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader(printWriter);
|
||||
printReportFileResults(printWriter);
|
||||
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open mob file.");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading mob file.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
reportBossHpBarData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +1,49 @@
|
||||
/*
|
||||
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";
|
||||
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static boolean ignoreCurrentScriptCosmetics = false;
|
||||
|
||||
static int initialStringLength = 50;
|
||||
|
||||
static byte status = 0;
|
||||
|
||||
static Map<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<>();
|
||||
|
||||
public class CashCosmeticsChecker {
|
||||
private static final String INPUT_DIRECTORY_PATH = ToolConstants.getInputFile("care").getPath();
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("cash_cosmetics_result.txt");
|
||||
private static final boolean IGNORE_CURRENT_SCRIPT_COSMETICS = false; // Toggle to preference
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
|
||||
private static final Map<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<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static InputStreamReader fileReader = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -81,13 +53,13 @@ public class MapleCashCosmeticsChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -97,84 +69,81 @@ public class MapleCashCosmeticsChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 3) {
|
||||
String d = getName(token);
|
||||
|
||||
|
||||
if (!(d.contentEquals("Face") || d.contentEquals("Hair"))) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
} else if (status == 4) {
|
||||
String d = getName(token);
|
||||
int itemid = Integer.valueOf(d);
|
||||
|
||||
int itemid = Integer.parseInt(d);
|
||||
|
||||
int cosmeticid;
|
||||
if (itemid >= 30000) {
|
||||
cosmeticid = (itemid / 10) * 10;
|
||||
} else {
|
||||
cosmeticid = itemid - ((itemid / 100) % 10) * 100;
|
||||
}
|
||||
|
||||
|
||||
allCosmetics.add(cosmeticid);
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readEqpStringData(String eqpStringDirectory) throws IOException {
|
||||
String line;
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(eqpStringDirectory), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(eqpStringDirectory), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void loadCosmeticWzData() throws IOException {
|
||||
System.out.println("Reading String.wz ...");
|
||||
readEqpStringData(wzPath + "/String.wz/Eqp.img.xml");
|
||||
readEqpStringData(WZFiles.STRING.getFilePath() + "/Eqp.img.xml");
|
||||
}
|
||||
|
||||
|
||||
private static void setCosmeticUsage(List<Integer> usedByNpcids, int cosmeticid) {
|
||||
if (!usedByNpcids.isEmpty()) {
|
||||
usedCosmetics.put(cosmeticid, usedByNpcids);
|
||||
@@ -182,7 +151,7 @@ public class MapleCashCosmeticsChecker {
|
||||
unusedCosmetics.add(cosmeticid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
@@ -196,60 +165,60 @@ public class MapleCashCosmeticsChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getNpcIdFromFilename(String name) {
|
||||
try {
|
||||
return Integer.valueOf(name.substring(0, name.indexOf('.')));
|
||||
} catch(Exception e) {
|
||||
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return npcids;
|
||||
}
|
||||
|
||||
|
||||
private static void loadScripts() throws IOException {
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(scriptPath + "/npc", files);
|
||||
listFiles(ToolConstants.SCRIPTS_PATH + "/npc", files);
|
||||
|
||||
for(File f : files) {
|
||||
for (File f : files) {
|
||||
Integer npcid = getNpcIdFromFilename(f.getName());
|
||||
|
||||
|
||||
//System.out.println("Parsing " + f.getAbsolutePath());
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
|
||||
|
||||
boolean cosmeticNpc = false;
|
||||
Set<Integer> cosmeticids = new HashSet<>();
|
||||
while((line = bufferedReader.readLine())!=null){
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
String[] s = line.split("hair_. = Array\\(", 2);
|
||||
|
||||
|
||||
if (s.length > 1) {
|
||||
cosmeticNpc = true;
|
||||
s = s[1].split("\\)", 2);
|
||||
s = s[0].split(", ");
|
||||
|
||||
|
||||
for (String st : s) {
|
||||
if (!st.isEmpty()) {
|
||||
int itemid = Integer.valueOf(st);
|
||||
int itemid = Integer.parseInt(st);
|
||||
cosmeticids.add(itemid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s = line.split("face_. = Array\\(", 2);
|
||||
|
||||
|
||||
if (s.length > 1) {
|
||||
cosmeticNpc = true;
|
||||
s = s[1].split("\\)", 2);
|
||||
@@ -257,18 +226,18 @@ public class MapleCashCosmeticsChecker {
|
||||
|
||||
for (String st : s) {
|
||||
if (!st.isEmpty()) {
|
||||
int itemid = Integer.valueOf(st);
|
||||
int itemid = Integer.parseInt(st);
|
||||
cosmeticids.add(itemid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stringBuffer.append(line).append("\n");
|
||||
}
|
||||
|
||||
|
||||
scriptEntries.put(npcid, stringBuffer.toString());
|
||||
|
||||
|
||||
if (cosmeticNpc) {
|
||||
scriptCosmetics.put(npcid, cosmeticids);
|
||||
}
|
||||
@@ -277,72 +246,74 @@ public class MapleCashCosmeticsChecker {
|
||||
fileReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void processCosmeticScriptData() throws IOException {
|
||||
System.out.println("Reading script files ...");
|
||||
loadScripts();
|
||||
|
||||
if (ignoreCurrentScriptCosmetics) {
|
||||
|
||||
if (IGNORE_CURRENT_SCRIPT_COSMETICS) {
|
||||
for (Set<Integer> npcCosmetics : scriptCosmetics.values()) {
|
||||
npcCosmetics.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Integer itemid : allCosmetics) {
|
||||
List<Integer> npcids = findCosmeticDataNpcids(itemid);
|
||||
setCosmeticUsage(npcids, itemid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String[] s = line.split(" - ", 3);
|
||||
|
||||
int itemid = Integer.valueOf(s[0]);
|
||||
|
||||
int itemid = Integer.parseInt(s[0]);
|
||||
if (itemid >= 5150000 && itemid < 5160000) {
|
||||
couponItemids.add(itemid);
|
||||
couponNames.put(itemid, s[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
|
||||
return couponItemids;
|
||||
}
|
||||
|
||||
|
||||
private static List<Integer> findItemidOnScript(int itemid) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
private static void loadCosmeticCouponNpcs() throws IOException {
|
||||
System.out.println("Locating cosmetic NPCs ...");
|
||||
|
||||
|
||||
for (Integer itemid : loadCosmeticCouponids()) {
|
||||
List<Integer> npcids = findItemidOnScript(itemid);
|
||||
|
||||
|
||||
if (!npcids.isEmpty()) {
|
||||
cosmeticNpcs.put(itemid, npcids.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum CosmeticType {
|
||||
HAIRSTYLE,
|
||||
HAIRCOLOR,
|
||||
@@ -351,11 +322,11 @@ public class MapleCashCosmeticsChecker {
|
||||
EYE_COLOR,
|
||||
SKIN_CARE
|
||||
}
|
||||
|
||||
|
||||
private static Pair<Integer, CosmeticType> parseCosmeticCoupon(String[] tokens) {
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String s = tokens[i];
|
||||
|
||||
|
||||
if (s.startsWith("Hair")) {
|
||||
if (s.contentEquals("Hairstyle")) {
|
||||
return new Pair<>(i, CosmeticType.HAIRSTYLE);
|
||||
@@ -378,10 +349,10 @@ public class MapleCashCosmeticsChecker {
|
||||
return new Pair<>(i, CosmeticType.SKIN_CARE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static List<String> getCosmeticCouponData(String town, String type, String subtype) {
|
||||
List<String> ret = new ArrayList<>(3);
|
||||
ret.add(town);
|
||||
@@ -389,77 +360,83 @@ public class MapleCashCosmeticsChecker {
|
||||
ret.add(subtype);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private static List<String> parseCosmeticCoupon(String couponName) {
|
||||
String town, type, subtype = "EXP";
|
||||
|
||||
|
||||
String[] s = couponName.split(" Coupon ", 2);
|
||||
|
||||
|
||||
if (s.length > 1) {
|
||||
subtype = s[1].substring(1, s[1].length() - 1);
|
||||
}
|
||||
|
||||
|
||||
String[] tokens = s[0].split(" ");
|
||||
Pair<Integer, CosmeticType> cosmeticData = parseCosmeticCoupon(tokens);
|
||||
if (cosmeticData == null) return null;
|
||||
|
||||
if (cosmeticData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
town = "";
|
||||
for (int i = 0; i < cosmeticData.left; i++) {
|
||||
town += (tokens[i] + "_");
|
||||
}
|
||||
town = town.substring(0, town.length() - 1).toLowerCase();
|
||||
|
||||
|
||||
switch (cosmeticData.right) {
|
||||
case HAIRSTYLE:
|
||||
type = "hair";
|
||||
break;
|
||||
|
||||
|
||||
case FACE_SURGERY:
|
||||
type = "face";
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return getCosmeticCouponData(town, type, subtype);
|
||||
}
|
||||
|
||||
|
||||
private static void generateCosmeticPlaceNpcs() {
|
||||
for (Entry<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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Integer getCosmeticNpcid(String townName, String typeCosmetic, String typeCoupon) {
|
||||
return cosmeticNpcids.get(getCosmeticCouponData(townName, typeCosmetic, typeCoupon));
|
||||
}
|
||||
|
||||
|
||||
private static String getCosmeticName(String name, boolean gender) {
|
||||
String ret = name + " (" + (gender ? "F" : "M") + ")";
|
||||
return ret;
|
||||
final String genderString = gender ? "F" : "M";
|
||||
return String.format("%s (%s)", name, genderString);
|
||||
}
|
||||
|
||||
|
||||
private static void loadCosmeticNames(String cosmeticPath) throws IOException {
|
||||
fileReader = new InputStreamReader(new FileInputStream(cosmeticPath), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(cosmeticPath), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
String[] s = line.split(" - ", 3);
|
||||
int itemid = Integer.valueOf(s[0]);
|
||||
|
||||
int itemid = Integer.parseInt(s[0]);
|
||||
|
||||
String name;
|
||||
if (itemid < 30000) {
|
||||
itemid = itemid - ((itemid / 100) % 10) * 100;
|
||||
|
||||
|
||||
int idx = s[1].lastIndexOf(" ");
|
||||
if (idx > -1) {
|
||||
name = s[1].substring(0, idx);
|
||||
@@ -468,7 +445,7 @@ public class MapleCashCosmeticsChecker {
|
||||
}
|
||||
} else {
|
||||
itemid = (Integer.valueOf(s[0]) / 10) * 10;
|
||||
|
||||
|
||||
int idx = s[1].indexOf(" ");
|
||||
if (idx > -1) {
|
||||
name = s[1].substring(idx + 1);
|
||||
@@ -476,17 +453,17 @@ public class MapleCashCosmeticsChecker {
|
||||
name = s[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
name = name.trim();
|
||||
|
||||
|
||||
String cname = getCosmeticName(name, (((itemid / 1000) % 10) % 3) != 0);
|
||||
|
||||
|
||||
/*
|
||||
if (cosmeticNameIds.containsKey(cname) && Math.abs(cosmeticNameIds.get(cname) - itemid) > 50) {
|
||||
System.out.println("Clashing '" + name + "' " + itemid + "/" + cosmeticNameIds.get(cname));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
cosmeticNameIds.put(cname, itemid);
|
||||
cosmeticIdNames.put(itemid, name);
|
||||
}
|
||||
@@ -494,17 +471,21 @@ public class MapleCashCosmeticsChecker {
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void loadCosmeticNames() throws IOException {
|
||||
System.out.println("Reading cosmetics from handbook ...");
|
||||
|
||||
loadCosmeticNames(handbookPath + "/Equip/Face.txt");
|
||||
loadCosmeticNames(handbookPath + "/Equip/Hair.txt");
|
||||
|
||||
loadCosmeticNames(getHandbookFileName("/Equip/Face.txt"));
|
||||
loadCosmeticNames(getHandbookFileName("/Equip/Hair.txt"));
|
||||
}
|
||||
|
||||
|
||||
private static String getHandbookFileName(String fileName) {
|
||||
return ToolConstants.HANDBOOK_PATH + fileName;
|
||||
}
|
||||
|
||||
private static List<Integer> fetchExpectedCosmetics(String[] cosmeticList, boolean gender) {
|
||||
List<Integer> list = new LinkedList<>();
|
||||
|
||||
|
||||
for (String cosmetic : cosmeticList) {
|
||||
String cname = getCosmeticName(cosmetic, gender);
|
||||
Integer itemid = cosmeticNameIds.get(cname);
|
||||
@@ -514,30 +495,30 @@ public class MapleCashCosmeticsChecker {
|
||||
missingCosmeticNames.add(cosmetic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static void verifyCosmeticExpectedFile(File f) throws IOException {
|
||||
String townName = f.getParent().substring(f.getParent().lastIndexOf("\\") + 1);
|
||||
String typeCosmetic = f.getName().substring(0, f.getName().indexOf("."));
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
while((line = bufferedReader.readLine())!=null){
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
String[] s = line.split(": ", 2);
|
||||
String[] t = s[0].split("ale ");
|
||||
|
||||
|
||||
String typeCoupon = t[1];
|
||||
boolean gender = !t[0].contentEquals("M");
|
||||
|
||||
|
||||
Integer npcid = getCosmeticNpcid(townName, typeCosmetic, typeCoupon);
|
||||
if (npcid != null) {
|
||||
String[] cosmetics = s[1].split(", ");
|
||||
List<Integer> cosmeticItemids = fetchExpectedCosmetics(cosmetics, gender);
|
||||
|
||||
|
||||
Set<Integer> npcCosmetics = scriptCosmetics.get(npcid);
|
||||
Set<Integer> missingCosmetics = new HashSet<>();
|
||||
for (Integer itemid : cosmeticItemids) {
|
||||
@@ -545,10 +526,10 @@ public class MapleCashCosmeticsChecker {
|
||||
missingCosmetics.add(itemid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!missingCosmetics.isEmpty()) {
|
||||
Pair<Integer, String> key = new Pair<>(npcid, typeCoupon);
|
||||
|
||||
|
||||
Set<Integer> list = missingCosmeticsNpcTypes.get(key);
|
||||
if (list == null) {
|
||||
missingCosmeticsNpcTypes.put(key, missingCosmetics);
|
||||
@@ -558,34 +539,34 @@ public class MapleCashCosmeticsChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void verifyCosmeticExpectedData() throws IOException {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
@@ -593,20 +574,20 @@ public class MapleCashCosmeticsChecker {
|
||||
return cmp;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleCashCosmeticsChecker feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the server source files and the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
private static Pair<List<Integer>, List<Integer>> getCosmeticReport(List<Integer> itemids) {
|
||||
List<Integer> maleItemids = new LinkedList<>();
|
||||
List<Integer> femaleItemids = new LinkedList<>();
|
||||
|
||||
|
||||
for (Integer i : itemids) {
|
||||
if ((((i / 1000) % 10) % 3) == 0) {
|
||||
maleItemids.add(i);
|
||||
@@ -614,10 +595,10 @@ public class MapleCashCosmeticsChecker {
|
||||
femaleItemids.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new Pair<>(maleItemids, femaleItemids);
|
||||
}
|
||||
|
||||
|
||||
private static void reportNpcCosmetics(List<Integer> itemids) {
|
||||
if (!itemids.isEmpty()) {
|
||||
String res = " ";
|
||||
@@ -625,75 +606,75 @@ public class MapleCashCosmeticsChecker {
|
||||
res += (i + ", ");
|
||||
unusedCosmetics.remove(i);
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(res.substring(0, res.length() - 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void reportCosmeticResults() throws IOException {
|
||||
System.out.println("Reporting results ...");
|
||||
|
||||
printWriter = new PrintWriter("lib/result.txt", "UTF-8");
|
||||
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
|
||||
|
||||
if (!missingCosmeticsNpcTypes.isEmpty()) {
|
||||
printWriter.println("Found " + missingCosmeticsNpcTypes.size() + " entries with missing cosmetic entries.");
|
||||
|
||||
|
||||
for (Pair<Pair<Integer, String>, List<Integer>> mcn : getSortedMapEntries(missingCosmeticsNpcTypes)) {
|
||||
printWriter.println(" NPC " + mcn.getLeft());
|
||||
|
||||
|
||||
Pair<List<Integer>, List<Integer>> genderItemids = getCosmeticReport(mcn.getRight());
|
||||
reportNpcCosmetics(genderItemids.getLeft());
|
||||
reportNpcCosmetics(genderItemids.getRight());
|
||||
printWriter.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!unusedCosmetics.isEmpty()) {
|
||||
printWriter.println("Unused cosmetics: " + unusedCosmetics.size());
|
||||
|
||||
|
||||
List<Integer> list = new ArrayList<>(unusedCosmetics);
|
||||
Collections.sort(list);
|
||||
|
||||
|
||||
for (Integer i : list) {
|
||||
printWriter.println(i + " " + cosmeticIdNames.get(i));
|
||||
}
|
||||
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
if (!missingCosmeticNames.isEmpty()) {
|
||||
printWriter.println("Missing cosmetic itemids: " + missingCosmeticNames.size());
|
||||
|
||||
|
||||
List<String> listString = new ArrayList<>(missingCosmeticNames);
|
||||
Collections.sort(listString);
|
||||
|
||||
|
||||
for (String c : listString) {
|
||||
printWriter.println(c);
|
||||
}
|
||||
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
loadCosmeticWzData();
|
||||
processCosmeticScriptData();
|
||||
|
||||
|
||||
loadCosmeticCouponNpcs();
|
||||
generateCosmeticPlaceNpcs();
|
||||
|
||||
|
||||
loadCosmeticNames();
|
||||
verifyCosmeticExpectedData();
|
||||
|
||||
|
||||
reportCosmeticResults();
|
||||
System.out.println("Done!");
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,28 @@
|
||||
/*
|
||||
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 maplecashcosmeticsfetcher;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import tools.MapleItemInformationProvider;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
|
||||
This application gathers info from the WZ.XML files, fetching all cosmetic coupons and tickets from there, and then
|
||||
searches the NPC script files, identifying the stylish NPCs that supposedly uses them. It will reports all NPCs that
|
||||
uses up a card, as well as report those currently unused.
|
||||
|
||||
Estimated parse time: 10 seconds
|
||||
|
||||
This application gathers info from the WZ.XML files, fetching all cosmetic coupons and tickets from there, and then
|
||||
searches the NPC script files, identifying the stylish NPCs that supposedly uses them. It will reports all NPCs that
|
||||
uses up a card, as well as report those currently unused.
|
||||
|
||||
Estimated parse time: 10 seconds
|
||||
|
||||
*/
|
||||
public class MapleCashCosmeticsFetcher {
|
||||
static MapleItemInformationProvider ii;
|
||||
|
||||
static String wzPath = "../../wz";
|
||||
static String scriptPath = "../../scripts";
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static Map<Integer, String> scriptEntries = new HashMap<>(500);
|
||||
public class CashCosmeticsFetcher {
|
||||
private static final Map<Integer, String> scriptEntries = new HashMap<>(500);
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
@@ -66,25 +37,25 @@ public class MapleCashCosmeticsFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void loadScripts() throws Exception {
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(scriptPath + "/npc", files);
|
||||
listFiles(ToolConstants.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");
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
String line;
|
||||
@@ -92,28 +63,29 @@ public class MapleCashCosmeticsFetcher {
|
||||
while((line = bufferedReader.readLine())!=null){
|
||||
stringBuffer.append(line).append("\n");
|
||||
}
|
||||
|
||||
|
||||
scriptEntries.put(npcid, stringBuffer.toString());
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<Integer> findItemidOnScript(int itemid) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
private static void reportCosmeticCouponResults() {
|
||||
final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
for (int itemid = 5150000; itemid <= 5154000; itemid++) {
|
||||
String itemName = ii.getName(itemid);
|
||||
|
||||
@@ -128,18 +100,16 @@ public class MapleCashCosmeticsFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("wzpath", wzPath);
|
||||
ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
DatabaseConnection.initializeConnectionPool(); // MapleItemInformationProvider loads unrelated stuff from the db
|
||||
try {
|
||||
loadScripts();
|
||||
System.out.println("Loaded scripts");
|
||||
|
||||
|
||||
reportCosmeticCouponResults();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +1,59 @@
|
||||
/*
|
||||
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.
|
||||
import provider.wz.WZFiles;
|
||||
import tools.Pair;
|
||||
|
||||
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 maplecashdropfetcher;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import tools.Pair;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
|
||||
This application gets info from the WZ.XML files regarding cash itemids then searches the drop data on the DB
|
||||
after any NX (cash item) drops and reports them.
|
||||
|
||||
Estimated parse time: 2 minutes
|
||||
* <p>
|
||||
* This application gets info from the WZ.XML files regarding cash itemids then searches the drop data on the DB
|
||||
* after any NX (cash item) drops and reports them.
|
||||
* <p>
|
||||
* Estimated parse time: 2 minutes
|
||||
*/
|
||||
public class MapleCashDropFetcher {
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
public class CashDropFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("cash_drop_report.txt");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final int ITEM_FILE_NAME_SIZE = 13;
|
||||
|
||||
static String wzPath = "../../wz";
|
||||
|
||||
static String directoryName = "../..";
|
||||
static String newFile = "lib/CashDropReport.txt";
|
||||
private static final Set<Integer> nxItems = new HashSet<>();
|
||||
private static final Set<Integer> nxDrops = new HashSet<>();
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static int initialLength = 200;
|
||||
static int initialStringLength = 50;
|
||||
static int itemFileNameSize = 13;
|
||||
|
||||
static Set<Integer> nxItems = new HashSet<>();
|
||||
static Set<Integer> nxDrops = new HashSet<>();
|
||||
|
||||
static byte status = 0;
|
||||
static int currentItemid = 0;
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
|
||||
private static byte status = 0;
|
||||
private static int currentItemid = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
if(j < i) return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
if (j < i) {
|
||||
return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
|
||||
}
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -100,115 +63,106 @@ public class MapleCashDropFetcher {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static void inspectEquipWzEntry() {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateEquipToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateEquipToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) {
|
||||
if(!getName(token).equals("info")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) {
|
||||
if (!getName(token).equals("info")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status += 1;
|
||||
}
|
||||
else {
|
||||
if(status == 2) {
|
||||
} else {
|
||||
if (status == 2) {
|
||||
String d = getName(token);
|
||||
|
||||
if(d.equals("cash")) {
|
||||
if(!getValue(token).equals("0")) {
|
||||
|
||||
if (d.equals("cash")) {
|
||||
if (!getValue(token).equals("0")) {
|
||||
nxItems.add(currentItemid);
|
||||
}
|
||||
|
||||
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void inspectItemWzEntry() {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateItemToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateItemToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) {
|
||||
currentItemid = Integer.valueOf(getName(token));
|
||||
}
|
||||
else if(status == 2) {
|
||||
if(!getName(token).equals("info")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) {
|
||||
currentItemid = Integer.parseInt(getName(token));
|
||||
} else if (status == 2) {
|
||||
if (!getName(token).equals("info")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status += 1;
|
||||
}
|
||||
else {
|
||||
if(status == 3) {
|
||||
} else {
|
||||
if (status == 3) {
|
||||
String d = getName(token);
|
||||
|
||||
if(d.equals("cash")) {
|
||||
if(!getValue(token).equals("0")) {
|
||||
|
||||
if (d.equals("cash")) {
|
||||
if (!getValue(token).equals("0")) {
|
||||
nxItems.add(currentItemid);
|
||||
}
|
||||
|
||||
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
@@ -220,7 +174,7 @@ public class MapleCashDropFetcher {
|
||||
printWriter.println(" # Generated data takes into account several data info from the underlying DB and the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
@@ -234,93 +188,92 @@ public class MapleCashDropFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getItemIdFromFilename(String name) {
|
||||
try {
|
||||
return Integer.valueOf(name.substring(0, name.indexOf('.')));
|
||||
} catch(Exception e) {
|
||||
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String getDropTableName(boolean dropdata) {
|
||||
return (dropdata ? "drop_data" : "reactordrops");
|
||||
}
|
||||
|
||||
|
||||
private static String getDropElementName(boolean dropdata) {
|
||||
return (dropdata ? "dropperid" : "reactorid");
|
||||
}
|
||||
|
||||
|
||||
private static void filterNxDropsOnDB(boolean dropdata) throws SQLException {
|
||||
nxDrops.clear();
|
||||
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("SELECT DISTINCT itemid FROM " + getDropTableName(dropdata));
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while(rs.next()) {
|
||||
|
||||
while (rs.next()) {
|
||||
int itemid = rs.getInt("itemid");
|
||||
|
||||
if(nxItems.contains(itemid)) {
|
||||
|
||||
if (nxItems.contains(itemid)) {
|
||||
nxDrops.add(itemid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
|
||||
private static List<Pair<Integer, Integer>> getNxDropsEntries(boolean dropdata) throws SQLException {
|
||||
List<Pair<Integer, Integer>> entries = new ArrayList<>();
|
||||
|
||||
|
||||
List<Integer> sortedNxDrops = new ArrayList<>(nxDrops);
|
||||
Collections.sort(sortedNxDrops);
|
||||
|
||||
for(Integer nx : sortedNxDrops) {
|
||||
|
||||
for (Integer nx : sortedNxDrops) {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT " + getDropElementName(dropdata) + " FROM " + getDropTableName(dropdata) + " WHERE itemid = ?");
|
||||
ps.setInt(1, nx);
|
||||
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
entries.add(new Pair<>(nx, rs.getInt(getDropElementName(dropdata))));
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
private static void reportNxDropResults(boolean dropdata) throws SQLException {
|
||||
filterNxDropsOnDB(dropdata);
|
||||
|
||||
if(!nxDrops.isEmpty()) {
|
||||
|
||||
if (!nxDrops.isEmpty()) {
|
||||
List<Pair<Integer, Integer>> nxEntries = getNxDropsEntries(dropdata);
|
||||
|
||||
printWriter.println("NX DROPS ON " + getDropTableName(dropdata));
|
||||
for(Pair<Integer, Integer> nx : nxEntries) {
|
||||
for (Pair<Integer, Integer> nx : nxEntries) {
|
||||
printWriter.println(nx.left + " : " + nx.right);
|
||||
}
|
||||
printWriter.println("\n\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReportNxDropData() {
|
||||
|
||||
private static void reportNxDropData() {
|
||||
try {
|
||||
Class.forName(driver).newInstance();
|
||||
|
||||
System.out.println("Reading Character.wz ...");
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(wzPath + "/Character.wz", files);
|
||||
|
||||
for(File f : files) {
|
||||
listFiles(WZFiles.CHARACTER.getFilePath(), files);
|
||||
|
||||
InputStreamReader fileReader = null;
|
||||
for (File f : files) {
|
||||
//System.out.println("Parsing " + f.getAbsolutePath());
|
||||
int itemid = getItemIdFromFilename(f.getName());
|
||||
if(itemid < 0) {
|
||||
if (itemid < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
currentItemid = itemid;
|
||||
@@ -329,24 +282,24 @@ public class MapleCashDropFetcher {
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
System.out.println("Reading Item.wz ...");
|
||||
files = new ArrayList<>();
|
||||
listFiles(wzPath + "/Item.wz", files);
|
||||
|
||||
for(File f : files) {
|
||||
listFiles(WZFiles.ITEM.getFilePath(), files);
|
||||
|
||||
for (File f : files) {
|
||||
//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);
|
||||
|
||||
if(f.getName().length() <= itemFileNameSize) {
|
||||
if (f.getName().length() <= ITEM_FILE_NAME_SIZE) {
|
||||
inspectItemWzEntry();
|
||||
} else { // pet file structure is similar to equips, maybe there are other item-types following this behaviour?
|
||||
int itemid = getItemIdFromFilename(f.getName());
|
||||
if(itemid < 0) {
|
||||
if (itemid < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
currentItemid = itemid;
|
||||
inspectEquipWzEntry();
|
||||
}
|
||||
@@ -354,53 +307,35 @@ public class MapleCashDropFetcher {
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
|
||||
// filter drop data on DB
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
|
||||
// report suspects of missing quest drop data, as well as those drop data that may have incorrect questids.
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
printReportFileHeader();
|
||||
|
||||
|
||||
reportNxDropResults(true);
|
||||
reportNxDropResults(false);
|
||||
|
||||
|
||||
/*
|
||||
printWriter.println("NX LIST"); // list of all cash items found
|
||||
for(Integer nx : nxItems) {
|
||||
printWriter.println(nx);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
con.close();
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Warning: Could not establish connection to database to report quest data.");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(ClassNotFoundException e) {
|
||||
System.out.println("Error: could not find class");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(InstantiationException e) {
|
||||
System.out.println("Error: instantiation failure");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
ReportNxDropData();
|
||||
reportNxDropData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +1,32 @@
|
||||
/*
|
||||
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.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 maplecashvegachecker;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
This application main objective is to read Vega-related information from
|
||||
the item's description report back missing nodes for these items.
|
||||
|
||||
Estimated parse time: 10 seconds
|
||||
*
|
||||
This application main objective is to read Vega-related information from
|
||||
the item's description report back missing nodes for these items.
|
||||
|
||||
Estimated parse time: 10 seconds
|
||||
*/
|
||||
public class MapleCashVegaChecker {
|
||||
|
||||
private static String wzPath = "../../wz";
|
||||
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static int initialStringLength = 1000;
|
||||
static int currentItem;
|
||||
|
||||
static byte status = 0;
|
||||
|
||||
static Set<Integer> vegaItems = new HashSet<>();
|
||||
|
||||
public class CashVegaChecker {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("vega_checker_report.txt");
|
||||
private static final int INITIAL_STRING_LENGTH = 1000;
|
||||
private static final Set<Integer> vegaItems = new HashSet<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static InputStreamReader fileReader = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static int currentItem;
|
||||
private static byte status = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -61,13 +36,13 @@ public class MapleCashVegaChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -77,13 +52,13 @@ public class MapleCashVegaChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
@@ -105,16 +80,16 @@ public class MapleCashVegaChecker {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateItemToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 2) {
|
||||
currentItem = Integer.valueOf(getName(token));
|
||||
currentItem = Integer.parseInt(getName(token));
|
||||
}
|
||||
} else {
|
||||
if (status == 2) {
|
||||
@@ -124,7 +99,7 @@ public class MapleCashVegaChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateVegaToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
@@ -139,11 +114,11 @@ public class MapleCashVegaChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readItemDescriptionFile(File f) {
|
||||
System.out.print("Reading String.wz... ");
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
@@ -158,11 +133,11 @@ public class MapleCashVegaChecker {
|
||||
}
|
||||
System.out.println(vegaItems.size() + " Vega Scroll items found");
|
||||
}
|
||||
|
||||
|
||||
private static void readVegaDescriptionFile(File f) {
|
||||
System.out.println("Reading Etc.wz...");
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
@@ -176,38 +151,38 @@ public class MapleCashVegaChecker {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleCashVegaChecker 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 reportMissingVegaItems() {
|
||||
System.out.println("Reporting results ...");
|
||||
|
||||
|
||||
try {
|
||||
printWriter = new PrintWriter("lib/result.txt", "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
|
||||
for (Integer itemid : vegaItems) {
|
||||
printWriter.println(" " + itemid);
|
||||
}
|
||||
|
||||
|
||||
printWriter.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
readItemDescriptionFile(new File(wzPath + "/String.wz/Consume.img.xml"));
|
||||
readVegaDescriptionFile(new File(wzPath + "/Etc.wz/VegaSpell.img.xml"));
|
||||
|
||||
|
||||
readItemDescriptionFile(new File(WZFiles.STRING.getFilePath() + "/Consume.img.xml"));
|
||||
readVegaDescriptionFile(new File(WZFiles.ETC.getFilePath() + "/VegaSpell.img.xml"));
|
||||
|
||||
reportMissingVegaItems();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,79 +1,46 @@
|
||||
/*
|
||||
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.
|
||||
import tools.Pair;
|
||||
|
||||
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 maplecodecoupongenerator;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
|
||||
This application parses the coupon descriptor XML file and automatically generates
|
||||
code entries on the DB reflecting the descriptions found. Parse time relies on the
|
||||
sum of coupon codes created and amount of current codes on DB.
|
||||
|
||||
Estimated parse time: 2 minutes (for 100 code entries)
|
||||
* <p>
|
||||
* This application parses the coupon descriptor XML file and automatically generates
|
||||
* code entries on the DB reflecting the descriptions found. Parse time relies on the
|
||||
* sum of coupon codes created and amount of current codes on DB.
|
||||
* <p>
|
||||
* Estimated parse time: 2 minutes (for 100 code entries)
|
||||
*/
|
||||
public class MapleCodeCouponGenerator {
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
|
||||
static Connection con = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static String fileName = "lib/CouponCodes.img.xml";
|
||||
static long currentTime;
|
||||
|
||||
static int initialStringLength = 250;
|
||||
|
||||
static String name;
|
||||
static boolean active;
|
||||
static int quantity, duration;
|
||||
static int maplePoint, nxCredit, nxPrepaid;
|
||||
|
||||
static List<Pair<Integer, Integer>> itemList = new ArrayList<>();
|
||||
static Pair<Integer, Integer> item;
|
||||
|
||||
|
||||
static List<CodeCouponDescriptor> activeCoupons = new ArrayList<>();
|
||||
static List<Integer> generatedKeys;
|
||||
static Set<String> usedCodes = new HashSet<>();
|
||||
|
||||
static byte status;
|
||||
|
||||
public class CodeCouponGenerator {
|
||||
private static final File INPUT_FILE = ToolConstants.getInputFile("CouponCodes.img.xml");
|
||||
private static final int INITIAL_STRING_LENGTH = 250;
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
private static final List<CodeCouponDescriptor> activeCoupons = new ArrayList<>();
|
||||
private static final Set<String> usedCodes = new HashSet<>();
|
||||
private static final List<Pair<Integer, Integer>> itemList = new ArrayList<>();
|
||||
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static long currentTime;
|
||||
private static String name;
|
||||
private static boolean active;
|
||||
private static int quantity;
|
||||
private static int duration;
|
||||
private static int maplePoint;
|
||||
private static int nxCredit;
|
||||
private static int nxPrepaid;
|
||||
private static Pair<Integer, Integer> item;
|
||||
private static List<Integer> generatedKeys;
|
||||
private static byte status;
|
||||
|
||||
private static void resetCouponPackage() {
|
||||
name = null;
|
||||
active = false;
|
||||
@@ -84,17 +51,17 @@ public class MapleCodeCouponGenerator {
|
||||
nxPrepaid = 0;
|
||||
itemList.clear();
|
||||
}
|
||||
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
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];
|
||||
try {
|
||||
token.getChars(i, j, dest, 0);
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
@@ -105,14 +72,13 @@ public class MapleCodeCouponGenerator {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Thread.sleep(100000000);
|
||||
} catch (Exception ex) {}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return new String(dest).trim();
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -122,68 +88,64 @@ public class MapleCodeCouponGenerator {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
|
||||
if (status == 1) {
|
||||
if (active) {
|
||||
activeCoupons.add(new CodeCouponDescriptor(name, quantity, duration, maplePoint, nxCredit, nxPrepaid, itemList));
|
||||
}
|
||||
|
||||
|
||||
resetCouponPackage();
|
||||
} else if (status == 3) {
|
||||
itemList.add(item);
|
||||
}
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 4) {
|
||||
item = new Pair<>(-1, -1);
|
||||
} else if (status == 2) {
|
||||
String d = getName(token);
|
||||
|
||||
|
||||
System.out.println(" Reading coupon '" + d + "'");
|
||||
name = d;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
String d = getName(token);
|
||||
|
||||
|
||||
if (status == 2) {
|
||||
switch (d) {
|
||||
case "active":
|
||||
if (Integer.valueOf(getValue(token)) == 0) {
|
||||
if (Integer.parseInt(getValue(token)) == 0) {
|
||||
forwardCursor(status);
|
||||
resetCouponPackage();
|
||||
} else {
|
||||
@@ -192,19 +154,19 @@ public class MapleCodeCouponGenerator {
|
||||
break;
|
||||
|
||||
case "quantity":
|
||||
quantity = Integer.valueOf(getValue(token));
|
||||
quantity = Integer.parseInt(getValue(token));
|
||||
break;
|
||||
case "duration":
|
||||
duration = Integer.valueOf(getValue(token));
|
||||
duration = Integer.parseInt(getValue(token));
|
||||
break;
|
||||
case "maplePoint":
|
||||
maplePoint = Integer.valueOf(getValue(token));
|
||||
maplePoint = Integer.parseInt(getValue(token));
|
||||
break;
|
||||
case "nxCredit":
|
||||
nxCredit = Integer.valueOf(getValue(token));
|
||||
nxCredit = Integer.parseInt(getValue(token));
|
||||
break;
|
||||
case "nxPrepaid":
|
||||
nxPrepaid = Integer.valueOf(getValue(token));
|
||||
nxPrepaid = Integer.parseInt(getValue(token));
|
||||
break;
|
||||
}
|
||||
} else if (status == 4) {
|
||||
@@ -219,13 +181,13 @@ public class MapleCodeCouponGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class CodeCouponDescriptor {
|
||||
protected String name;
|
||||
protected int quantity, duration;
|
||||
protected int nxCredit, maplePoint, nxPrepaid;
|
||||
protected List<Pair<Integer, Integer>> itemList;
|
||||
|
||||
|
||||
protected CodeCouponDescriptor(String name, int quantity, int duration, int maplePoint, int nxCredit, int nxPrepaid, List<Pair<Integer, Integer>> itemList) {
|
||||
this.name = name;
|
||||
this.quantity = quantity;
|
||||
@@ -233,109 +195,111 @@ public class MapleCodeCouponGenerator {
|
||||
this.maplePoint = maplePoint;
|
||||
this.nxCredit = nxCredit;
|
||||
this.nxPrepaid = nxPrepaid;
|
||||
|
||||
|
||||
this.itemList = new ArrayList<>(itemList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String randomizeCouponCode() {
|
||||
return Long.toHexString(Double.doubleToLongBits(Math.random())).substring(0, 15);
|
||||
}
|
||||
|
||||
|
||||
private static String generateCouponCode() {
|
||||
String newCode;
|
||||
do {
|
||||
newCode = randomizeCouponCode();
|
||||
} while (usedCodes.contains(newCode));
|
||||
|
||||
|
||||
usedCodes.add(newCode);
|
||||
return newCode;
|
||||
}
|
||||
|
||||
|
||||
private static List<Integer> getGeneratedKeys(PreparedStatement ps) throws SQLException {
|
||||
if (generatedKeys == null) {
|
||||
generatedKeys = new ArrayList<>();
|
||||
|
||||
|
||||
ResultSet rs = ps.getGeneratedKeys();
|
||||
while (rs.next()) {
|
||||
generatedKeys.add(rs.getInt(1));
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
|
||||
|
||||
return generatedKeys;
|
||||
}
|
||||
|
||||
|
||||
private static void commitCodeCouponDescription(CodeCouponDescriptor recipe) throws SQLException {
|
||||
if (recipe.quantity < 1) return;
|
||||
|
||||
if (recipe.quantity < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println(" Generating coupon '" + recipe.name + "'");
|
||||
generatedKeys = null;
|
||||
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("INSERT IGNORE INTO `nxcode` (`code`, `expiration`) VALUES (?, ?)", Statement.RETURN_GENERATED_KEYS);
|
||||
ps.setLong(2, currentTime + ((long) recipe.duration * 60 * 60 * 1000));
|
||||
|
||||
for(int i = 0; i < recipe.quantity; i++) {
|
||||
|
||||
for (int i = 0; i < recipe.quantity; i++) {
|
||||
ps.setString(1, generateCouponCode());
|
||||
ps.addBatch();
|
||||
}
|
||||
ps.executeBatch();
|
||||
|
||||
|
||||
PreparedStatement ps2 = con.prepareStatement("INSERT IGNORE INTO `nxcode_items` (`codeid`, `type`, `item`, `quantity`) VALUES (?, ?, ?, ?)");
|
||||
if (!recipe.itemList.isEmpty()) {
|
||||
ps2.setInt(2, 5);
|
||||
List<Integer> keys = getGeneratedKeys(ps);
|
||||
|
||||
|
||||
for (Pair<Integer, Integer> p : recipe.itemList) {
|
||||
ps2.setInt(3, p.getLeft());
|
||||
ps2.setInt(4, p.getRight());
|
||||
|
||||
|
||||
for (Integer codeid : keys) {
|
||||
ps2.setInt(1, codeid);
|
||||
ps2.addBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ps2.setInt(3, 0);
|
||||
if (recipe.nxCredit > 0) {
|
||||
ps2.setInt(2, 0);
|
||||
ps2.setInt(4, recipe.nxCredit);
|
||||
List<Integer> keys = getGeneratedKeys(ps);
|
||||
|
||||
for(Integer codeid : keys) {
|
||||
|
||||
for (Integer codeid : keys) {
|
||||
ps2.setInt(1, codeid);
|
||||
ps2.addBatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (recipe.maplePoint > 0) {
|
||||
ps2.setInt(2, 1);
|
||||
ps2.setInt(4, recipe.maplePoint);
|
||||
List<Integer> keys = getGeneratedKeys(ps);
|
||||
|
||||
for(Integer codeid : keys) {
|
||||
|
||||
for (Integer codeid : keys) {
|
||||
ps2.setInt(1, codeid);
|
||||
ps2.addBatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (recipe.nxPrepaid > 0) {
|
||||
ps2.setInt(2, 2);
|
||||
ps2.setInt(4, recipe.nxPrepaid);
|
||||
List<Integer> keys = getGeneratedKeys(ps);
|
||||
|
||||
for(Integer codeid : keys) {
|
||||
|
||||
for (Integer codeid : keys) {
|
||||
ps2.setInt(1, codeid);
|
||||
ps2.addBatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ps2.executeBatch();
|
||||
ps2.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
|
||||
private static void loadUsedCouponCodes() throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT code FROM nxcode", Statement.RETURN_GENERATED_KEYS);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
@@ -345,51 +309,48 @@ public class MapleCodeCouponGenerator {
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
private static void generateCodeCoupons(String fileName) throws IOException {
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||
|
||||
private static void generateCodeCoupons(File file) throws IOException {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
resetCouponPackage();
|
||||
status = 0;
|
||||
|
||||
|
||||
System.out.println("Reading XML coupon information...");
|
||||
String line;
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
System.out.println();
|
||||
|
||||
|
||||
try {
|
||||
Class.forName(driver).newInstance();
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
System.out.println("Loading DB coupon codes...");
|
||||
loadUsedCouponCodes();
|
||||
System.out.println();
|
||||
|
||||
|
||||
System.out.println("Saving generated coupons...");
|
||||
currentTime = System.currentTimeMillis();
|
||||
for (CodeCouponDescriptor ccd : activeCoupons) {
|
||||
commitCodeCouponDescription(ccd);
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
|
||||
con.close();
|
||||
System.out.println("Done.");
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
generateCodeCoupons(fileName);
|
||||
} catch(IOException ex) {
|
||||
System.out.println("Error reading file '" + fileName + "'");
|
||||
generateCodeCoupons(INPUT_FILE);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + INPUT_FILE.getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
255
src/main/java/tools/mapletools/CouponInstaller.java
Normal file
255
src/main/java/tools/mapletools/CouponInstaller.java
Normal file
@@ -0,0 +1,255 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application gathers information about the Cash Shop's EXP & DROP coupons,
|
||||
* such as applied rates, active times of day and days of week and dumps them in
|
||||
* a SQL table that the server will make use.
|
||||
*/
|
||||
public class CouponInstaller {
|
||||
private static final File COUPON_INPUT_FILE_1 = new File(WZFiles.ITEM.getFilePath(), "/Cash/0521.img.xml");
|
||||
private static final File COUPON_INPUT_FILE_2 = new File(WZFiles.ITEM.getFilePath(), "/Cash/0536.img.xml");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int itemId = -1;
|
||||
private static int itemMultiplier = 1;
|
||||
private static int startHour = -1;
|
||||
private static int endHour = -1;
|
||||
private static int activeDay = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
if (i < 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[8];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d);
|
||||
}
|
||||
|
||||
private static String getNodeValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("value=");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
if (j - i < 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
dest = new char[j - i];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d);
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getDayOfWeek(String day) {
|
||||
return switch (day) {
|
||||
case "SUN" -> 1;
|
||||
case "MON" -> 2;
|
||||
case "TUE" -> 3;
|
||||
case "WED" -> 4;
|
||||
case "THU" -> 5;
|
||||
case "FRI" -> 6;
|
||||
case "SAT" -> 7;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
private static void processHourTimeString(String time) {
|
||||
startHour = Integer.parseInt(time.substring(4, 6));
|
||||
endHour = Integer.parseInt(time.substring(7, 9));
|
||||
}
|
||||
|
||||
private static void processDayTimeString(String time) {
|
||||
String day = time.substring(0, 3);
|
||||
int d = getDayOfWeek(day);
|
||||
|
||||
activeDay |= (1 << d);
|
||||
}
|
||||
|
||||
private static void loadTimeFromCoupon(int st) {
|
||||
System.out.println("Loading coupon id " + itemId + ". Rate: " + itemMultiplier + "x.");
|
||||
|
||||
String line = null;
|
||||
try {
|
||||
startHour = -1;
|
||||
endHour = -1;
|
||||
activeDay = 0;
|
||||
|
||||
String time = null;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
if (status < st) {
|
||||
break;
|
||||
}
|
||||
|
||||
time = getNodeValue(line);
|
||||
processDayTimeString(time);
|
||||
|
||||
simpleToken(line);
|
||||
}
|
||||
|
||||
if (time != null) {
|
||||
processHourTimeString(time);
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("INSERT INTO nxcoupons (couponid, rate, activeday, starthour, endhour) VALUES (?, ?, ?, ?, ?)");
|
||||
ps.setInt(1, itemId);
|
||||
ps.setInt(2, itemMultiplier);
|
||||
ps.setInt(3, activeDay);
|
||||
ps.setInt(4, startHour);
|
||||
ps.setInt(5, endHour);
|
||||
ps.execute();
|
||||
|
||||
ps.close();
|
||||
}
|
||||
} catch (SQLException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting ItemId
|
||||
d = getName(token);
|
||||
itemId = Integer.parseInt(d);
|
||||
} else if (status == 2) {
|
||||
d = getName(token);
|
||||
|
||||
if (!d.contains("info")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
} else if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
if (!d.contains("time")) {
|
||||
forwardCursor(status);
|
||||
} else {
|
||||
loadTimeFromCoupon(status);
|
||||
}
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
if (d.contains("rate")) {
|
||||
String r = getNodeValue(token);
|
||||
|
||||
double db = Double.parseDouble(r);
|
||||
itemMultiplier = (int) db;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void installRateCoupons(File file) {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + file + "'");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + file + "'");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void installCouponsTable() {
|
||||
try {
|
||||
PreparedStatement ps = con.prepareStatement("DROP TABLE IF EXISTS `nxcoupons`;");
|
||||
ps.execute();
|
||||
ps.close();
|
||||
|
||||
ps = con.prepareStatement(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS `nxcoupons` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`couponid` int(11) NOT NULL DEFAULT '0',
|
||||
`rate` int(11) NOT NULL DEFAULT '0',
|
||||
`activeday` int(11) NOT NULL DEFAULT '0',
|
||||
`starthour` int(11) NOT NULL DEFAULT '0',
|
||||
`endhour` int(11) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;"""
|
||||
);
|
||||
|
||||
ps.execute();
|
||||
ps.close();
|
||||
|
||||
installRateCoupons(COUPON_INPUT_FILE_1);
|
||||
installRateCoupons(COUPON_INPUT_FILE_2);
|
||||
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Warning: Could not establish connection to database to change card chance rate.");
|
||||
System.out.println(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
installCouponsTable();
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,42 @@
|
||||
/*
|
||||
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.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 mapledojoupdate;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
|
||||
This application parses the Character.wz folder inputted and adds/updates the "info/level"
|
||||
node on every known equipment id. This addition enables client-side view of the equipment
|
||||
level attribute on every equipment in the game, given proper item visibility, be it from
|
||||
own equipments or from other players.
|
||||
|
||||
Estimated parse time: 10 seconds
|
||||
|
||||
* <p>
|
||||
* This application parses the Character.wz folder inputted and adds/updates the "info/level"
|
||||
* node on every known equipment id. This addition enables client-side view of the equipment
|
||||
* level attribute on every equipment in the game, given proper item visibility, be it from
|
||||
* own equipments or from other players.
|
||||
* <p>
|
||||
* Estimated parse time: 10 seconds
|
||||
*/
|
||||
public class MapleDojoUpdate {
|
||||
public class DojoUpdate {
|
||||
private static final File INPUT_DIRECTORY = new File(WZFiles.MAP.getFile(), "/Map/Map9");
|
||||
private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("dojo-maps");
|
||||
private static final int DOJO_MIN_MAP_ID = 925_020_100;
|
||||
private static final int DOJO_MAX_MAP_ID = 925_033_804;
|
||||
private static final int INITIAL_STRING_LENGTH = 250;
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static boolean isDojoMapid;
|
||||
private static byte status;
|
||||
|
||||
static String dojoDirectory = "lib/original/";
|
||||
static String outputDirectory = "lib/updated/";
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static int initialStringLength = 250;
|
||||
static boolean isDojoMapid;
|
||||
|
||||
static byte status;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
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];
|
||||
try {
|
||||
token.getChars(i, j, dest, 0);
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
@@ -75,59 +47,56 @@ public class MapleDojoUpdate {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Thread.sleep(100000000);
|
||||
} catch (Exception ex) {}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
printWriter.println(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
printWriter.println(token);
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
printWriter.println(token);
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 2) {
|
||||
String d = getName(token);
|
||||
if(!d.contentEquals("info")) {
|
||||
if (!d.contentEquals("info")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
} else if (status > 2) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (status == 2 && isDojoMapid) {
|
||||
String item = getName(token);
|
||||
|
||||
|
||||
if (item.contentEquals("onFirstUserEnter")) {
|
||||
printWriter.println(" <string name=\"onFirstUserEnter\" value=\"dojang_1st\"/>");
|
||||
} else if (item.contentEquals("onUserEnter")) {
|
||||
@@ -140,24 +109,27 @@ public class MapleDojoUpdate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getMapId(String fileName) {
|
||||
return Integer.parseInt(fileName.substring(0, 9));
|
||||
}
|
||||
|
||||
|
||||
private static void parseDojoData(File file, String curPath) throws IOException {
|
||||
printWriter = new PrintWriter(outputDirectory + curPath + file.getName(), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
|
||||
int mapId = getMapId(file.getName());
|
||||
isDojoMapid = isDojoMapId(mapId);
|
||||
if (!isDojoMapid) {
|
||||
return;
|
||||
}
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_DIRECTORY.getPath() + "/" + curPath + file.getName(), StandardCharsets.UTF_8);
|
||||
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
status = 0;
|
||||
|
||||
int mapid = getMapId(file.getName());
|
||||
isDojoMapid = mapid >= 925020100 && mapid < 925040000;
|
||||
|
||||
|
||||
String line;
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
@@ -167,35 +139,35 @@ public class MapleDojoUpdate {
|
||||
printFileFooter();
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
|
||||
private static boolean isDojoMapId(int mapId) {
|
||||
return mapId >= DOJO_MIN_MAP_ID && mapId <= DOJO_MAX_MAP_ID;
|
||||
}
|
||||
|
||||
private static void printFileFooter() {
|
||||
printWriter.println("<!--");
|
||||
printWriter.println(" # WZ XML File updated by the MapleDojoUpdate feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account info from the server-side WZ.xmls.");
|
||||
printWriter.println("-->");
|
||||
}
|
||||
|
||||
|
||||
private static void parseDirectoryDojoData(String curPath) {
|
||||
File folder = new File(outputDirectory + curPath);
|
||||
File folder = new File(OUTPUT_DIRECTORY, curPath);
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
|
||||
|
||||
System.out.println("Parsing directory '" + curPath + "'");
|
||||
folder = new File(dojoDirectory + curPath);
|
||||
folder = new File(INPUT_DIRECTORY, curPath);
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.isFile()) {
|
||||
try {
|
||||
parseDojoData(file, curPath);
|
||||
}
|
||||
catch(FileNotFoundException ex) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open dojo file " + file.getAbsolutePath() + ".");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading dojo file " + file.getAbsolutePath() + ".");
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
@@ -203,9 +175,8 @@ public class MapleDojoUpdate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
parseDirectoryDojoData("");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,72 +1,38 @@
|
||||
/*
|
||||
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.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 mapleemptyitemwzchecker;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
This application has two objectives: it reports in a detailed file all itemids which is
|
||||
currently missing either a name entry in the String.wz or an item entry in the Item.wz;
|
||||
And it removes from the String.wz XMLs all entries which misses properties on Item.wz.
|
||||
* <p>
|
||||
* This application has two objectives: it reports in a detailed file all itemids which is
|
||||
* currently missing either a name entry in the String.wz or an item entry in the Item.wz;
|
||||
* And it removes from the String.wz XMLs all entries which misses properties on Item.wz.
|
||||
*/
|
||||
public class MapleEmptyItemWzChecker {
|
||||
|
||||
static String newFile = "lib/Report.txt";
|
||||
static String outputWzPath = "lib";
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static String wzPath = "../../wz";
|
||||
static String handbookPath = "../../handbook";
|
||||
static int initialStringLength = 50;
|
||||
static int itemFileNameSize = 13;
|
||||
|
||||
static byte status = 0;
|
||||
static int currentItemid = 0;
|
||||
static int currentDepth = 0;
|
||||
static Stack<String> currentPath = new Stack<>();
|
||||
static String currentFile;
|
||||
|
||||
static Map<Integer, String> stringWzItems = new HashMap<>();
|
||||
static Map<Integer, String> contentWzItems = new HashMap<>();
|
||||
|
||||
static Set<Integer> handbookItems = new HashSet<>();
|
||||
static Set<Integer> nonPropItems;
|
||||
|
||||
public class EmptyItemWzChecker {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("empty_item_wz_report.txt");
|
||||
private static final String OUTPUT_PATH = ToolConstants.OUTPUT_DIRECTORY.getPath();
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final int ITEM_FILE_NAME_SIZE = 13;
|
||||
|
||||
private static final Stack<String> currentPath = new Stack<>();
|
||||
private static final Map<Integer, String> stringWzItems = new HashMap<>();
|
||||
private static final Map<Integer, String> contentWzItems = new HashMap<>();
|
||||
private static final Set<Integer> handbookItems = new HashSet<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static InputStreamReader fileReader = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int currentItemid = 0;
|
||||
private static int currentDepth = 0;
|
||||
private static String currentFile;
|
||||
private static Set<Integer> nonPropItems;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -76,35 +42,33 @@ public class MapleEmptyItemWzChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
@@ -118,137 +82,135 @@ public class MapleEmptyItemWzChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getItemIdFromFilename(String name) {
|
||||
try {
|
||||
return Integer.valueOf(name.substring(0, name.indexOf('.')));
|
||||
} catch(Exception e) {
|
||||
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void inspectItemWzEntry() {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateItemToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String currentItemPath() {
|
||||
String s = currentFile + " -> ";
|
||||
|
||||
|
||||
for (String p : currentPath) {
|
||||
s += (p + "\\");
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
private static void translateItemToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
|
||||
currentPath.pop();
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
String d = getName(token);
|
||||
|
||||
if(status == 2) {
|
||||
currentItemid = Integer.valueOf(d);
|
||||
|
||||
if (status == 2) {
|
||||
currentItemid = Integer.parseInt(d);
|
||||
contentWzItems.put(currentItemid, currentItemPath());
|
||||
|
||||
|
||||
forwardCursor(status);
|
||||
} else {
|
||||
currentPath.push(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void inspectStringWzEntry() {
|
||||
String line = null;
|
||||
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateStringToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateStringToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
currentPath.pop();
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
String d = getName(token);
|
||||
|
||||
if(status == currentDepth) {
|
||||
currentItemid = Integer.valueOf(d);
|
||||
|
||||
if (status == currentDepth) {
|
||||
currentItemid = Integer.parseInt(d);
|
||||
stringWzItems.put(currentItemid, currentItemPath());
|
||||
//if (currentItemid >= 4000000) System.out.println(" " + currentItemid);
|
||||
|
||||
|
||||
forwardCursor(status);
|
||||
} else {
|
||||
currentPath.push(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void loadStringWzFile(String filePath, int depth) throws IOException {
|
||||
fileReader = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
currentFile = filePath;
|
||||
currentDepth = 2 + depth;
|
||||
//System.out.println(filePath + " depth " + depth);
|
||||
inspectStringWzEntry();
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void loadStringWz() throws IOException {
|
||||
System.out.println("Reading String.wz ...");
|
||||
String stringWzFiles[][] = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
|
||||
String stringWzPath = wzPath + "/String.wz/";
|
||||
|
||||
String[][] stringWzFiles = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
|
||||
|
||||
for (int i = 0; i < stringWzFiles.length; i++) {
|
||||
for (String dirFile : stringWzFiles[i]) {
|
||||
loadStringWzFile(stringWzPath + dirFile + ".img.xml", i);
|
||||
final String fileName = "/" + dirFile + ".img.xml";
|
||||
loadStringWzFile(WZFiles.STRING.getFilePath() + fileName, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void loadItemWz() throws IOException {
|
||||
System.out.println("Reading Item.wz ...");
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(wzPath + "/Item.wz", files);
|
||||
listFiles(WZFiles.ITEM.getFilePath(), files);
|
||||
|
||||
for (File f : files) {
|
||||
if (f.getParentFile().getName().contentEquals("Special")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(File f : files) {
|
||||
if (f.getParentFile().getName().contentEquals("Special")) continue;
|
||||
|
||||
//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);
|
||||
|
||||
|
||||
currentFile = f.getCanonicalPath();
|
||||
|
||||
if(f.getName().length() <= itemFileNameSize) {
|
||||
if (f.getName().length() <= ITEM_FILE_NAME_SIZE) {
|
||||
inspectItemWzEntry();
|
||||
} else { // pet file structure is similar to equips, maybe there are other item-types following this behaviour?
|
||||
int itemid = getItemIdFromFilename(f.getName());
|
||||
if(itemid < 0) {
|
||||
if (itemid < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -260,17 +222,19 @@ public class MapleEmptyItemWzChecker {
|
||||
fileReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void loadCharacterWz() throws IOException {
|
||||
System.out.println("Reading Character.wz ...");
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(wzPath + "/Character.wz", files);
|
||||
listFiles(WZFiles.CHARACTER.getFilePath(), files);
|
||||
|
||||
for (File f : files) {
|
||||
if (f.getParentFile().getName().contentEquals("Character.wz")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(File f : files) {
|
||||
if (f.getParentFile().getName().contentEquals("Character.wz")) continue;
|
||||
|
||||
int itemid = getItemIdFromFilename(f.getName());
|
||||
if(itemid < 0) {
|
||||
if (itemid < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -279,57 +243,56 @@ public class MapleEmptyItemWzChecker {
|
||||
contentWzItems.put(currentItemid, currentItemPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void calculateItemNameDiff(Set<Integer> emptyItemNames, Set<Integer> emptyNameItems) {
|
||||
for (Integer i : contentWzItems.keySet()) {
|
||||
if (!stringWzItems.containsKey(i)) {
|
||||
emptyNameItems.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Integer i : stringWzItems.keySet()) {
|
||||
if (!contentWzItems.containsKey(i)) {
|
||||
emptyItemNames.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readHandbookItems() throws IOException {
|
||||
System.out.println("Reading handbook ...");
|
||||
String[] handbookPaths = {"Equip", "Cash.txt", "Etc.txt", "Pet.txt", "Setup.txt", "Use.txt"};
|
||||
|
||||
|
||||
for (String path : handbookPaths) {
|
||||
readHandbookPath(handbookPath + "/" + path);
|
||||
readHandbookPath(ToolConstants.HANDBOOK_PATH + "/" + path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readHandbookPath(String filePath) throws IOException {
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
|
||||
|
||||
File testFile = new File(filePath);
|
||||
if (testFile.isDirectory()) {
|
||||
listFiles(filePath, files);
|
||||
} else {
|
||||
files.add(testFile);
|
||||
}
|
||||
|
||||
|
||||
for (File f : files) {
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
String[] tokens = line.split(" - ");
|
||||
|
||||
if (tokens[0].length() > 0) {
|
||||
int itemid = Integer.valueOf(tokens[0]);
|
||||
int itemid = Integer.parseInt(tokens[0]);
|
||||
handbookItems.add(itemid);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -337,60 +300,60 @@ public class MapleEmptyItemWzChecker {
|
||||
fileReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleEmptyItemWzChecker feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
private static List<Integer> getSortedItems(Set<Integer> items) {
|
||||
List<Integer> sortedItems = new ArrayList<>(items);
|
||||
Collections.sort(sortedItems);
|
||||
|
||||
|
||||
return sortedItems;
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileResults(Set<Integer> emptyItemNames, Set<Integer> emptyNameItems) {
|
||||
if (!emptyItemNames.isEmpty()) {
|
||||
printWriter.println("String.wz NAMES with no Item.wz node, " + emptyItemNames.size() + " entries:");
|
||||
|
||||
for(Integer itemid : getSortedItems(emptyItemNames)) {
|
||||
|
||||
for (Integer itemid : getSortedItems(emptyItemNames)) {
|
||||
printWriter.println(" " + itemid + " " + stringWzItems.get(itemid) + (handbookItems.contains(itemid) ? "" : " NOT FOUND"));
|
||||
}
|
||||
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
if (!emptyNameItems.isEmpty()) {
|
||||
printWriter.println("Item.wz ITEMS with no String.wz node, " + emptyNameItems.size() + " entries:");
|
||||
|
||||
for(Integer itemid : getSortedItems(emptyNameItems)) {
|
||||
|
||||
for (Integer itemid : getSortedItems(emptyNameItems)) {
|
||||
printWriter.println(" " + itemid + " " + contentWzItems.get(itemid) + (handbookItems.contains(itemid) ? "" : " NOT FOUND"));
|
||||
}
|
||||
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void reportItemNameDiff(Set<Integer> emptyItemNames, Set<Integer> emptyNameItems) throws IOException {
|
||||
System.out.println("Reporting results...");
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
printReportFileResults(emptyItemNames, emptyNameItems);
|
||||
|
||||
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
|
||||
private static void locateItemStringWzDiff() throws IOException {
|
||||
Set<Integer> emptyItemNames = new HashSet<>(), emptyNameItems = new HashSet<>();
|
||||
calculateItemNameDiff(emptyItemNames, emptyNameItems);
|
||||
|
||||
|
||||
reportItemNameDiff(emptyItemNames, emptyNameItems);
|
||||
nonPropItems = emptyItemNames;
|
||||
}
|
||||
|
||||
|
||||
private static void runEmptyItemWzChecker() throws IOException {
|
||||
readHandbookItems();
|
||||
|
||||
@@ -400,77 +363,75 @@ public class MapleEmptyItemWzChecker {
|
||||
|
||||
locateItemStringWzDiff();
|
||||
}
|
||||
|
||||
|
||||
private static void generateStringWzEntry() {
|
||||
String line = null;
|
||||
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
updateStringToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void updateStringToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == currentDepth && nonPropItems.contains(Integer.valueOf(getName(token)))) {
|
||||
forwardCursor(status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(token);
|
||||
}
|
||||
|
||||
|
||||
private static void generateStringWzFile(String filePath, int depth) throws IOException {
|
||||
fileReader = new InputStreamReader(new FileInputStream(wzPath + filePath), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(WZFiles.DIRECTORY + filePath), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
printWriter = new PrintWriter(outputWzPath + filePath, "UTF-8");
|
||||
printWriter = new PrintWriter(OUTPUT_PATH + filePath, StandardCharsets.UTF_8);
|
||||
currentDepth = 2 + depth;
|
||||
|
||||
|
||||
//System.out.println(filePath + " depth " + depth);
|
||||
generateStringWzEntry();
|
||||
|
||||
|
||||
printWriter.close();
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void generateStringWz() throws IOException {
|
||||
System.out.println("Generating clean String.wz ...");
|
||||
String stringWzFiles[][] = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
|
||||
String[][] stringWzFiles = {{"Cash", "Consume", "Ins", "Pet"}, {"Etc"}, {"Eqp"}};
|
||||
String stringWzPath = "/String.wz/";
|
||||
|
||||
File folder = new File(outputWzPath + "/String.wz/");
|
||||
|
||||
File folder = new File(OUTPUT_PATH + "/String.wz/");
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < stringWzFiles.length; i++) {
|
||||
for (String dirFile : stringWzFiles[i]) {
|
||||
generateStringWzFile(stringWzPath + dirFile + ".img.xml", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
runEmptyItemWzChecker();
|
||||
generateStringWz();
|
||||
|
||||
|
||||
System.out.println("Done!");
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,82 +1,51 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
package tools.mapletools;
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 mapleequipmentomnileveler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
|
||||
This application parses the Character.wz folder inputted and adds/updates the "info/level"
|
||||
node on every known equipment id. This addition enables client-side view of the equipment
|
||||
level attribute on every equipment in the game, given proper item visibility, be it from
|
||||
own equipments or from other players.
|
||||
|
||||
Estimated parse time: 7 minutes
|
||||
|
||||
* <p>
|
||||
* This application parses the Character.wz folder inputted and adds/updates the "info/level"
|
||||
* node on every known equipment id. This addition enables client-side view of the equipment
|
||||
* level attribute on every equipment in the game, given proper item visibility, be it from
|
||||
* own equipments or from other players.
|
||||
* <p>
|
||||
* Estimated parse time: 7 minutes
|
||||
*/
|
||||
public class MapleEquipmentOmnileveler {
|
||||
public class EquipmentOmniLeveller {
|
||||
private static final File INPUT_DIRECTORY = WZFiles.CHARACTER.getFile();
|
||||
private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("equips-with-levels");
|
||||
private static final int INITIAL_STRING_LENGTH = 250;
|
||||
private static final int FIXED_EXP = 10000;
|
||||
private static final int MAX_EQP_LEVEL = 30;
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static InputStreamReader fileReader = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
|
||||
private static int infoTagState = -1;
|
||||
private static int infoTagExpState = -1;
|
||||
private static boolean infoTagLevel;
|
||||
private static boolean infoTagLevelExp;
|
||||
private static boolean infoTagLevelInfo;
|
||||
private static int parsedLevels = 0;
|
||||
private static byte status;
|
||||
private static boolean upgradeable;
|
||||
private static boolean cash;
|
||||
|
||||
static String equipDirectory = "lib/original/";
|
||||
static String outputDirectory = "lib/updated/";
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static int initialStringLength = 250;
|
||||
|
||||
static int fixedExp = 10000;
|
||||
static int maxEqpLevel = 30;
|
||||
|
||||
static int infoTagState = -1, infoTagExpState = -1;
|
||||
|
||||
static boolean infoTagLevel;
|
||||
static boolean infoTagLevelExp;
|
||||
static boolean infoTagLevelInfo;
|
||||
|
||||
static int parsedLevels = 0;
|
||||
|
||||
static byte status;
|
||||
static boolean upgradeable;
|
||||
static boolean cash;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
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];
|
||||
try {
|
||||
token.getChars(i, j, dest, 0);
|
||||
} catch (StringIndexOutOfBoundsException e) {
|
||||
@@ -87,14 +56,15 @@ public class MapleEquipmentOmnileveler {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Thread.sleep(100000000);
|
||||
} catch (Exception ex) {}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -104,153 +74,147 @@ public class MapleEquipmentOmnileveler {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
printWriter.println(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateLevelCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
|
||||
try {
|
||||
infoTagLevelInfo = false;
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
translateLevelToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateInfoTag(int st) {
|
||||
infoTagLevel = false;
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) { // skipping directory & canvas definition
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) { // skipping directory & canvas definition
|
||||
translateInfoToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
if (!upgradeable || cash) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printUpdatedLevelExp() {
|
||||
printWriter.println(" <int name=\"exp\" value=\"" + fixedExp + "\"/>");
|
||||
printWriter.println(" <int name=\"exp\" value=\"" + FIXED_EXP + "\"/>");
|
||||
}
|
||||
|
||||
|
||||
private static void printDefaultLevel(int level) {
|
||||
printWriter.println(" <imgdir name=\"" + level + "\">");
|
||||
printUpdatedLevelExp();
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
|
||||
private static void printDefaultLevelInfoTag() {
|
||||
printWriter.println(" <imgdir name=\"info\">");
|
||||
for (int i = 1; i <= maxEqpLevel; i++) printDefaultLevel(i);
|
||||
for (int i = 1; i <= MAX_EQP_LEVEL; i++) {
|
||||
printDefaultLevel(i);
|
||||
}
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
|
||||
private static void printDefaultLevelTag() {
|
||||
printWriter.println(" <imgdir name=\"level\">");
|
||||
printDefaultLevelInfoTag();
|
||||
printWriter.println(" </imgdir>");
|
||||
}
|
||||
|
||||
|
||||
private static void processLevelInfoTag(int st) {
|
||||
String line;
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
translateLevelExpToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void processLevelInfoSet(int st) {
|
||||
parsedLevels = (1 << maxEqpLevel) - 1;
|
||||
|
||||
parsedLevels = (1 << MAX_EQP_LEVEL) - 1;
|
||||
|
||||
String line;
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
translateLevelInfoSetToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateLevelToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
if (status == 3) {
|
||||
if (!infoTagLevelInfo) {
|
||||
printDefaultLevelInfoTag();
|
||||
}
|
||||
}
|
||||
printWriter.println(token);
|
||||
|
||||
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
printWriter.println(token);
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 4) {
|
||||
String d = getName(token);
|
||||
if(d.contentEquals("info")) {
|
||||
if (d.contentEquals("info")) {
|
||||
infoTagLevelInfo = true;
|
||||
processLevelInfoSet(status);
|
||||
} else {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printWriter.println(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateLevelInfoSetToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
|
||||
if (status == 3) {
|
||||
if (parsedLevels != 0) {
|
||||
for (int i = 0; i < maxEqpLevel; i++) {
|
||||
for (int i = 0; i < MAX_EQP_LEVEL; i++) {
|
||||
if ((parsedLevels >> i) % 2 != 0) {
|
||||
int level = i + 1;
|
||||
printDefaultLevel(level);
|
||||
@@ -258,47 +222,43 @@ public class MapleEquipmentOmnileveler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(token);
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
printWriter.println(token);
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 5) {
|
||||
int level = Integer.parseInt(getName(token)) - 1;
|
||||
parsedLevels ^= (1 << level);
|
||||
|
||||
|
||||
infoTagLevelExp = false;
|
||||
infoTagExpState = status; // status: 5
|
||||
processLevelInfoTag(status);
|
||||
processLevelInfoTag(status);
|
||||
infoTagExpState = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printWriter.println(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateLevelExpToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
|
||||
if (status < infoTagExpState) {
|
||||
if (!infoTagLevelExp) {
|
||||
printUpdatedLevelExp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(token);
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
printWriter.println(token);
|
||||
status += 1;
|
||||
|
||||
|
||||
forwardCursor(status);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
String name = getName(token);
|
||||
if (name.contentEquals("exp")) {
|
||||
infoTagLevelExp = true;
|
||||
@@ -308,23 +268,22 @@ public class MapleEquipmentOmnileveler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateInfoToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
|
||||
if (status < infoTagState) {
|
||||
if (!infoTagLevel) {
|
||||
printDefaultLevelTag();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(token);
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
printWriter.println(token);
|
||||
|
||||
|
||||
String d = getName(token);
|
||||
if (d.contentEquals("level")) {
|
||||
infoTagLevel = true;
|
||||
@@ -332,17 +291,16 @@ public class MapleEquipmentOmnileveler {
|
||||
} else {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
String name = getName(token);
|
||||
|
||||
switch(name) {
|
||||
|
||||
switch (name) {
|
||||
case "cash":
|
||||
if (!getValue(token).contentEquals("0")) {
|
||||
cash = true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case "tuc":
|
||||
case "incPAD":
|
||||
case "incMAD":
|
||||
@@ -363,25 +321,24 @@ public class MapleEquipmentOmnileveler {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean translateToken(String token) {
|
||||
boolean accessInfoTag = false;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
printWriter.println(token);
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
printWriter.println(token);
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 2) {
|
||||
String d = getName(token);
|
||||
if(!d.contentEquals("info")) {
|
||||
if (!d.contentEquals("info")) {
|
||||
forwardCursor(status);
|
||||
} else {
|
||||
accessInfoTag = true;
|
||||
@@ -389,22 +346,21 @@ public class MapleEquipmentOmnileveler {
|
||||
} else if (status > 2) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
printWriter.println(token);
|
||||
}
|
||||
|
||||
|
||||
return accessInfoTag;
|
||||
}
|
||||
|
||||
|
||||
private static void copyCashItemData(File file, String curPath) throws IOException {
|
||||
printWriter = new PrintWriter(outputDirectory + curPath + file.getName(), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
|
||||
printWriter = new PrintWriter(new File(OUTPUT_DIRECTORY, curPath + file.getName()), StandardCharsets.UTF_8);
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
String line;
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
printWriter.println(line);
|
||||
}
|
||||
|
||||
@@ -413,70 +369,66 @@ public class MapleEquipmentOmnileveler {
|
||||
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
|
||||
private static void parseEquipData(File file, String curPath) throws IOException {
|
||||
printWriter = new PrintWriter(outputDirectory + curPath + file.getName(), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
|
||||
printWriter = new PrintWriter(new File(OUTPUT_DIRECTORY, curPath + file.getName()), StandardCharsets.UTF_8);
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
try {
|
||||
status = 0;
|
||||
upgradeable = false;
|
||||
cash = false;
|
||||
|
||||
|
||||
String line;
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (translateToken(line)) {
|
||||
infoTagState = status; // status: 2
|
||||
translateInfoTag(status);
|
||||
infoTagState = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
|
||||
printFileFooter();
|
||||
printWriter.close();
|
||||
} catch (RuntimeException e) {
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
|
||||
printWriter.close();
|
||||
|
||||
|
||||
copyCashItemData(file, curPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printFileFooter() {
|
||||
printWriter.println("<!--");
|
||||
printWriter.println(" # WZ XML File parsed by the MapleEquipmentOmnilever feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account info from the server-side WZ.xmls.");
|
||||
printWriter.println("-->");
|
||||
}
|
||||
|
||||
|
||||
private static void parseDirectoryEquipData(String curPath) {
|
||||
File folder = new File(outputDirectory + curPath);
|
||||
File folder = new File(OUTPUT_DIRECTORY, curPath);
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
|
||||
|
||||
System.out.println("Parsing directory '" + curPath + "'");
|
||||
folder = new File(equipDirectory + curPath);
|
||||
folder = new File(INPUT_DIRECTORY, curPath);
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.isFile()) {
|
||||
try {
|
||||
parseEquipData(file, curPath);
|
||||
}
|
||||
catch(FileNotFoundException ex) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open equip file " + file.getAbsolutePath() + ".");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading equip file " + file.getAbsolutePath() + ".");
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
@@ -484,9 +436,8 @@ public class MapleEquipmentOmnileveler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
parseDirectoryEquipData("");
|
||||
}
|
||||
|
||||
}
|
||||
102
src/main/java/tools/mapletools/EventMethodFiller.java
Normal file
102
src/main/java/tools/mapletools/EventMethodFiller.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application objective is to read all scripts from the event folder
|
||||
* and fill empty functions for every function name not yet present in the
|
||||
* script.
|
||||
* <p>
|
||||
* Estimated parse time: 10 seconds
|
||||
*/
|
||||
public class EventMethodFiller {
|
||||
private static boolean foundMatchingDataOnFile(String fileContent, Pattern pattern) {
|
||||
Matcher matcher = pattern.matcher(fileContent);
|
||||
return matcher.find();
|
||||
}
|
||||
|
||||
private static void fileSearchMatchingData(File file, Map<Pattern, String> functions) {
|
||||
try {
|
||||
String fileContent = FileUtils.readFileToString(file, "UTF-8");
|
||||
List<String> fillFunctions = new LinkedList<>();
|
||||
|
||||
for (Map.Entry<Pattern, String> f : functions.entrySet()) {
|
||||
if (!foundMatchingDataOnFile(fileContent, f.getKey())) {
|
||||
fillFunctions.add(f.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (!fillFunctions.isEmpty()) {
|
||||
System.out.println("Filling out " + file.getName() + "...");
|
||||
|
||||
FileWriter fileWriter = new FileWriter(file, true);
|
||||
PrintWriter printWriter = new PrintWriter(fileWriter);
|
||||
|
||||
printWriter.println();
|
||||
printWriter.println();
|
||||
printWriter.println("// ---------- FILLER FUNCTIONS ----------");
|
||||
printWriter.println();
|
||||
|
||||
for (String s : fillFunctions) {
|
||||
printWriter.println(s);
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
printWriter.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void filterDirectorySearchMatchingData(String directoryPath, Map<Pattern, String> functions) {
|
||||
Iterator iter = FileUtils.iterateFiles(new File(directoryPath), new String[]{"sql", "js", "txt", "java"}, true);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
File file = (File) iter.next();
|
||||
fileSearchMatchingData(file, functions);
|
||||
}
|
||||
}
|
||||
|
||||
private static Pattern compileJsFunctionPattern(String function) {
|
||||
String jsFunction = "function(\\s)+";
|
||||
return Pattern.compile(jsFunction + function);
|
||||
}
|
||||
|
||||
private static Map<Pattern, String> getFunctions() {
|
||||
Map<Pattern, String> functions = new HashMap<>();
|
||||
functions.put(compileJsFunctionPattern("playerEntry"), "function playerEntry(eim, player) {}");
|
||||
functions.put(compileJsFunctionPattern("playerExit"), "function playerExit(eim, player) {}");
|
||||
functions.put(compileJsFunctionPattern("scheduledTimeout"), "function scheduledTimeout(eim) {}");
|
||||
functions.put(compileJsFunctionPattern("playerUnregistered"), "function playerUnregistered(eim, player) {}");
|
||||
functions.put(compileJsFunctionPattern("changedLeader"), "function changedLeader(eim, leader) {}");
|
||||
functions.put(compileJsFunctionPattern("monsterKilled"), "function monsterKilled(mob, eim) {}");
|
||||
functions.put(compileJsFunctionPattern("allMonstersDead"), "function allMonstersDead(eim) {}");
|
||||
functions.put(compileJsFunctionPattern("playerDisconnected"), "function playerDisconnected(eim, player) {}");
|
||||
functions.put(compileJsFunctionPattern("monsterValue"), "function monsterValue(eim, mobid) {return 0;}");
|
||||
functions.put(compileJsFunctionPattern("dispose"), "function dispose() {}");
|
||||
functions.put(compileJsFunctionPattern("leftParty"), "function leftParty(eim, player) {}");
|
||||
functions.put(compileJsFunctionPattern("disbandParty"), "function disbandParty(eim, player) {}");
|
||||
functions.put(compileJsFunctionPattern("clearPQ"), "function clearPQ(eim) {}");
|
||||
functions.put(compileJsFunctionPattern("afterSetup"), "function afterSetup(eim) {}");
|
||||
functions.put(compileJsFunctionPattern("cancelSchedule"), "function cancelSchedule() {}");
|
||||
functions.put(compileJsFunctionPattern("setup"), "function setup(eim, leaderid) {}");
|
||||
//put(compileJsFunctionPattern("getEligibleParty"), "function getEligibleParty(party) {}"); not really needed
|
||||
return functions;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
filterDirectorySearchMatchingData(ToolConstants.SCRIPTS_PATH + "/event", getFunctions());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +1,36 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
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 maplegachaponitemidretriever;
|
||||
package tools.mapletools;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application reads metadata for the gachapons found on the "gachapon_items.txt"
|
||||
* recipe file, then checks up the Handbook DB (installed through MapleIdRetriever)
|
||||
* and translates the item names from the recipe file into their respective itemids.
|
||||
* The translated itemids are then stored in specific gachapon files inside the
|
||||
* "lib/gachapons" folder.
|
||||
*
|
||||
* <p>
|
||||
* Estimated parse time: 1 minute
|
||||
*/
|
||||
public class MapleGachaponItemidRetriever {
|
||||
public class GachaponItemIdRetriever {
|
||||
private static final File INPUT_FILE = ToolConstants.getInputFile("gachapon_items.txt");
|
||||
private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("gachapons");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
private static final Pattern pattern = Pattern.compile("(\\d*)%");
|
||||
private static final int[] scrollsChances = new int[]{10, 15, 30, 60, 65, 70, 100};
|
||||
private static final Map<GachaponScroll, List<Integer>> scrollItemids = new HashMap<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
|
||||
static Connection con = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
static PrintWriter printWriter = null;
|
||||
|
||||
// ------- SET-UP section arguments --------
|
||||
|
||||
static String directoryName = "./handbook/";
|
||||
|
||||
// ------- SEARCH section arguments --------
|
||||
|
||||
static String inputName = "lib/gachapon_items.txt";
|
||||
static String outputPath = "lib/gachapons/";
|
||||
|
||||
static Pattern p = Pattern.compile("(\\d*)%");
|
||||
static int[] scrollsChances = new int[]{10, 15, 30, 60, 65, 70, 100};
|
||||
|
||||
static Map<GachaponScroll, List<Integer>> scrollItemids = new HashMap<>();
|
||||
|
||||
private static void insertGachaponScrollItemid(Integer id, String name, String description, boolean both) {
|
||||
GachaponScroll gachaScroll = getGachaponScroll(name, description, both);
|
||||
|
||||
@@ -74,25 +42,25 @@ public class MapleGachaponItemidRetriever {
|
||||
|
||||
list.add(id);
|
||||
}
|
||||
|
||||
|
||||
private static void loadHandbookUseNames() throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM `handbook` WHERE `id` >= 2040000 AND `id` < 2050000 ORDER BY `id` ASC;");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
Integer id = rs.getInt("id");
|
||||
String name = rs.getString("name");
|
||||
|
||||
|
||||
if (isUpgradeScroll(name)) {
|
||||
String description = rs.getString("description");
|
||||
insertGachaponScrollItemid(id, name, description, false);
|
||||
insertGachaponScrollItemid(id, name, description, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
|
||||
|
||||
/*
|
||||
for (Entry<GachaponScroll, List<Integer>> e : scrollItemids.entrySet()) {
|
||||
System.out.println(e);
|
||||
@@ -100,41 +68,41 @@ public class MapleGachaponItemidRetriever {
|
||||
System.out.println("------------");
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
private static class GachaponScroll {
|
||||
private String header;
|
||||
private String target;
|
||||
private String buff;
|
||||
private int prop;
|
||||
|
||||
|
||||
private GachaponScroll(GachaponScroll from, int prop) {
|
||||
this.header = from.header;
|
||||
this.target = from.target;
|
||||
this.buff = from.buff;
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
|
||||
private GachaponScroll(String name, String description, boolean both) {
|
||||
String[] params = name.split(" for ");
|
||||
if (params.length < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String header = both ? "scroll" : " " + params[0];
|
||||
String target = params[1];
|
||||
|
||||
int prop = 0;
|
||||
String buff = params[2];
|
||||
|
||||
Matcher m = p.matcher(buff);
|
||||
Matcher m = pattern.matcher(buff);
|
||||
if (m.find()) {
|
||||
prop = Integer.valueOf(m.group(1));
|
||||
prop = Integer.parseInt(m.group(1));
|
||||
buff = buff.substring(0, m.start() - 1).trim();
|
||||
} else {
|
||||
m = p.matcher(description);
|
||||
|
||||
m = pattern.matcher(description);
|
||||
|
||||
if (m.find()) {
|
||||
prop = Integer.valueOf(m.group(1));
|
||||
prop = Integer.parseInt(m.group(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,45 +111,54 @@ public class MapleGachaponItemidRetriever {
|
||||
buff = buff.substring(0, idx);
|
||||
}
|
||||
buff = buff.replace(".", "");
|
||||
|
||||
|
||||
this.header = header;
|
||||
this.target = target;
|
||||
this.buff = buff;
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = prop ^ (prop >>> 32);
|
||||
result = 31 * result + (header != null ? header.hashCode() : 0);
|
||||
result = 31 * result + (header != null ? header.hashCode() : 0);
|
||||
result = 31 * result + (target != null ? target.hashCode() : 0);
|
||||
result = 31 * result + (buff != null ? buff.hashCode() : 0);
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
GachaponScroll sc = (GachaponScroll) o;
|
||||
if (header != null ? !header.equals(sc.header) : sc.header != null) return false;
|
||||
if (target != null ? !target.equals(sc.target) : sc.target != null) return false;
|
||||
if (buff != null ? !buff.equals(sc.buff) : sc.buff != null) return false;
|
||||
if (prop != sc.prop) return false;
|
||||
return true;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
GachaponScroll sc = (GachaponScroll) o;
|
||||
if (header != null ? !header.equals(sc.header) : sc.header != null) {
|
||||
return false;
|
||||
}
|
||||
if (target != null ? !target.equals(sc.target) : sc.target != null) {
|
||||
return false;
|
||||
}
|
||||
if (buff != null ? !buff.equals(sc.buff) : sc.buff != null) {
|
||||
return false;
|
||||
}
|
||||
return prop == sc.prop;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return header + " for " + target + " for " + buff + " - " + prop + "%";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static String getGachaponScrollResults(String line, boolean both) {
|
||||
String str = "";
|
||||
List<GachaponScroll> gachaScrollList;
|
||||
|
||||
|
||||
GachaponScroll gachaScroll = getGachaponScroll(line, "", both);
|
||||
if (gachaScroll.prop != 0) {
|
||||
gachaScrollList = Collections.singletonList(gachaScroll);
|
||||
@@ -192,7 +169,7 @@ public class MapleGachaponItemidRetriever {
|
||||
gachaScrollList.add(new GachaponScroll(gachaScroll, prop));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (GachaponScroll gs : gachaScrollList) {
|
||||
List<Integer> gachaItemids = scrollItemids.get(gs);
|
||||
if (gachaItemids != null) {
|
||||
@@ -209,10 +186,10 @@ public class MapleGachaponItemidRetriever {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
private static GachaponScroll getGachaponScroll(String name, String description, boolean both) {
|
||||
name = name.toLowerCase();
|
||||
name = name.replace("for acc ", "for accuracy ");
|
||||
@@ -222,22 +199,22 @@ public class MapleGachaponItemidRetriever {
|
||||
name = name.replace("for attack", "for att");
|
||||
name = name.replace("1-handed", "one-handed");
|
||||
name = name.replace("2-handed", "two-handed");
|
||||
|
||||
|
||||
return new GachaponScroll(name, description, both);
|
||||
}
|
||||
|
||||
|
||||
private static boolean isUpgradeScroll(String name) {
|
||||
return name.matches("^(([D|d]ark )?[S|s]croll for).*");
|
||||
}
|
||||
|
||||
|
||||
private static void fetchLineOnMapleHandbook(String line, String rarity) throws SQLException {
|
||||
String str = "";
|
||||
if (!isUpgradeScroll(line)) {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? COLLATE latin1_general_ci ORDER BY `id` ASC;");
|
||||
PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? ORDER BY `id` ASC;");
|
||||
ps.setString(1, line);
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
int id = rs.getInt("id");
|
||||
|
||||
str += Integer.toString(id);
|
||||
@@ -250,37 +227,37 @@ public class MapleGachaponItemidRetriever {
|
||||
str += getGachaponScrollResults(line, false);
|
||||
if (str.isEmpty()) {
|
||||
str += getGachaponScrollResults(line, true);
|
||||
|
||||
|
||||
if (str.isEmpty()) {
|
||||
System.out.println("NONE for '" + line + "' : " + getGachaponScroll(line, "", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (str.isEmpty()) {
|
||||
str += line;
|
||||
}
|
||||
|
||||
|
||||
if (rarity != null) {
|
||||
str += ("- " + rarity);
|
||||
}
|
||||
|
||||
printWriter.println(str);
|
||||
}
|
||||
|
||||
|
||||
private static void fetchDataOnMapleHandbook() throws SQLException {
|
||||
String line;
|
||||
|
||||
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(inputName), "UTF-8");
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
int skip = 0;
|
||||
boolean lineHeader = false;
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (skip > 0) {
|
||||
skip--;
|
||||
|
||||
|
||||
if (lineHeader) {
|
||||
if (!line.isEmpty()) {
|
||||
lineHeader = false;
|
||||
@@ -291,14 +268,19 @@ public class MapleGachaponItemidRetriever {
|
||||
} else if (line.isEmpty()) {
|
||||
printWriter.println("");
|
||||
} else if (line.startsWith("Gachapon ")) {
|
||||
String s[] = line.split("<EFBFBD> ");
|
||||
String[] s = line.split("<EFBFBD> ");
|
||||
String gachaponName = s[s.length - 1];
|
||||
gachaponName = gachaponName.replace(" ", "_");
|
||||
gachaponName = gachaponName.toLowerCase();
|
||||
|
||||
if (printWriter != null) printWriter.close();
|
||||
printWriter = new PrintWriter(outputPath + gachaponName + ".txt", "UTF-8");
|
||||
|
||||
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
}
|
||||
File outputFile = new File(OUTPUT_DIRECTORY, gachaponName + ".txt");
|
||||
setupDirectories(outputFile);
|
||||
|
||||
printWriter = new PrintWriter(outputFile, StandardCharsets.UTF_8);
|
||||
|
||||
skip = 2;
|
||||
lineHeader = true;
|
||||
} else if (line.startsWith(".")) {
|
||||
@@ -316,44 +298,33 @@ public class MapleGachaponItemidRetriever {
|
||||
}
|
||||
}
|
||||
|
||||
if (printWriter != null) printWriter.close();
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
}
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
catch(FileNotFoundException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void setupDirectories(File file) {
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
Class.forName(driver).newInstance();
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
loadHandbookUseNames();
|
||||
fetchDataOnMapleHandbook();
|
||||
|
||||
con.close();
|
||||
}
|
||||
|
||||
catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Error: invalid SQL syntax");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(ClassNotFoundException e) {
|
||||
System.out.println("Error: could not find class");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(InstantiationException | IllegalAccessException e) {
|
||||
System.out.println("Error: instantiation failure");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,86 +1,56 @@
|
||||
/*
|
||||
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
|
||||
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 mapleidretriever;
|
||||
package tools.mapletools;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application acts two-way: first section sets up a table on the SQL Server with all the names used within MapleStory,
|
||||
* and the second queries all the names placed inside "fetch.txt", returning in the same line order the ids of the elements.
|
||||
* In case of multiple entries with the same name, multiple ids will be returned in the same line split by a simple space
|
||||
* in ascending order. An empty line means that no entry with the given name in a line has been found.
|
||||
*
|
||||
* <p>
|
||||
* IMPORTANT: this will fail for fetching MAP ID (you shouldn't be using this program for these, just checking them up in the
|
||||
* handbook is enough anyway).
|
||||
*
|
||||
* Set whether you are first installing the handbook on the SQL Server (TRUE) or just fetching whatever is on your "fetch.txt"
|
||||
* <p>
|
||||
* Set whether you are first installing the handbook on the SQL Server (TRUE) or just fetching whatever is on your "fetch_ids.txt"
|
||||
* file (FALSE) on the INSTALL_SQLTABLE property and build the project. With all done, run the Java executable.
|
||||
*
|
||||
* <p>
|
||||
* Expected installing time: 30 minutes
|
||||
*
|
||||
*/
|
||||
public class MapleIdRetriever {
|
||||
private final static boolean INSTALL_SQLTABLE = true;
|
||||
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
|
||||
static Connection con = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
static PrintWriter printWriter = null;
|
||||
|
||||
// ------- SET-UP section arguments --------
|
||||
|
||||
static String directoryName = "./handbook/";
|
||||
|
||||
// ------- SEARCH section arguments --------
|
||||
|
||||
static String inputName = "lib/fetch.txt";
|
||||
static String outputName = "lib/result.txt";
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
public class IdRetriever {
|
||||
private static final boolean INSTALL_SQLTABLE = true;
|
||||
private static final File INPUT_FILE = ToolConstants.getInputFile("fetch_ids.txt");
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("fetched_ids.txt");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
// get all the files from a directory
|
||||
File[] fList = directory.listFiles();
|
||||
for (File file : fList) {
|
||||
if (file.isFile()) {
|
||||
files.add(file);
|
||||
} else if (file.isDirectory()) {
|
||||
listFiles(file.getAbsolutePath(), files);
|
||||
}
|
||||
private static InputStreamReader fileReader = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
// get all the files from a directory
|
||||
File[] fList = directory.listFiles();
|
||||
for (File file : fList) {
|
||||
if (file.isFile()) {
|
||||
files.add(file);
|
||||
} else if (file.isDirectory()) {
|
||||
listFiles(file.getAbsolutePath(), files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void parseMapleHandbookLine(String line) throws SQLException {
|
||||
String[] tokens = line.split(" - ", 3);
|
||||
|
||||
if(tokens.length > 1) {
|
||||
|
||||
if (tokens.length > 1) {
|
||||
PreparedStatement ps = con.prepareStatement("INSERT INTO `handbook` (`id`, `name`, `description`) VALUES (?, ?, ?)");
|
||||
try {
|
||||
ps.setInt(1, Integer.parseInt(tokens[0]));
|
||||
@@ -91,135 +61,132 @@ public class MapleIdRetriever {
|
||||
ps.setString(2, tokens[1]);
|
||||
ps.setString(3, tokens.length > 2 ? tokens[2] : "");
|
||||
ps.execute();
|
||||
|
||||
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void parseMapleHandbookFile(File fileObj) throws SQLException {
|
||||
if (shouldSkipParsingFile(fileObj.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String line;
|
||||
|
||||
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileObj), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileObj), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
System.out.println("Parsing file '" + fileObj.getCanonicalPath() + "'.");
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
parseMapleHandbookLine(line);
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
try {
|
||||
parseMapleHandbookLine(line);
|
||||
} catch (SQLException e) {
|
||||
System.err.println("Failed to parse line: " + line);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
catch(FileNotFoundException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Quest.txt has different formatting: id is last token on the line, instead of the first
|
||||
private static boolean shouldSkipParsingFile(String fileName) {
|
||||
return "Quest.txt".equals(fileName);
|
||||
}
|
||||
|
||||
private static void setupSqlTable() throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("DROP TABLE IF EXISTS `handbook`;");
|
||||
ps.execute();
|
||||
ps.close();
|
||||
|
||||
|
||||
ps = con.prepareStatement("CREATE TABLE `handbook` ("
|
||||
+ "`key` int(10) unsigned NOT NULL AUTO_INCREMENT,"
|
||||
+ "`id` int(10) DEFAULT NULL,"
|
||||
+ "`name` varchar(200) DEFAULT NULL,"
|
||||
+ "`description` varchar(1000) DEFAULT '',"
|
||||
+ "PRIMARY KEY (`key`)"
|
||||
+ ") ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;");
|
||||
+ ");");
|
||||
ps.execute();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
|
||||
private static void parseMapleHandbook() throws SQLException {
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
|
||||
listFiles(directoryName, files);
|
||||
if(files.isEmpty()) return;
|
||||
listFiles(ToolConstants.HANDBOOK_PATH, files);
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setupSqlTable();
|
||||
|
||||
for(File f: files) {
|
||||
for (File f : files) {
|
||||
parseMapleHandbookFile(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void fetchDataOnMapleHandbook() throws SQLException {
|
||||
String line;
|
||||
|
||||
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(inputName), "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
printWriter = new PrintWriter(outputName, "UTF-8");
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
if(line.isEmpty()) {
|
||||
|
||||
PrintWriter printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (line.isEmpty()) {
|
||||
printWriter.println("");
|
||||
continue;
|
||||
}
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? COLLATE latin1_general_ci ORDER BY `id` ASC;");
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("SELECT `id` FROM `handbook` WHERE `name` LIKE ? ORDER BY `id` ASC;");
|
||||
ps.setString(1, line);
|
||||
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
|
||||
String str = "";
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
int id = rs.getInt("id");
|
||||
|
||||
|
||||
str += Integer.toString(id);
|
||||
str += " ";
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
|
||||
|
||||
printWriter.println(str);
|
||||
}
|
||||
|
||||
printWriter.close();
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
catch(FileNotFoundException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
Class.forName(driver).newInstance();
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
if(INSTALL_SQLTABLE) parseMapleHandbook();
|
||||
else fetchDataOnMapleHandbook();
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
if (INSTALL_SQLTABLE) {
|
||||
parseMapleHandbook();
|
||||
} else {
|
||||
fetchDataOnMapleHandbook();
|
||||
}
|
||||
|
||||
con.close();
|
||||
}
|
||||
|
||||
catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Error: invalid SQL syntax");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(ClassNotFoundException e) {
|
||||
System.out.println("Error: could not find class");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(InstantiationException | IllegalAccessException e) {
|
||||
System.out.println("Error: instantiation failure");
|
||||
System.out.println(e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
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 mapleskillmakerfetcher;
|
||||
package tools.mapletools;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.List;
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class MapleMakerItemEntry {
|
||||
public class MakerItemEntry {
|
||||
public int id = -1;
|
||||
public int itemid = -1;
|
||||
public int reqLevel = -1;
|
||||
@@ -43,7 +43,7 @@ public class MapleMakerItemEntry {
|
||||
public List<int[]> recipeList = null;
|
||||
public List<int[]> randomList = null;
|
||||
|
||||
public MapleMakerItemEntry(int id, int itemid, int reqLevel, int reqMakerLevel, int reqItem, int reqMeso, int reqEquip, int catalyst, int quantity, int tuc, int recipeCount, int recipeItem, List<int[]> recipeList, List<int[]> randomList) {
|
||||
MakerItemEntry(int id, int itemid, int reqLevel, int reqMakerLevel, int reqItem, int reqMeso, int reqEquip, int catalyst, int quantity, int tuc, int recipeCount, int recipeItem, List<int[]> recipeList, List<int[]> randomList) {
|
||||
this.id = id;
|
||||
this.itemid = itemid;
|
||||
this.reqLevel = reqLevel;
|
||||
@@ -1,56 +1,25 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 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.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 maplemapfieldlimitchecker;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
This application seeks from the XMLs all mapid entries that holds the specified
|
||||
fieldLimit.
|
||||
* <p>
|
||||
* This application seeks from the XMLs all mapid entries that holds the specified
|
||||
* fieldLimit.
|
||||
*/
|
||||
public class MapleMapFieldLimitChecker {
|
||||
|
||||
static String newFile = "lib/Report.txt";
|
||||
static String outputWzPath = "lib";
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static String wzPath = "../../wz";
|
||||
static int initialStringLength = 50;
|
||||
static int itemFileNameSize = 13;
|
||||
|
||||
static int fieldLimit = 0x400000;
|
||||
|
||||
static byte status = 0;
|
||||
static int mapid = 0;
|
||||
|
||||
public class MapFieldLimitChecker {
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final int FIELD_LIMIT = 0x400000;
|
||||
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int mapid = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -60,13 +29,13 @@ public class MapleMapFieldLimitChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -76,35 +45,33 @@ public class MapleMapFieldLimitChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void listFiles(String directoryName, ArrayList<File> files) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
@@ -118,65 +85,62 @@ public class MapleMapFieldLimitChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getMapIdFromFilename(String name) {
|
||||
try {
|
||||
return Integer.valueOf(name.substring(0, name.indexOf('.')));
|
||||
} catch(Exception e) {
|
||||
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 2) {
|
||||
String d = getName(token);
|
||||
if (!d.contentEquals("info")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (status == 2) {
|
||||
String d = getName(token);
|
||||
|
||||
|
||||
if (d.contentEquals("fieldLimit")) {
|
||||
int value = Integer.valueOf(getValue(token));
|
||||
if ((value & fieldLimit) == fieldLimit) {
|
||||
int value = Integer.parseInt(getValue(token));
|
||||
if ((value & FIELD_LIMIT) == FIELD_LIMIT) {
|
||||
System.out.println(mapid + " " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void inspectMapEntry() {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void loadMapWz() throws IOException {
|
||||
System.out.println("Reading Map.wz ...");
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
listFiles(wzPath + "/Map.wz/Map", files);
|
||||
listFiles(WZFiles.MAP.getFilePath() + "/Map", files);
|
||||
|
||||
for(File f : files) {
|
||||
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
|
||||
for (File f : files) {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
mapid = getMapIdFromFilename(f.getName());
|
||||
inspectMapEntry();
|
||||
|
||||
@@ -184,7 +148,7 @@ public class MapleMapFieldLimitChecker {
|
||||
fileReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
loadMapWz();
|
||||
@@ -193,5 +157,4 @@ public class MapleMapFieldLimitChecker {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
157
src/main/java/tools/mapletools/MapInfoRetriever.java
Normal file
157
src/main/java/tools/mapletools/MapInfoRetriever.java
Normal file
@@ -0,0 +1,157 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* The main objective of this tool is to locate all mapids that doesn't have
|
||||
* the "info" node in their WZ node tree.
|
||||
*/
|
||||
public class MapInfoRetriever {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("map_info_report.txt");
|
||||
private static final List<Integer> missingInfo = new ArrayList<>();
|
||||
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static boolean hasInfo;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[50];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean translateToken(String token) {
|
||||
String d;
|
||||
int temp;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) {
|
||||
d = getName(token);
|
||||
if (d.contains("info")) {
|
||||
hasInfo = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
temp = status;
|
||||
forwardCursor(temp);
|
||||
}
|
||||
|
||||
status += 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void searchMapDirectory(int mapArea) {
|
||||
final File mapDirectory = new File(WZFiles.MAP.getFilePath() + "/Map/Map" + mapArea);
|
||||
try {
|
||||
Iterator<File> iter = FileUtils.iterateFiles(mapDirectory, new String[]{"xml"}, true);
|
||||
System.out.println("Parsing map area " + mapArea);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
File file = iter.next();
|
||||
searchMapFile(file);
|
||||
}
|
||||
} catch (UncheckedIOException e) {
|
||||
System.err.println("Directory " + mapDirectory.getPath() + " does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
private static void searchMapFile(File file) {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
hasInfo = false;
|
||||
status = 0;
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
if (translateToken(line)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasInfo) {
|
||||
missingInfo.add(Integer.valueOf(file.getName().split(".img.xml")[0]));
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + file.getName() + "'");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeReport() {
|
||||
try {
|
||||
PrintWriter printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
if (!missingInfo.isEmpty()) {
|
||||
for (Integer i : missingInfo) {
|
||||
printWriter.println(i);
|
||||
}
|
||||
} else {
|
||||
printWriter.println("All map files contain 'info' node.");
|
||||
}
|
||||
|
||||
printWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i <= 9; i++) {
|
||||
searchMapDirectory(i);
|
||||
}
|
||||
writeReport();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,210 +1,184 @@
|
||||
/*
|
||||
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 maplemesofetcher;
|
||||
|
||||
import life.MapleLifeFactory;
|
||||
import life.MapleMonsterStats;
|
||||
import server.life.MapleMonsterStats;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.Pair;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application traces missing meso drop data on the underlying DB (that must be
|
||||
* defined on the DatabaseConnection file of this project) and generates a
|
||||
* SQL file that proposes missing drop entries for the drop_data table.
|
||||
*
|
||||
* <p>
|
||||
* The meso range is calculated accordingly with the target mob stats, such as level
|
||||
* and if it's a boss or not, similarly as how it has been done for the actual meso
|
||||
* drops.
|
||||
*
|
||||
*/
|
||||
|
||||
public class MapleMesoFetcher {
|
||||
public class MesoFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("meso_drop_data.sql");
|
||||
private static final boolean PERMIT_MESOS_ON_DOJO_BOSSES = false;
|
||||
private static final int MESO_ID = 0;
|
||||
private static final int MIN_ITEMS = 4;
|
||||
private static final int CHANCE = 400000;
|
||||
|
||||
private static final Map<Integer, Pair<Integer, Integer>> mobRange = new HashMap<>();
|
||||
private static PrintWriter printWriter;
|
||||
private static String newFile = "lib/meso_drop_data.sql";
|
||||
|
||||
private static boolean permitMesosOnDojoBosses = false;
|
||||
|
||||
private static int minItems = 4;
|
||||
|
||||
private static int mesoid = 0;
|
||||
private static int chance = 400000;
|
||||
|
||||
private static Map<Integer, MapleMonsterStats> mobStats;
|
||||
private static Map<Integer, Pair<Integer, Integer>> mobRange = new HashMap<>();
|
||||
|
||||
|
||||
private static Pair<Integer, Integer> calcMesoRange90(int level, boolean boss) {
|
||||
int minRange, maxRange;
|
||||
|
||||
|
||||
// MIN range
|
||||
minRange = (int)(72.70814714 * Math.exp(0.02284640619 * level));
|
||||
|
||||
minRange = (int) (72.70814714 * Math.exp(0.02284640619 * level));
|
||||
|
||||
// MAX range
|
||||
maxRange = (int)(133.8194881 * Math.exp(0.02059225059 * level));
|
||||
|
||||
maxRange = (int) (133.8194881 * Math.exp(0.02059225059 * level));
|
||||
|
||||
// boss perks
|
||||
if(boss) {
|
||||
if (boss) {
|
||||
minRange *= 3;
|
||||
maxRange *= 10;
|
||||
}
|
||||
|
||||
|
||||
return new Pair<>(minRange, maxRange);
|
||||
}
|
||||
|
||||
|
||||
private static Pair<Integer, Integer> calcMesoRange(int level, boolean boss) {
|
||||
int minRange, maxRange;
|
||||
|
||||
|
||||
// MIN range
|
||||
minRange = (int)(30.32032228 * Math.exp(0.03281144930 * level));
|
||||
|
||||
minRange = (int) (30.32032228 * Math.exp(0.03281144930 * level));
|
||||
|
||||
// MAX range
|
||||
maxRange = (int)(44.45878459 * Math.exp(0.03289611686 * level));
|
||||
|
||||
maxRange = (int) (44.45878459 * Math.exp(0.03289611686 * level));
|
||||
|
||||
// boss perks
|
||||
if(boss) {
|
||||
if (boss) {
|
||||
minRange *= 3;
|
||||
maxRange *= 10;
|
||||
}
|
||||
|
||||
|
||||
return new Pair<>(minRange, maxRange);
|
||||
}
|
||||
|
||||
|
||||
private static void calcAllMobsMesoRange() {
|
||||
System.out.print("Calculating range... ");
|
||||
|
||||
for(Entry<Integer, MapleMonsterStats> mobStat : mobStats.entrySet()) {
|
||||
|
||||
for (Map.Entry<Integer, MapleMonsterStats> mobStat : mobStats.entrySet()) {
|
||||
MapleMonsterStats mms = mobStat.getValue();
|
||||
Pair<Integer, Integer> mesoRange;
|
||||
|
||||
if(mms.getLevel() < 90) {
|
||||
|
||||
if (mms.getLevel() < 90) {
|
||||
mesoRange = calcMesoRange(mms.getLevel(), mms.isBoss());
|
||||
} else {
|
||||
mesoRange = calcMesoRange90(mms.getLevel(), mms.isBoss());
|
||||
}
|
||||
|
||||
|
||||
mobRange.put(mobStat.getKey(), mesoRange);
|
||||
}
|
||||
|
||||
|
||||
System.out.println("done!");
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlHeader() {
|
||||
printWriter.println(" # SQL File autogenerated from the MapleMesoFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account mob stats such as level and boss for the meso ranges.");
|
||||
printWriter.println(" # Only mobs with " + minItems + " or more items with no meso entry on the DB it was compiled are presented here.");
|
||||
printWriter.println(" # Only mobs with " + MIN_ITEMS + " or more items with no meso entry on the DB it was compiled are presented here.");
|
||||
printWriter.println();
|
||||
|
||||
|
||||
printWriter.println(" INSERT IGNORE INTO drop_data (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`) VALUES");
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlExceptions() {
|
||||
if(!permitMesosOnDojoBosses) {
|
||||
printWriter.println("\r\n DELETE FROM drop_data WHERE dropperid >= 9300184 AND dropperid <= 9300215 AND itemid = " + mesoid + ";");
|
||||
if (!PERMIT_MESOS_ON_DOJO_BOSSES) {
|
||||
printWriter.println("\r\n DELETE FROM drop_data WHERE dropperid >= 9300184 AND dropperid <= 9300215 AND itemid = " + MESO_ID + ";");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlMobMesoRange(int mobid) {
|
||||
Pair<Integer, Integer> mobmeso = mobRange.get(mobid);
|
||||
printWriter.println("(" + mobid + ", " + mesoid + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + chance + "),");
|
||||
printWriter.println("(" + mobid + ", " + MESO_ID + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + CHANCE + "),");
|
||||
}
|
||||
|
||||
|
||||
private static void printSqlMobMesoRangeFinal(int mobid) {
|
||||
Pair<Integer, Integer> mobmeso = mobRange.get(mobid);
|
||||
printWriter.println("(" + mobid + ", " + mesoid + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + chance + ");");
|
||||
printWriter.println("(" + mobid + ", " + MESO_ID + ", " + mobmeso.left + ", " + mobmeso.right + ", 0, " + CHANCE + ");");
|
||||
}
|
||||
|
||||
|
||||
private static void generateMissingMobsMesoRange() {
|
||||
System.out.print("Generating missing ranges... ");
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
Connection con = SimpleDatabaseConnection.getConnection();
|
||||
List<Integer> existingMobs = new ArrayList<>(200);
|
||||
|
||||
|
||||
try {
|
||||
// select all mobs which doesn't drop mesos and have a fair amount of items dropping (meaning they are not an event mob)
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE dropperid NOT IN (SELECT DISTINCT dropperid FROM drop_data WHERE itemid = 0) GROUP BY dropperid HAVING count(*) >= " + minItems + ";");
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE dropperid NOT IN (SELECT DISTINCT dropperid FROM drop_data WHERE itemid = 0) GROUP BY dropperid HAVING count(*) >= " + MIN_ITEMS + ";");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
|
||||
if (rs.isBeforeFirst()) {
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
int mobid = rs.getInt(1);
|
||||
|
||||
if(mobRange.containsKey(mobid)) {
|
||||
|
||||
if (mobRange.containsKey(mobid)) {
|
||||
existingMobs.add(mobid);
|
||||
}
|
||||
}
|
||||
|
||||
if(!existingMobs.isEmpty()) {
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
if (!existingMobs.isEmpty()) {
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
printSqlHeader();
|
||||
|
||||
for(int i = 0; i < existingMobs.size() - 1; i++)
|
||||
|
||||
for (int i = 0; i < existingMobs.size() - 1; i++) {
|
||||
printSqlMobMesoRange(existingMobs.get(i));
|
||||
|
||||
}
|
||||
|
||||
printSqlMobMesoRangeFinal(existingMobs.get(existingMobs.size() - 1));
|
||||
|
||||
|
||||
printSqlExceptions();
|
||||
|
||||
|
||||
printWriter.close();
|
||||
} else {
|
||||
throw new Exception("ALREADY UPDATED");
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
throw new Exception("ALREADY UPDATED");
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
|
||||
|
||||
System.out.println("done!");
|
||||
|
||||
} catch(Exception e) {
|
||||
if(e.getMessage() != null && e.getMessage().equals("ALREADY UPDATED")) {
|
||||
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage() != null && e.getMessage().equals("ALREADY UPDATED")) {
|
||||
System.out.println("done! The DB is already up-to-date, no file generated.");
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// load mob stats from WZ
|
||||
mobStats = MapleLifeFactory.getAllMonsterStats();
|
||||
|
||||
mobStats = MonsterStatFetcher.getAllMonsterStats();
|
||||
|
||||
calcAllMobsMesoRange();
|
||||
generateMissingMobsMesoRange();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
169
src/main/java/tools/mapletools/MobBookIndexer.java
Normal file
169
src/main/java/tools/mapletools/MobBookIndexer.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application simply gets from the MonsterBook.img.xml all mobid's and
|
||||
* puts them on a SQL table with the correspondent mob cardid.
|
||||
*/
|
||||
public class MobBookIndexer {
|
||||
private static final File INPUT_FILE = new File(WZFiles.STRING.getFile(), "MonsterBook.img.xml");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int mobId = -1;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
if (j - i < 7) {
|
||||
dest = new char[6];
|
||||
} else {
|
||||
dest = new char[7];
|
||||
}
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d);
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCard(int itemId) {
|
||||
return itemId / 10000 == 238;
|
||||
}
|
||||
|
||||
private static void loadPairFromMob() {
|
||||
System.out.println("Loading mob id " + mobId);
|
||||
|
||||
try {
|
||||
PreparedStatement ps, ps2;
|
||||
ResultSet rs;
|
||||
|
||||
ps = con.prepareStatement("SELECT itemid FROM drop_data WHERE (dropperid = ? AND itemid > 0) GROUP BY itemid;");
|
||||
ps.setInt(1, mobId);
|
||||
rs = ps.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
int itemId = rs.getInt("itemid");
|
||||
if (isCard(itemId)) {
|
||||
ps2 = con.prepareStatement("INSERT INTO `monstercardwz` (`cardid`, `mobid`) VALUES (?, ?)");
|
||||
ps2.setInt(1, itemId);
|
||||
ps2.setInt(2, mobId);
|
||||
|
||||
ps2.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
int temp;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting MobId
|
||||
d = getName(token);
|
||||
mobId = Integer.parseInt(d);
|
||||
} else if (status == 2) {
|
||||
d = getName(token);
|
||||
|
||||
if (d.contains("reward")) {
|
||||
temp = status;
|
||||
|
||||
loadPairFromMob();
|
||||
forwardCursor(temp);
|
||||
}
|
||||
}
|
||||
|
||||
status += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void indexFromDropData() {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("DROP TABLE IF EXISTS monstercardwz;");
|
||||
ps.execute();
|
||||
|
||||
ps = con.prepareStatement("CREATE TABLE `monstercardwz` ("
|
||||
+ "`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
|
||||
+ "`cardid` int(10) NOT NULL DEFAULT '-1',"
|
||||
+ "`mobid` int(10) NOT NULL DEFAULT '-1',"
|
||||
+ "PRIMARY KEY (`id`)"
|
||||
+ ");");
|
||||
ps.execute();
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
con.close();
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + INPUT_FILE + "'");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + INPUT_FILE + "'");
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Warning: Could not establish connection to database to change card chance rate.");
|
||||
System.out.println(e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
indexFromDropData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +1,39 @@
|
||||
/*
|
||||
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 maplemobbookupdate;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application updates the Monster Book drop data with the actual underlying drop data from
|
||||
* the Maplestory database specified in the URL below.
|
||||
*
|
||||
* <p>
|
||||
* In other words all items drops from monsters listed inside the Mob Book feature will be patched to match exactly like the item
|
||||
* drop list specified in the URL's Maplestory database.
|
||||
*
|
||||
* <p>
|
||||
* The original file "MonsterBook.img.xml" from String.wz must be copied to the directory of this application and only then
|
||||
* executed. This program will generate another file that must replace the original server file to make the effects take place
|
||||
* to on your server.
|
||||
*
|
||||
* <p>
|
||||
* After replacing on server, this XML must be updated on the client via WZ Editor (HaRepack for instance). Once inside the repack,
|
||||
* remove the property 'MonsterBook.img' inside 'string.wz' and choose to import the xml generated with this software.
|
||||
*
|
||||
*/
|
||||
public class MapleMobBookUpdate {
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
public class MobBookUpdate {
|
||||
private static final File INPUT_FILE = new File(WZFiles.STRING.getFile(), "MonsterBook.img.xml");
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("MonsterBook_updated.img.xml");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
static String fileName = "lib/MonsterBook.img.xml";
|
||||
static String newFile = "lib/MonsterBook_updated.img.xml";
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
static byte status = 0;
|
||||
static int mobId = -1;
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int mobId = -1;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
@@ -70,33 +44,36 @@ public class MapleMobBookUpdate {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
if(j - i < 7) dest = new char[6];
|
||||
else dest = new char[7];
|
||||
if (j - i < 7) {
|
||||
dest = new char[6];
|
||||
} else {
|
||||
dest = new char[7];
|
||||
}
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d);
|
||||
return (d);
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
if(line != null) printWriter.println(line);
|
||||
}
|
||||
catch(Exception e) {
|
||||
if (line != null) {
|
||||
printWriter.println(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
@@ -112,9 +89,11 @@ public class MapleMobBookUpdate {
|
||||
ps.setInt(1, mobId);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
toPrint = "";
|
||||
for(int k = 0; k <= status; k++) toPrint += " ";
|
||||
for (int k = 0; k <= status; k++) {
|
||||
toPrint += " ";
|
||||
}
|
||||
|
||||
toPrint += "<int name=\"";
|
||||
toPrint += cont;
|
||||
@@ -127,11 +106,10 @@ public class MapleMobBookUpdate {
|
||||
printWriter.println(toPrint);
|
||||
cont++;
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -142,18 +120,16 @@ public class MapleMobBookUpdate {
|
||||
|
||||
printWriter.println(token);
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting MobId
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting MobId
|
||||
d = getName(token);
|
||||
mobId = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 2) {
|
||||
} else if (status == 2) {
|
||||
d = getName(token);
|
||||
|
||||
if(d.contains("reward")) {
|
||||
if (d.contains("reward")) {
|
||||
temp = status;
|
||||
|
||||
loadDropsFromMob();
|
||||
@@ -166,19 +142,16 @@ public class MapleMobBookUpdate {
|
||||
|
||||
}
|
||||
|
||||
private static void UpdateFromDropData() {
|
||||
private static void updateFromDropData() {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
Class.forName(driver).newInstance();
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
@@ -187,37 +160,20 @@ public class MapleMobBookUpdate {
|
||||
fileReader.close();
|
||||
|
||||
con.close();
|
||||
}
|
||||
|
||||
catch(FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + fileName + "'");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
System.out.println("Error reading file '" + fileName + "'");
|
||||
}
|
||||
|
||||
catch(SQLException e) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + INPUT_FILE + "'");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + INPUT_FILE + "'");
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Warning: Could not establish connection to database to change card chance rate.");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(ClassNotFoundException e) {
|
||||
System.out.println("Error: could not find class");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(InstantiationException e) {
|
||||
System.out.println("Error: instantiation failure");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
UpdateFromDropData();
|
||||
updateFromDropData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,69 +1,40 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
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 life;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataDirectoryEntry;
|
||||
import provider.MapleDataFileEntry;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.*;
|
||||
import provider.wz.MapleDataType;
|
||||
import provider.wz.WZFiles;
|
||||
import server.life.Element;
|
||||
import server.life.ElementalEffectiveness;
|
||||
import server.life.MapleLifeFactory.BanishInfo;
|
||||
import server.life.MapleLifeFactory.loseItem;
|
||||
import server.life.MapleLifeFactory.selfDestruction;
|
||||
import server.life.MapleMonsterStats;
|
||||
import tools.Pair;
|
||||
|
||||
public class MapleLifeFactory {
|
||||
private static String wzPath = "../../wz";
|
||||
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/Mob.wz"));
|
||||
private final static MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/String.wz"));
|
||||
private static MapleData mobStringData = stringDataWZ.getData("Mob.img");
|
||||
private static MapleData npcStringData = stringDataWZ.getData("Npc.img");
|
||||
private static Map<Integer, MapleMonsterStats> monsterStats = new HashMap<>();
|
||||
import java.util.*;
|
||||
|
||||
private static int getMonsterId(String fileName) {
|
||||
return Integer.parseInt(fileName.substring(0, 7));
|
||||
}
|
||||
|
||||
public static Map<Integer, MapleMonsterStats> getAllMonsterStats() {
|
||||
public class MonsterStatFetcher {
|
||||
private static final MapleDataProvider data = MapleDataProviderFactory.getDataProvider(WZFiles.MOB);
|
||||
private static final MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(WZFiles.STRING);
|
||||
private static final MapleData mobStringData = stringDataWZ.getData("Mob.img");
|
||||
private static final Map<Integer, MapleMonsterStats> monsterStats = new HashMap<>();
|
||||
|
||||
static Map<Integer, MapleMonsterStats> getAllMonsterStats() {
|
||||
MapleDataDirectoryEntry root = data.getRoot();
|
||||
|
||||
|
||||
System.out.print("Parsing mob stats... ");
|
||||
for (MapleDataFileEntry mFile : root.getFiles()) {
|
||||
try {
|
||||
String fileName = mFile.getName();
|
||||
|
||||
|
||||
//System.out.println("Parsing '" + fileName + "'");
|
||||
MapleData monsterData = data.getData(fileName);
|
||||
if (monsterData == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Integer mid = getMonsterId(fileName);
|
||||
|
||||
|
||||
MapleData monsterInfoData = monsterData.getChildByPath("info");
|
||||
MapleMonsterStats stats = new MapleMonsterStats();
|
||||
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
|
||||
@@ -71,7 +42,7 @@ public class MapleLifeFactory {
|
||||
stats.setPADamage(MapleDataTool.getIntConvert("PADamage", monsterInfoData));
|
||||
stats.setPDDamage(MapleDataTool.getIntConvert("PDDamage", monsterInfoData));
|
||||
stats.setMADamage(MapleDataTool.getIntConvert("MADamage", monsterInfoData));
|
||||
stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
|
||||
stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
|
||||
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
|
||||
stats.setExp(MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
|
||||
stats.setLevel(MapleDataTool.getIntConvert("level", monsterInfoData));
|
||||
@@ -139,7 +110,7 @@ public class MapleLifeFactory {
|
||||
int i = 0;
|
||||
List<Pair<Integer, Integer>> skills = new ArrayList<>();
|
||||
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
|
||||
skills.add(new Pair<>(Integer.valueOf(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0)), Integer.valueOf(MapleDataTool.getInt(i + "/level", monsterSkillData, 0))));
|
||||
skills.add(new Pair<>(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0), MapleDataTool.getInt(i + "/level", monsterSkillData, 0)));
|
||||
i++;
|
||||
}
|
||||
stats.setSkills(skills);
|
||||
@@ -148,93 +119,25 @@ public class MapleLifeFactory {
|
||||
if (banishData != null) {
|
||||
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
|
||||
}
|
||||
|
||||
|
||||
monsterStats.put(mid, stats);
|
||||
} catch(NullPointerException npe) {
|
||||
//System.out.println("[SEVERE] " + mFile.getName() + " failed to load. Issue: " + npe.getMessage() + "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("done!");
|
||||
|
||||
System.out.println("Done parsing mob stats!");
|
||||
return monsterStats;
|
||||
}
|
||||
|
||||
private static int getMonsterId(String fileName) {
|
||||
return Integer.parseInt(fileName.substring(0, 7));
|
||||
}
|
||||
|
||||
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
|
||||
for (int i = 0; i < elemAttr.length(); i += 2) {
|
||||
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
|
||||
}
|
||||
}
|
||||
|
||||
public static class BanishInfo {
|
||||
|
||||
private int map;
|
||||
private String portal, msg;
|
||||
|
||||
public BanishInfo(String msg, int map, String portal) {
|
||||
this.msg = msg;
|
||||
this.map = map;
|
||||
this.portal = portal;
|
||||
}
|
||||
|
||||
public int getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getPortal() {
|
||||
return portal;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
public static class loseItem {
|
||||
|
||||
private int id;
|
||||
private byte chance, x;
|
||||
|
||||
private loseItem(int id, byte chance, byte x) {
|
||||
this.id = id;
|
||||
this.chance = chance;
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte getChance() {
|
||||
return chance;
|
||||
}
|
||||
|
||||
public byte getX() {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
public static class selfDestruction {
|
||||
|
||||
private byte action;
|
||||
private int removeAfter;
|
||||
private int hp;
|
||||
|
||||
private selfDestruction(byte action, int removeAfter, int hp) {
|
||||
this.action = action;
|
||||
this.removeAfter = removeAfter;
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
public int getHp() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
public byte getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public int removeAfter() {
|
||||
return removeAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,35 @@
|
||||
/*
|
||||
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.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 maplenoitemidfetcher;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application finds inexistent itemids within the drop data from
|
||||
* the Maplestory database specified in the URL below. This program
|
||||
* assumes all itemids uses 7 digits.
|
||||
*
|
||||
* <p>
|
||||
* A file is generated listing all the inexistent ids.
|
||||
*/
|
||||
public class MapleNoItemIdFetcher {
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
public class NoItemIdFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("no_item_id_report.txt");
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
static String wzPath = "../../wz";
|
||||
static String newFile = "lib/result.txt";
|
||||
private static final Set<Integer> existingIds = new HashSet<>();
|
||||
private static final Set<Integer> nonExistingIds = new HashSet<>();
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
static byte status = 0;
|
||||
static int itemId = -1;
|
||||
|
||||
static Set<Integer> existingIds = new HashSet<>();
|
||||
static Set<Integer> nonExistingIds = new HashSet<>();
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int itemId = -1;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
@@ -79,42 +44,39 @@ public class MapleNoItemIdFetcher {
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d);
|
||||
return (d);
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting ItemId
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting ItemId
|
||||
d = getName(token);
|
||||
itemId = Integer.parseInt(d.substring(1, 8));
|
||||
|
||||
|
||||
existingIds.add(itemId);
|
||||
forwardCursor(status);
|
||||
}
|
||||
@@ -127,36 +89,34 @@ public class MapleNoItemIdFetcher {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
|
||||
try {
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
status = 0;
|
||||
try {
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
} catch(NumberFormatException npe) {
|
||||
} catch (NumberFormatException npe) {
|
||||
// second criteria, itemid is on the name of the file
|
||||
|
||||
|
||||
try {
|
||||
itemId = Integer.parseInt(file.getName().substring(0, 7));
|
||||
existingIds.add(itemId);
|
||||
} catch(NumberFormatException npe2) {}
|
||||
} catch (NumberFormatException npe2) {
|
||||
}
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
catch(FileNotFoundException ex) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + file.getName() + "'");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + file.getName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readEquipDataDirectory(String dirPath) {
|
||||
File[] folders = new File(dirPath).listFiles();
|
||||
//If this pathname does not denote a directory, then listFiles() returns null.
|
||||
@@ -164,21 +124,22 @@ public class MapleNoItemIdFetcher {
|
||||
for (File folder : folders) { // enter all subfolders
|
||||
if (folder.isDirectory()) {
|
||||
System.out.println("Reading '" + dirPath + "/" + folder.getName() + "'...");
|
||||
|
||||
|
||||
try {
|
||||
File[] files = folder.listFiles();
|
||||
|
||||
|
||||
for (File file : files) { // enter all XML files under subfolders
|
||||
if (file.isFile()) {
|
||||
itemId = Integer.parseInt(file.getName().substring(0, 8));
|
||||
existingIds.add(itemId);
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException nfe) {}
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readItemDataDirectory(String dirPath) {
|
||||
File[] folders = new File(dirPath).listFiles();
|
||||
//If this pathname does not denote a directory, then listFiles() returns null.
|
||||
@@ -186,9 +147,9 @@ public class MapleNoItemIdFetcher {
|
||||
for (File folder : folders) { // enter all subfolders
|
||||
if (folder.isDirectory()) {
|
||||
System.out.println("Reading '" + dirPath + "/" + folder.getName() + "'...");
|
||||
|
||||
|
||||
File[] files = folder.listFiles();
|
||||
|
||||
|
||||
for (File file : files) { // enter all XML files under subfolders
|
||||
if (file.isFile()) {
|
||||
readItemDataFile(file);
|
||||
@@ -197,13 +158,13 @@ public class MapleNoItemIdFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void evaluateDropsFromTable(String table) throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT DISTINCT itemid FROM " + table + ";");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while(rs.next()) {
|
||||
if(!existingIds.contains(rs.getInt(1))) {
|
||||
while (rs.next()) {
|
||||
if (!existingIds.contains(rs.getInt(1))) {
|
||||
nonExistingIds.add(rs.getInt(1));
|
||||
}
|
||||
}
|
||||
@@ -211,64 +172,45 @@ public class MapleNoItemIdFetcher {
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
|
||||
private static void evaluateDropsFromDb() {
|
||||
try {
|
||||
System.out.println("Evaluating item data on DB...");
|
||||
|
||||
Class.forName(driver).newInstance();
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
|
||||
evaluateDropsFromTable("drop_data");
|
||||
evaluateDropsFromTable("reactordrops");
|
||||
|
||||
if(!nonExistingIds.isEmpty()) {
|
||||
|
||||
if (!nonExistingIds.isEmpty()) {
|
||||
List<Integer> list = new ArrayList<>(nonExistingIds);
|
||||
Collections.sort(list);
|
||||
|
||||
for(Integer i : list) {
|
||||
|
||||
for (Integer i : list) {
|
||||
printWriter.println(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
System.out.println("Inexistent itemid count: " + nonExistingIds.size());
|
||||
System.out.println("Total itemid count: " + existingIds.size());
|
||||
|
||||
con.close();
|
||||
}
|
||||
|
||||
catch(ClassNotFoundException e) {
|
||||
System.out.println("Error: could not find class");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(InstantiationException e) {
|
||||
System.out.println("Error: instantiation failure");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
con.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
existingIds.add(0); // meso itemid
|
||||
readEquipDataDirectory(wzPath + "/Character.wz");
|
||||
readItemDataDirectory(wzPath + "/Item.wz");
|
||||
|
||||
readEquipDataDirectory(WZFiles.CHARACTER.getFilePath());
|
||||
readItemDataDirectory(WZFiles.ITEM.getFilePath());
|
||||
|
||||
evaluateDropsFromDb();
|
||||
|
||||
|
||||
printWriter.close();
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +1,51 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
package tools.mapletools;
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
import provider.*;
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 maplenoitemnamefetcher;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataDirectoryEntry;
|
||||
import provider.MapleDataFileEntry;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
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 MapleNoItemNameFetcher {
|
||||
static String wzPath = "../../wz";
|
||||
static String newFile = "lib/result.txt";
|
||||
static String xmlFile = "lib/output.txt";
|
||||
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");
|
||||
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static Map<Integer, String> itemsWzPath = new HashMap<>();
|
||||
static Map<Integer, ItemType> itemTypes = new HashMap<>();
|
||||
static Map<Integer, EquipType> equipTypes = new HashMap<>();
|
||||
|
||||
static Map<Integer, ItemType> itemsWithNoNameProperty = new HashMap<>();
|
||||
static Set<Integer> equipsWithNoCashProperty = new HashSet<>();
|
||||
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;
|
||||
|
||||
static Map<Integer, String> nameContentCache = new HashMap<>();
|
||||
static Map<Integer, String> descContentCache = new HashMap<>();
|
||||
|
||||
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()) {
|
||||
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);
|
||||
@@ -93,7 +55,7 @@ public class MapleNoItemNameFetcher {
|
||||
} 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) {
|
||||
@@ -101,9 +63,9 @@ public class MapleNoItemNameFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readStringSubdirectoryData(MapleData subdirData, int depth, String subdirPath) {
|
||||
if(depth > 0) {
|
||||
if (depth > 0) {
|
||||
for (MapleData mDir : subdirData.getChildren()) {
|
||||
readStringSubdirectoryData(mDir, depth - 1, subdirPath + mDir.getName() + "/");
|
||||
}
|
||||
@@ -111,230 +73,162 @@ public class MapleNoItemNameFetcher {
|
||||
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(new File(System.getProperty("wzpath") + "/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) {
|
||||
switch(dirName) {
|
||||
case "Cash":
|
||||
return ItemType.CASH;
|
||||
|
||||
case "Consume":
|
||||
return ItemType.CONSUME;
|
||||
|
||||
case "Etc":
|
||||
return ItemType.ETC;
|
||||
|
||||
case "Install":
|
||||
return ItemType.INS;
|
||||
|
||||
case "Pet":
|
||||
return ItemType.PET;
|
||||
|
||||
default:
|
||||
return ItemType.UNDEF;
|
||||
}
|
||||
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) {
|
||||
switch(dirName) {
|
||||
case "Accessory":
|
||||
return EquipType.ACCESSORY;
|
||||
|
||||
case "Cap":
|
||||
return EquipType.CAP;
|
||||
|
||||
case "Cape":
|
||||
return EquipType.CAPE;
|
||||
|
||||
case "Coat":
|
||||
return EquipType.COAT;
|
||||
|
||||
case "Face":
|
||||
return EquipType.FACE;
|
||||
|
||||
case "Glove":
|
||||
return EquipType.GLOVE;
|
||||
|
||||
case "Hair":
|
||||
return EquipType.HAIR;
|
||||
|
||||
case "Longcoat":
|
||||
return EquipType.LONGCOAT;
|
||||
|
||||
case "Pants":
|
||||
return EquipType.PANTS;
|
||||
|
||||
case "PetEquip":
|
||||
return EquipType.PETEQUIP;
|
||||
|
||||
case "Ring":
|
||||
return EquipType.RING;
|
||||
|
||||
case "Shield":
|
||||
return EquipType.SHIELD;
|
||||
|
||||
case "Shoes":
|
||||
return EquipType.SHOES;
|
||||
|
||||
case "TamingMob":
|
||||
return EquipType.TAMING;
|
||||
|
||||
case "Weapon":
|
||||
return EquipType.WEAPON;
|
||||
|
||||
default:
|
||||
return EquipType.UNDEF;
|
||||
}
|
||||
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) {
|
||||
switch(eType) {
|
||||
case ACCESSORY:
|
||||
return "Accessory";
|
||||
|
||||
case CAP:
|
||||
return "Cap";
|
||||
|
||||
case CAPE:
|
||||
return "Cape";
|
||||
|
||||
case COAT:
|
||||
return "Coat";
|
||||
|
||||
case FACE:
|
||||
return "Face";
|
||||
|
||||
case GLOVE:
|
||||
return "Glove";
|
||||
|
||||
case HAIR:
|
||||
return "Hair";
|
||||
|
||||
case LONGCOAT:
|
||||
return "Longcoat";
|
||||
|
||||
case PANTS:
|
||||
return "Pants";
|
||||
|
||||
case PETEQUIP:
|
||||
return "PetEquip";
|
||||
|
||||
case RING:
|
||||
return "Ring";
|
||||
|
||||
case SHIELD:
|
||||
return "Shield";
|
||||
|
||||
case SHOES:
|
||||
return "Shoes";
|
||||
|
||||
case TAMING:
|
||||
return "Taming";
|
||||
|
||||
case WEAPON:
|
||||
return "Weapon";
|
||||
|
||||
default:
|
||||
return "Undefined";
|
||||
}
|
||||
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()) {
|
||||
|
||||
for (MapleDataFileEntry mFile : mDir.getFiles()) {
|
||||
String fileName = mFile.getName();
|
||||
|
||||
try {
|
||||
int itemId = Integer.parseInt(fileName.substring(0, 8));
|
||||
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)) {
|
||||
if (!isAccessory(itemId) && !isTamingMob(itemId)) {
|
||||
try {
|
||||
MapleData fileData = data.getData(dirName + "/" + fileName);
|
||||
MapleData mdinfo = fileData.getChildByPath("info");
|
||||
if( mdinfo.getChildByPath("cash") == null) {
|
||||
if (mdinfo.getChildByPath("cash") == null) {
|
||||
equipsWithNoCashProperty.add(itemId);
|
||||
}
|
||||
} catch(NullPointerException npe) {
|
||||
} catch (NullPointerException npe) {
|
||||
System.out.println("[SEVERE] " + mFile.getName() + " failed to load. Issue: " + npe.getMessage() + "\n\n");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readEquipWZData() {
|
||||
String wzFileName = "Character.wz";
|
||||
|
||||
MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/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;
|
||||
|
||||
if (dirName.contentEquals("Dragon")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
readEquipNodeData(data, mDir, wzFileName, dirName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readItemWZData() {
|
||||
String wzFileName = "Item.wz";
|
||||
|
||||
MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/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;
|
||||
|
||||
if (dirName.contentEquals("Special")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
curType = getItemTypeFromDirectoryName(dirName);
|
||||
if(!dirName.contentEquals("Pet")) {
|
||||
for(MapleDataFileEntry mFile : mDir.getFiles()) {
|
||||
if (!dirName.contentEquals("Pet")) {
|
||||
for (MapleDataFileEntry mFile : mDir.getFiles()) {
|
||||
String fileName = mFile.getName();
|
||||
|
||||
MapleData fileData = data.getData(dirName + "/" + fileName);
|
||||
for(MapleData mData : fileData.getChildren()) {
|
||||
for (MapleData mData : fileData.getChildren()) {
|
||||
try {
|
||||
int itemId = Integer.parseInt(mData.getName());
|
||||
itemsWithNoNameProperty.put(itemId, curType);
|
||||
@@ -349,38 +243,38 @@ public class MapleNoItemNameFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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()) {
|
||||
if (!itemsWithNoNameProperty.isEmpty()) {
|
||||
printWriter.println("Itemids with missing 'name' property: ");
|
||||
|
||||
|
||||
List<Integer> itemids = new ArrayList<>(itemsWithNoNameProperty.keySet());
|
||||
Collections.sort(itemids);
|
||||
|
||||
for(Integer itemid : itemids) {
|
||||
|
||||
for (Integer itemid : itemids) {
|
||||
printWriter.println(" " + itemid + " " + itemsWzPath.get(itemid));
|
||||
}
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
if(!equipsWithNoCashProperty.isEmpty()) {
|
||||
|
||||
if (!equipsWithNoCashProperty.isEmpty()) {
|
||||
printWriter.println("Equipids with missing 'cash' property: ");
|
||||
|
||||
|
||||
List<Integer> itemids = new ArrayList<>(equipsWithNoCashProperty);
|
||||
Collections.sort(itemids);
|
||||
|
||||
for(Integer itemid : 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);
|
||||
@@ -388,35 +282,18 @@ public class MapleNoItemNameFetcher {
|
||||
List<Integer> etcList = new ArrayList<>(20);
|
||||
List<Integer> insList = new ArrayList<>(20);
|
||||
List<Integer> petList = new ArrayList<>(20);
|
||||
|
||||
for(Entry<Integer, ItemType> ids : itemsWithNoNameProperty.entrySet()) {
|
||||
switch(ids.getValue()) {
|
||||
case CASH:
|
||||
cashList.add(ids.getKey());
|
||||
break;
|
||||
|
||||
case CONSUME:
|
||||
consList.add(ids.getKey());
|
||||
break;
|
||||
|
||||
case EQP:
|
||||
eqpList.add(ids.getKey());
|
||||
break;
|
||||
|
||||
case ETC:
|
||||
etcList.add(ids.getKey());
|
||||
break;
|
||||
|
||||
case INS:
|
||||
insList.add(ids.getKey());
|
||||
break;
|
||||
|
||||
case PET:
|
||||
petList.add(ids.getKey());
|
||||
break;
|
||||
|
||||
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);
|
||||
@@ -424,94 +301,94 @@ public class MapleNoItemNameFetcher {
|
||||
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()) {
|
||||
if (!missingNames.isEmpty()) {
|
||||
Collections.sort(missingNames);
|
||||
writeEquipSubdirectoryHeader(eType);
|
||||
|
||||
for(Integer equipid : missingNames) {
|
||||
|
||||
for (Integer equipid : missingNames) {
|
||||
writeMissingEquipInfo(equipid);
|
||||
}
|
||||
|
||||
|
||||
writeEquipSubdirectoryFooter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void writeMissingStringWZNode(String nodePath, List<Integer> missingNames, boolean isEquip) {
|
||||
if(!missingNames.isEmpty()) {
|
||||
if(!isEquip) {
|
||||
if (!missingNames.isEmpty()) {
|
||||
if (!isEquip) {
|
||||
Collections.sort(missingNames);
|
||||
|
||||
printWriter.println(nodePath + ":");
|
||||
@@ -519,7 +396,7 @@ public class MapleNoItemNameFetcher {
|
||||
|
||||
writeXMLHeader(nodePath);
|
||||
|
||||
for(Integer i : missingNames) {
|
||||
for (Integer i : missingNames) {
|
||||
writeMissingItemInfo(i);
|
||||
}
|
||||
|
||||
@@ -528,23 +405,23 @@ public class MapleNoItemNameFetcher {
|
||||
printWriter.println();
|
||||
} else {
|
||||
int arraySize = EquipType.values().length;
|
||||
|
||||
List<Integer> equips[] = new List[arraySize];
|
||||
for(int i = 0; i < arraySize; i++) {
|
||||
|
||||
List<Integer>[] equips = new List[arraySize];
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
equips[i] = new ArrayList<>(42);
|
||||
}
|
||||
|
||||
for(Integer itemid : missingNames) {
|
||||
|
||||
for (Integer itemid : missingNames) {
|
||||
equips[equipTypes.get(itemid).ordinal()].add(itemid);
|
||||
}
|
||||
|
||||
|
||||
printWriter.println(nodePath + ":");
|
||||
printWriter.println();
|
||||
|
||||
writeXMLHeader(nodePath);
|
||||
writeEquipXMLHeader();
|
||||
|
||||
for(EquipType eType : EquipType.values()) {
|
||||
for (EquipType eType : EquipType.values()) {
|
||||
writeMissingEquipWZNode(eType, equips[eType.ordinal()]);
|
||||
}
|
||||
|
||||
@@ -555,43 +432,41 @@ public class MapleNoItemNameFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void writeMissingStringWZNames(Map<String, List<Integer>> missingNames) throws Exception {
|
||||
System.out.println("Writing remaining 'String.wz' names...");
|
||||
|
||||
printWriter = new PrintWriter(xmlFile, "UTF-8");
|
||||
|
||||
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++) {
|
||||
|
||||
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 {
|
||||
System.setProperty("wzpath", wzPath);
|
||||
|
||||
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(newFile, "UTF-8");
|
||||
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) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
268
src/main/java/tools/mapletools/QuestItemCountFetcher.java
Normal file
268
src/main/java/tools/mapletools/QuestItemCountFetcher.java
Normal file
@@ -0,0 +1,268 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.wz.WZFiles;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application parses the Quest.wz file inputted and generates a report showing
|
||||
* all cases where a quest requires an item, but doesn't take them, which may happen
|
||||
* because the node representing the item doesn't have a "count" clause.
|
||||
* <p>
|
||||
* Running it should generate a report file under "output" folder with the search results.
|
||||
*/
|
||||
public class QuestItemCountFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("quest_item_count_report.txt");
|
||||
private static final String ACT_NAME = WZFiles.QUEST.getFilePath() + "/Act.img.xml";
|
||||
private static final String CHECK_NAME = WZFiles.QUEST.getFilePath() + "/Check.img.xml";
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
|
||||
private static final Map<Integer, Map<Integer, Integer>> checkItems = new HashMap<>();
|
||||
private static final Map<Integer, Map<Integer, Integer>> actItems = new HashMap<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int questId = -1;
|
||||
private static int isCompleteState = 0;
|
||||
private static int curItemId;
|
||||
private static int curItemCount;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("value");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void readItemLabel(String token) {
|
||||
String name = getName(token);
|
||||
String value = getValue(token);
|
||||
|
||||
switch (name) {
|
||||
case "id" -> curItemId = Integer.parseInt(value);
|
||||
case "count" -> curItemCount = Integer.parseInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void commitQuestItemPair(Map<Integer, Map<Integer, Integer>> map) {
|
||||
Map<Integer, Integer> list = map.get(questId);
|
||||
if (list == null) {
|
||||
list = new LinkedHashMap<>();
|
||||
map.put(questId, list);
|
||||
}
|
||||
|
||||
list.put(curItemId, curItemCount);
|
||||
}
|
||||
|
||||
private static void translateTokenAct(String token) {
|
||||
String d;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
if (status == 4) {
|
||||
if (curItemCount == Integer.MAX_VALUE && isCompleteState == 1) {
|
||||
commitQuestItemPair(actItems);
|
||||
}
|
||||
}
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
} else if (status == 3) {
|
||||
if (!token.contains("item")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
} else if (status == 4) {
|
||||
curItemId = Integer.MAX_VALUE;
|
||||
curItemCount = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if (status == 5) {
|
||||
readItemLabel(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateTokenCheck(String token) {
|
||||
String d;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
if (status == 4) {
|
||||
Map<Integer, Integer> missedItems = actItems.get(questId);
|
||||
|
||||
if (missedItems != null && missedItems.containsKey(curItemId) && isCompleteState == 1) {
|
||||
commitQuestItemPair(checkItems);
|
||||
}
|
||||
}
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
} else if (status == 3) {
|
||||
if (!token.contains("item")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
} else if (status == 4) {
|
||||
curItemId = Integer.MAX_VALUE;
|
||||
curItemCount = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if (status == 5) {
|
||||
readItemLabel(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void readQuestItemCountData() throws IOException {
|
||||
String line;
|
||||
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(ACT_NAME), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateTokenAct(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(CHECK_NAME), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateTokenCheck(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleQuestItemCountFetcher 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() {
|
||||
List<Pair<Integer, Pair<Integer, Integer>>> reports = new ArrayList<>();
|
||||
List<Pair<Integer, Integer>> notChecked = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<Integer, Map<Integer, Integer>> actItem : actItems.entrySet()) {
|
||||
int questid = actItem.getKey();
|
||||
|
||||
for (Map.Entry<Integer, Integer> actData : actItem.getValue().entrySet()) {
|
||||
int itemid = actData.getKey();
|
||||
|
||||
Map<Integer, Integer> checkData = checkItems.get(questid);
|
||||
if (checkData != null) {
|
||||
Integer count = checkData.get(itemid);
|
||||
if (count != null) {
|
||||
reports.add(new Pair<>(questid, new Pair<>(itemid, -count)));
|
||||
}
|
||||
} else {
|
||||
notChecked.add(new Pair<>(questid, itemid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Pair<Integer, Pair<Integer, Integer>> r : reports) {
|
||||
printWriter.println("Questid " + r.left + " : Itemid " + r.right.left + " should have qty " + r.right.right);
|
||||
}
|
||||
|
||||
for (Pair<Integer, Integer> r : notChecked) {
|
||||
printWriter.println("Questid " + r.left + " : Itemid " + r.right + " is unchecked");
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportQuestItemCountData() {
|
||||
// This will reference one line at a time
|
||||
|
||||
try {
|
||||
System.out.println("Reading WZs...");
|
||||
readQuestItemCountData();
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
printReportFileResults();
|
||||
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open quest file.");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading quest file.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
reportQuestItemCountData();
|
||||
}
|
||||
}
|
||||
@@ -1,102 +1,72 @@
|
||||
/*
|
||||
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
|
||||
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 maplequestitemfetcher;
|
||||
package tools.mapletools;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import tools.MapleItemInformationProvider;
|
||||
import provider.wz.WZFiles;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application haves 2 objectives: fetch missing drop data relevant to quests,
|
||||
* and update the questid from items that are labeled as "Quest Item" on the DB.
|
||||
*
|
||||
* To test a server instance with this feature, MapleQuestItemFetcher must be set
|
||||
* just like it is displayed on the HeavenMS source: 2 folders ahead
|
||||
* of the root of the main source.
|
||||
*
|
||||
* Running it should generate a report file under "lib" folder with the search results.
|
||||
*
|
||||
* <p>
|
||||
* Running it should generate a report file under "output" folder with the search results.
|
||||
* <p>
|
||||
* Estimated parse time: 1 minute
|
||||
*/
|
||||
public class MapleQuestItemFetcher {
|
||||
static MapleItemInformationProvider ii;
|
||||
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
public class QuestItemFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("quest_report.txt");
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final int INITIAL_LENGTH = 200;
|
||||
private static final boolean DISPLAY_EXTRA_INFO = true; // display items with zero quantity over the quest act WZ
|
||||
|
||||
static String wzPath = "../../wz";
|
||||
static String directoryName = "../..";
|
||||
static String newFile = "lib/QuestReport.txt";
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
private static final Map<Integer, Set<Integer>> startQuestItems = new HashMap<>(INITIAL_LENGTH);
|
||||
private static final Map<Integer, Set<Integer>> completeQuestItems = new HashMap<>(INITIAL_LENGTH);
|
||||
private static final Map<Integer, Set<Integer>> zeroedStartQuestItems = new HashMap<>();
|
||||
private static final Map<Integer, Set<Integer>> zeroedCompleteQuestItems = new HashMap<>();
|
||||
private static final Map<Integer, int[]> mixedQuestidItems = new HashMap<>();
|
||||
private static final Set<Integer> limitedQuestids = new HashSet<>();
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static int initialLength = 200;
|
||||
static int initialStringLength = 50;
|
||||
static boolean displayExtraInfo = true; // display items with zero quantity over the quest act WZ
|
||||
|
||||
static Map<Integer, Set<Integer>> startQuestItems = new HashMap<>(initialLength);
|
||||
static Map<Integer, Set<Integer>> completeQuestItems = new HashMap<>(initialLength);
|
||||
|
||||
static Map<Integer, Set<Integer>> zeroedStartQuestItems = new HashMap<>();
|
||||
static Map<Integer, Set<Integer>> zeroedCompleteQuestItems = new HashMap<>();
|
||||
static Map<Integer, int[]> mixedQuestidItems = new HashMap<>();
|
||||
static Set<Integer> limitedQuestids = new HashSet<>();
|
||||
|
||||
static byte status = 0;
|
||||
static int questId = -1;
|
||||
static int isCompleteState = 0;
|
||||
|
||||
static int currentItemid = 0;
|
||||
static int currentCount = 0;
|
||||
private static MapleItemInformationProvider ii;
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int questId = -1;
|
||||
private static int isCompleteState = 0;
|
||||
private static int currentItemid = 0;
|
||||
private static int currentCount = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
if(j < i) return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
if (j < i) {
|
||||
return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
|
||||
}
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -106,56 +76,53 @@ public class MapleQuestItemFetcher {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void inspectQuestItemList(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
readItemToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void processCurrentItem() {
|
||||
try {
|
||||
if(ii.isQuestItem(currentItemid)) {
|
||||
if(currentCount != 0) {
|
||||
if(isCompleteState == 1) {
|
||||
if(currentCount < 0) {
|
||||
if (ii.isQuestItem(currentItemid)) {
|
||||
if (currentCount != 0) {
|
||||
if (isCompleteState == 1) {
|
||||
if (currentCount < 0) {
|
||||
Set<Integer> qi = completeQuestItems.get(questId);
|
||||
if(qi == null) {
|
||||
if (qi == null) {
|
||||
Set<Integer> newSet = new HashSet<>();
|
||||
newSet.add(currentItemid);
|
||||
|
||||
@@ -165,9 +132,9 @@ public class MapleQuestItemFetcher {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(currentCount > 0) {
|
||||
if (currentCount > 0) {
|
||||
Set<Integer> qi = startQuestItems.get(questId);
|
||||
if(qi == null) {
|
||||
if (qi == null) {
|
||||
Set<Integer> newSet = new HashSet<>();
|
||||
newSet.add(currentItemid);
|
||||
|
||||
@@ -178,9 +145,9 @@ public class MapleQuestItemFetcher {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(isCompleteState == 1) {
|
||||
if (isCompleteState == 1) {
|
||||
Set<Integer> qi = zeroedCompleteQuestItems.get(questId);
|
||||
if(qi == null) {
|
||||
if (qi == null) {
|
||||
Set<Integer> newSet = new HashSet<>();
|
||||
newSet.add(currentItemid);
|
||||
|
||||
@@ -190,7 +157,7 @@ public class MapleQuestItemFetcher {
|
||||
}
|
||||
} else {
|
||||
Set<Integer> qi = zeroedStartQuestItems.get(questId);
|
||||
if(qi == null) {
|
||||
if (qi == null) {
|
||||
Set<Integer> newSet = new HashSet<>();
|
||||
newSet.add(currentItemid);
|
||||
|
||||
@@ -201,27 +168,26 @@ public class MapleQuestItemFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readItemToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
|
||||
processCurrentItem();
|
||||
|
||||
|
||||
currentItemid = 0;
|
||||
currentCount = 0;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
String d = getName(token);
|
||||
|
||||
if(d.equals("id")) {
|
||||
|
||||
if (d.equals("id")) {
|
||||
currentItemid = Integer.parseInt(getValue(token));
|
||||
} else if(d.equals("count")) {
|
||||
} else if (d.equals("count")) {
|
||||
currentCount = Integer.parseInt(getValue(token));
|
||||
}
|
||||
}
|
||||
@@ -231,22 +197,19 @@ public class MapleQuestItemFetcher {
|
||||
String d;
|
||||
int temp;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting QuestId
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 2) { //start/complete
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 3) {
|
||||
} else if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
if(d.contains("item")) {
|
||||
if (d.contains("item")) {
|
||||
temp = status;
|
||||
inspectQuestItemList(temp);
|
||||
} else {
|
||||
@@ -256,41 +219,38 @@ public class MapleQuestItemFetcher {
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if(status == 3) {
|
||||
if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
if(d.equals("end")) {
|
||||
if (d.equals("end")) {
|
||||
limitedQuestids.add(questId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateCheckToken(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting QuestId
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 2) { //start/complete
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 3) {
|
||||
} else if (status == 3) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if(status == 3) {
|
||||
if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
if(d.equals("end")) {
|
||||
if (d.equals("end")) {
|
||||
limitedQuestids.add(questId);
|
||||
}
|
||||
}
|
||||
@@ -299,14 +259,14 @@ public class MapleQuestItemFetcher {
|
||||
|
||||
private static void calculateQuestItemDiff() {
|
||||
// This will remove started quest items from the "to complete" item set.
|
||||
|
||||
for(Entry<Integer, Set<Integer>> qd : startQuestItems.entrySet()) {
|
||||
for(Integer qi : qd.getValue()) {
|
||||
|
||||
for (Map.Entry<Integer, Set<Integer>> qd : startQuestItems.entrySet()) {
|
||||
for (Integer qi : qd.getValue()) {
|
||||
Set<Integer> questSet = completeQuestItems.get(qd.getKey());
|
||||
|
||||
if(questSet != null) {
|
||||
if(questSet.remove(qi)) {
|
||||
if(completeQuestItems.isEmpty()) {
|
||||
|
||||
if (questSet != null) {
|
||||
if (questSet.remove(qi)) {
|
||||
if (completeQuestItems.isEmpty()) {
|
||||
completeQuestItems.remove(qd.getKey());
|
||||
}
|
||||
}
|
||||
@@ -314,37 +274,37 @@ public class MapleQuestItemFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static List<Pair<Integer, Integer>> getPairsQuestItem() { // quest items not gained at WZ's quest start
|
||||
List<Pair<Integer, Integer>> list = new ArrayList<>(initialLength);
|
||||
|
||||
for(Entry<Integer, Set<Integer>> qd : completeQuestItems.entrySet()) {
|
||||
for(Integer qi : qd.getValue()) {
|
||||
List<Pair<Integer, Integer>> list = new ArrayList<>(INITIAL_LENGTH);
|
||||
|
||||
for (Map.Entry<Integer, Set<Integer>> qd : completeQuestItems.entrySet()) {
|
||||
for (Integer qi : qd.getValue()) {
|
||||
list.add(new Pair<>(qi, qd.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static String getTableName(boolean dropdata) {
|
||||
return dropdata ? "drop_data" : "reactordrops";
|
||||
}
|
||||
|
||||
|
||||
private static void filterQuestDropsOnTable(Pair<Integer, Integer> iq, List<Pair<Integer, Integer>> itemsWithQuest, boolean dropdata) throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT questid FROM " + getTableName(dropdata) + " WHERE itemid = ?;");
|
||||
ps.setInt(1, iq.getLeft());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
if (rs.isBeforeFirst()) {
|
||||
while(rs.next()) {
|
||||
while (rs.next()) {
|
||||
int curQuest = rs.getInt(1);
|
||||
if(curQuest != iq.getRight()) {
|
||||
if (curQuest != iq.getRight()) {
|
||||
Set<Integer> sqSet = startQuestItems.get(curQuest);
|
||||
if(sqSet != null && sqSet.contains(iq.getLeft())) {
|
||||
if (sqSet != null && sqSet.contains(iq.getLeft())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int[] mixed = new int[3];
|
||||
mixed[0] = iq.getLeft();
|
||||
mixed[1] = curQuest;
|
||||
@@ -360,176 +320,171 @@ public class MapleQuestItemFetcher {
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
|
||||
private static void filterQuestDropsOnDB(List<Pair<Integer, Integer>> itemsWithQuest) throws SQLException {
|
||||
List<Pair<Integer, Integer>> copyItemsWithQuest = new ArrayList<>(itemsWithQuest);
|
||||
try {
|
||||
for(Pair<Integer, Integer> iq : copyItemsWithQuest) {
|
||||
for (Pair<Integer, Integer> iq : copyItemsWithQuest) {
|
||||
filterQuestDropsOnTable(iq, itemsWithQuest, true);
|
||||
filterQuestDropsOnTable(iq, itemsWithQuest, false);
|
||||
}
|
||||
}
|
||||
catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void filterDirectorySearchMatchingData(String path, List<Pair<Integer, Integer>> itemsWithQuest) {
|
||||
Iterator iter = FileUtils.iterateFiles(new File(directoryName + "/" + path), new String[]{"sql", "js", "txt","java"}, true);
|
||||
|
||||
while(iter.hasNext()) {
|
||||
File file = (File) iter.next();
|
||||
private static void filterDirectorySearchMatchingData(String path, List<Pair<Integer, Integer>> itemsWithQuest) {
|
||||
Iterator<File> iter = FileUtils.iterateFiles(new File(path), new String[]{"sql", "js", "txt", "java"}, true);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
File file = iter.next();
|
||||
fileSearchMatchingData(file, itemsWithQuest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean foundMatchingDataOnFile(String fileContent, String searchStr) {
|
||||
return fileContent.contains(searchStr);
|
||||
}
|
||||
|
||||
|
||||
private static void fileSearchMatchingData(File file, List<Pair<Integer, Integer>> itemsWithQuest) {
|
||||
try {
|
||||
String fileContent = FileUtils.readFileToString(file, "UTF-8");
|
||||
|
||||
String fileContent = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
|
||||
|
||||
List<Pair<Integer, Integer>> copyItemsWithQuest = new ArrayList<>(itemsWithQuest);
|
||||
for(Pair<Integer, Integer> iq : copyItemsWithQuest) {
|
||||
if(foundMatchingDataOnFile(fileContent, String.valueOf(iq.getLeft()))) {
|
||||
for (Pair<Integer, Integer> iq : copyItemsWithQuest) {
|
||||
if (foundMatchingDataOnFile(fileContent, String.valueOf(iq.getLeft()))) {
|
||||
itemsWithQuest.remove(iq);
|
||||
}
|
||||
}
|
||||
} catch(IOException ioe) {
|
||||
} catch (IOException ioe) {
|
||||
System.out.println("Failed to read file: " + file.getAbsolutePath());
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleQuestItemFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the underlying DB, server source files and the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
private static List<Entry<Integer, Integer>> getSortedMapEntries0(Map<Integer, Integer> map) {
|
||||
List<Entry<Integer, Integer>> list = new ArrayList<>(map.size());
|
||||
|
||||
private static List<Map.Entry<Integer, Integer>> getSortedMapEntries0(Map<Integer, Integer> map) {
|
||||
List<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.size());
|
||||
list.addAll(map.entrySet());
|
||||
|
||||
Collections.sort(list, (o1, o2) -> o1.getKey() - o2.getKey());
|
||||
|
||||
|
||||
list.sort((o1, o2) -> o1.getKey() - o2.getKey());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<Entry<Integer, int[]>> getSortedMapEntries1(Map<Integer, int[]> map) {
|
||||
List<Entry<Integer, int[]>> list = new ArrayList<>(map.size());
|
||||
|
||||
private static List<Map.Entry<Integer, int[]>> getSortedMapEntries1(Map<Integer, int[]> map) {
|
||||
List<Map.Entry<Integer, int[]>> list = new ArrayList<>(map.size());
|
||||
list.addAll(map.entrySet());
|
||||
|
||||
Collections.sort(list, (o1, o2) -> o1.getKey() - o2.getKey());
|
||||
|
||||
|
||||
list.sort((o1, o2) -> o1.getKey() - o2.getKey());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static List<Pair<Integer, List<Integer>>> getSortedMapEntries2(Map<Integer, Set<Integer>> map) {
|
||||
List<Pair<Integer, List<Integer>>> list = new ArrayList<>(map.size());
|
||||
for(Entry<Integer, Set<Integer>> e : map.entrySet()) {
|
||||
for (Map.Entry<Integer, 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) -> o1.getLeft() - o2.getLeft());
|
||||
|
||||
|
||||
list.sort((o1, o2) -> o1.getLeft() - o2.getLeft());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static String getExpiredStringLabel(int questid) {
|
||||
return (!limitedQuestids.contains(questid) ? "" : " EXPIRED");
|
||||
}
|
||||
|
||||
private static void ReportQuestItemData() {
|
||||
|
||||
private static void reportQuestItemData() {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
String fileName = null;
|
||||
|
||||
try {
|
||||
Class.forName(driver).newInstance();
|
||||
|
||||
System.out.println("Reading WZs...");
|
||||
|
||||
fileName = wzPath + "/Quest.wz/Check.img.xml";
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||
|
||||
fileName = WZFiles.QUEST.getFilePath() + "/Check.img.xml";
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateCheckToken(line); // fetch expired quests through here as well
|
||||
}
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
fileName = wzPath + "/Quest.wz/Act.img.xml";
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||
|
||||
fileName = WZFiles.QUEST.getFilePath() + "/Act.img.xml";
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateActToken(line);
|
||||
}
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
|
||||
System.out.println("Calculating table diffs...");
|
||||
calculateQuestItemDiff();
|
||||
|
||||
|
||||
System.out.println("Filtering drops on DB...");
|
||||
List<Pair<Integer, Integer>> itemsWithQuest = getPairsQuestItem();
|
||||
|
||||
// filter drop data on DB
|
||||
con = DriverManager.getConnection(host, username, password);
|
||||
|
||||
filterQuestDropsOnDB(itemsWithQuest);
|
||||
con.close();
|
||||
|
||||
|
||||
System.out.println("Filtering drops on project files...");
|
||||
// finally, filter whether this item is mentioned on the source code or not.
|
||||
filterDirectorySearchMatchingData("scripts", itemsWithQuest);
|
||||
filterDirectorySearchMatchingData("sql", itemsWithQuest);
|
||||
filterDirectorySearchMatchingData("src", itemsWithQuest);
|
||||
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
// report suspects of missing quest drop data, as well as those drop data that may have incorrect questids.
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
|
||||
if(!mixedQuestidItems.isEmpty()) {
|
||||
|
||||
if (!mixedQuestidItems.isEmpty()) {
|
||||
printWriter.println("INCORRECT QUESTIDS ON DB");
|
||||
for(Entry<Integer, int[]> emqi : getSortedMapEntries1(mixedQuestidItems)) {
|
||||
for (Map.Entry<Integer, int[]> emqi : getSortedMapEntries1(mixedQuestidItems)) {
|
||||
int[] mqi = emqi.getValue();
|
||||
printWriter.println(mqi[0] + " : " + mqi[1] + " -> " + mqi[2] + getExpiredStringLabel(mqi[2]));
|
||||
}
|
||||
printWriter.println("\n\n\n\n\n");
|
||||
}
|
||||
|
||||
if(!itemsWithQuest.isEmpty()) {
|
||||
|
||||
if (!itemsWithQuest.isEmpty()) {
|
||||
Map<Integer, Integer> mapIwq = new HashMap<>(itemsWithQuest.size());
|
||||
for(Pair<Integer, Integer> iwq : itemsWithQuest) {
|
||||
for (Pair<Integer, Integer> iwq : itemsWithQuest) {
|
||||
mapIwq.put(iwq.getLeft(), iwq.getRight());
|
||||
}
|
||||
|
||||
|
||||
printWriter.println("ITEMS WITH NO QUEST DROP DATA ON DB");
|
||||
for(Entry<Integer, Integer> iwq : getSortedMapEntries0(mapIwq)) {
|
||||
for (Map.Entry<Integer, Integer> iwq : getSortedMapEntries0(mapIwq)) {
|
||||
printWriter.println(iwq.getKey() + " - " + iwq.getValue() + getExpiredStringLabel(iwq.getValue()));
|
||||
}
|
||||
printWriter.println("\n\n\n\n\n");
|
||||
}
|
||||
|
||||
if(displayExtraInfo) {
|
||||
if(!zeroedStartQuestItems.isEmpty()) {
|
||||
|
||||
if (DISPLAY_EXTRA_INFO) {
|
||||
if (!zeroedStartQuestItems.isEmpty()) {
|
||||
printWriter.println("START QUEST ITEMS WITH ZERO QUANTITY");
|
||||
for(Pair<Integer, List<Integer>> iwq : getSortedMapEntries2(zeroedStartQuestItems)) {
|
||||
for (Pair<Integer, List<Integer>> iwq : getSortedMapEntries2(zeroedStartQuestItems)) {
|
||||
printWriter.println(iwq.getLeft() + getExpiredStringLabel(iwq.getLeft()) + ":");
|
||||
for(Integer i : iwq.getRight()) {
|
||||
for (Integer i : iwq.getRight()) {
|
||||
printWriter.println(" " + i);
|
||||
}
|
||||
printWriter.println();
|
||||
@@ -537,11 +492,11 @@ public class MapleQuestItemFetcher {
|
||||
printWriter.println("\n\n\n\n\n");
|
||||
}
|
||||
|
||||
if(!zeroedCompleteQuestItems.isEmpty()) {
|
||||
if (!zeroedCompleteQuestItems.isEmpty()) {
|
||||
printWriter.println("COMPLETE QUEST ITEMS WITH ZERO QUANTITY");
|
||||
for(Pair<Integer, List<Integer>> iwq : getSortedMapEntries2(zeroedCompleteQuestItems)) {
|
||||
for (Pair<Integer, List<Integer>> iwq : getSortedMapEntries2(zeroedCompleteQuestItems)) {
|
||||
printWriter.println(iwq.getLeft() + getExpiredStringLabel(iwq.getLeft()) + ":");
|
||||
for(Integer i : iwq.getRight()) {
|
||||
for (Integer i : iwq.getRight()) {
|
||||
printWriter.println(" " + i);
|
||||
}
|
||||
printWriter.println();
|
||||
@@ -552,40 +507,23 @@ public class MapleQuestItemFetcher {
|
||||
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
catch(FileNotFoundException ex) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + fileName + "'");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + fileName + "'");
|
||||
}
|
||||
|
||||
catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Warning: Could not establish connection to database to report quest data.");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(ClassNotFoundException e) {
|
||||
System.out.println("Error: could not find class");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(InstantiationException e) {
|
||||
System.out.println("Error: instantiation failure");
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("wzpath", wzPath);
|
||||
DatabaseConnection.initializeConnectionPool(); // MapleItemInformationProvider loads some unrelated db data
|
||||
ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
ReportQuestItemData();
|
||||
|
||||
reportQuestItemData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
263
src/main/java/tools/mapletools/QuestMesoFetcher.java
Normal file
263
src/main/java/tools/mapletools/QuestMesoFetcher.java
Normal file
@@ -0,0 +1,263 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application parses the Quest.wz file inputted and generates a report showing
|
||||
* all cases where a quest takes a meso fee to complete a quest, but it doesn't
|
||||
* properly checks the player for the needed amount before completing it.
|
||||
* <p>
|
||||
* Running it should generate a report file under "output" folder with the search results.
|
||||
*/
|
||||
public class QuestMesoFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("quest_meso_report.txt");
|
||||
private static final boolean PRINT_FEES = true; // print missing values as additional info report
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
|
||||
private static final Map<Integer, Integer> checkedMesoQuests = new HashMap<>();
|
||||
private static final Map<Integer, Integer> appliedMesoQuests = new HashMap<>();
|
||||
private static final Set<Integer> checkedEndscriptQuests = new HashSet<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int questId = -1;
|
||||
private static int isCompleteState = 0;
|
||||
private static int currentMeso = 0;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("value");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateTokenAct(String token) {
|
||||
String d;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
} else if (status == 3) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if (token.contains("money")) {
|
||||
if (isCompleteState != 0) {
|
||||
d = getValue(token);
|
||||
|
||||
currentMeso = -1 * Integer.parseInt(d);
|
||||
|
||||
if (currentMeso > 0) {
|
||||
appliedMesoQuests.put(questId, currentMeso);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void translateTokenCheck(String token) {
|
||||
String d;
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
} else if (status == 3) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if (token.contains("endmeso")) {
|
||||
d = getValue(token);
|
||||
currentMeso = Integer.parseInt(d);
|
||||
|
||||
checkedMesoQuests.put(questId, currentMeso);
|
||||
} else if (token.contains("endscript")) {
|
||||
checkedEndscriptQuests.add(questId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void readQuestMesoData() throws IOException {
|
||||
String line;
|
||||
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(WZFiles.QUEST.getFilePath() + "/Act.img.xml"), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateTokenAct(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(WZFiles.QUEST.getFilePath() + "/Check.img.xml"), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateTokenCheck(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleQuestMesoFetcher 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(Map<Integer, Integer> target, Map<Integer, Integer> base, boolean testingCheck) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
List<Integer> error = new ArrayList<>();
|
||||
|
||||
Map<Integer, Integer> questFee = new HashMap<>();
|
||||
|
||||
for (Map.Entry<Integer, Integer> e : base.entrySet()) {
|
||||
Integer v = target.get(e.getKey());
|
||||
|
||||
if (v == null) {
|
||||
if (testingCheck || !checkedEndscriptQuests.contains(e.getKey())) {
|
||||
result.add(e.getKey());
|
||||
questFee.put(e.getKey(), e.getValue());
|
||||
}
|
||||
} else if (v.intValue() != e.getValue().intValue()) {
|
||||
error.add(e.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.isEmpty() || !error.isEmpty()) {
|
||||
printWriter.println("MISMATCH INFORMATION ON '" + (testingCheck ? "check" : "act") + "':");
|
||||
if (!result.isEmpty()) {
|
||||
result.sort((o1, o2) -> o1 - o2);
|
||||
|
||||
printWriter.println("# MISSING");
|
||||
|
||||
if (!PRINT_FEES) {
|
||||
for (Integer i : result) {
|
||||
printWriter.println(i);
|
||||
}
|
||||
} else {
|
||||
for (Integer i : result) {
|
||||
printWriter.println(i + " " + questFee.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
if (!error.isEmpty() && testingCheck) {
|
||||
error.sort((o1, o2) -> o1 - o2);
|
||||
|
||||
printWriter.println("# WRONG VALUE");
|
||||
|
||||
for (Integer i : error) {
|
||||
printWriter.println(i);
|
||||
}
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
printWriter.println("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportQuestMesoData() {
|
||||
// This will reference one line at a time
|
||||
|
||||
try {
|
||||
System.out.println("Reading WZs...");
|
||||
readQuestMesoData();
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
// report missing meso checks on quest completes
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
|
||||
printReportFileResults(checkedMesoQuests, appliedMesoQuests, true);
|
||||
printReportFileResults(appliedMesoQuests, checkedMesoQuests, false);
|
||||
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open quest file.");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading quest file.");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
reportQuestMesoData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,89 +1,47 @@
|
||||
/*
|
||||
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.
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
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 maplequestlinefetcher;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
|
||||
This application parses the Quest.wz file inputted and generates a report showing
|
||||
all cases where quest script files have not been found for quests that requires a
|
||||
script file.
|
||||
As an extension, it highlights missing script files for questlines that hand over
|
||||
skills as rewards.
|
||||
|
||||
Running it should generate a report file under "lib" folder with the search results.
|
||||
|
||||
* <p>
|
||||
* This application parses the Quest.wz file inputted and generates a report showing
|
||||
* all cases where quest script files have not been found for quests that requires a
|
||||
* script file.
|
||||
* As an extension, it highlights missing script files for questlines that hand over
|
||||
* skills as rewards.
|
||||
* <p>
|
||||
* Running it should generate a report file under "output" folder with the search results.
|
||||
*/
|
||||
public class MapleQuestlineFetcher {
|
||||
static String actName = "../../wz/Quest.wz/Act.img.xml";
|
||||
static String checkName = "../../wz/Quest.wz/Check.img.xml";
|
||||
static String directoryName = "../..";
|
||||
static String newFile = "lib/QuestReport.txt";
|
||||
public class QuestlineFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("questline_report.txt");
|
||||
private static final String ACT_NAME = WZFiles.QUEST.getFilePath() + "/Act.img.xml";
|
||||
private static final String CHECK_NAME = WZFiles.QUEST.getFilePath() + "/Check.img.xml";
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
|
||||
private static final Stack<Integer> skillObtainableQuests = new Stack<>();
|
||||
private static final Set<Integer> scriptedQuestFiles = new HashSet<>();
|
||||
private static final Set<Integer> expiredQuests = new HashSet<>();
|
||||
private static final Map<Integer, List<Integer>> questDependencies = new HashMap<>();
|
||||
private static final Set<Integer> nonScriptedQuests = new HashSet<>();
|
||||
private static final Set<Integer> skillObtainableNonScriptedQuests = new HashSet<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static InputStreamReader fileReader = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int questId = -1;
|
||||
private static int isCompleteState = 0;
|
||||
private static boolean isScriptedQuest;
|
||||
private static boolean isExpiredQuest;
|
||||
private static List<Integer> questDependencyList;
|
||||
private static int curQuestId;
|
||||
private static int curQuestState;
|
||||
|
||||
static Connection con = null;
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static int initialLength = 200;
|
||||
static int initialStringLength = 50;
|
||||
|
||||
static byte status = 0;
|
||||
static int questId = -1;
|
||||
static int isCompleteState = 0;
|
||||
static boolean isScriptedQuest;
|
||||
static boolean isExpiredQuest;
|
||||
static List<Integer> questDependencyList;
|
||||
|
||||
static int curQuestId;
|
||||
static int curQuestState;
|
||||
|
||||
static Stack<Integer> skillObtainableQuests = new Stack<>();
|
||||
static Set<Integer> scriptedQuestFiles = new HashSet<>();
|
||||
static Set<Integer> expiredQuests = new HashSet<>();
|
||||
|
||||
static Map<Integer, List<Integer>> questDependencies = new HashMap<>();
|
||||
|
||||
static Set<Integer> nonScriptedQuests = new HashSet<>();
|
||||
static Set<Integer> skillObtainableNonScriptedQuests = new HashSet<>();
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -93,13 +51,13 @@ public class MapleQuestlineFetcher {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -109,108 +67,97 @@ public class MapleQuestlineFetcher {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateTokenCheck(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
if(status == 1) {
|
||||
|
||||
if (status == 1) {
|
||||
evaluateCurrentQuest();
|
||||
}
|
||||
else if(status == 4) {
|
||||
} else if (status == 4) {
|
||||
evaluateCurrentQuestDependency();
|
||||
}
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting QuestId
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
|
||||
|
||||
isScriptedQuest = false;
|
||||
isExpiredQuest = false;
|
||||
questDependencyList = new LinkedList<>();
|
||||
}
|
||||
else if(status == 2) { //start/complete
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 3) {
|
||||
if(isCompleteState == 1 || !token.contains("quest")) {
|
||||
} else if (status == 3) {
|
||||
if (isCompleteState == 1 || !token.contains("quest")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status += 1;
|
||||
}
|
||||
else {
|
||||
if(status == 3) {
|
||||
} else {
|
||||
if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
if(d.contains("script")) {
|
||||
|
||||
if (d.contains("script")) {
|
||||
isScriptedQuest = true;
|
||||
} else if(d.contains("end")) {
|
||||
} else if (d.contains("end")) {
|
||||
isExpiredQuest = true;
|
||||
}
|
||||
}
|
||||
else if(status == 5) {
|
||||
} else if (status == 5) {
|
||||
readQuestLabel(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateTokenAct(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting QuestId
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting QuestId
|
||||
d = getName(token);
|
||||
questId = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 2) { //start/complete
|
||||
} else if (status == 2) { //start/complete
|
||||
d = getName(token);
|
||||
isCompleteState = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 3) {
|
||||
if(isCompleteState == 1 && token.contains("skill")) {
|
||||
} else if (status == 3) {
|
||||
if (isCompleteState == 1 && token.contains("skill")) {
|
||||
skillObtainableQuests.add(questId);
|
||||
}
|
||||
|
||||
|
||||
forwardCursor(status);
|
||||
}
|
||||
|
||||
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
@@ -219,34 +166,29 @@ public class MapleQuestlineFetcher {
|
||||
String name = getName(token);
|
||||
String value = getValue(token);
|
||||
|
||||
switch(name) {
|
||||
case "id":
|
||||
curQuestId = Integer.parseInt(value);
|
||||
break;
|
||||
|
||||
case "state":
|
||||
curQuestState = Integer.parseInt(value);
|
||||
break;
|
||||
switch (name) {
|
||||
case "id" -> curQuestId = Integer.parseInt(value);
|
||||
case "state" -> curQuestState = Integer.parseInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void evaluateCurrentQuestDependency() {
|
||||
if(curQuestState == 2) {
|
||||
if (curQuestState == 2) {
|
||||
questDependencyList.add(curQuestId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void evaluateCurrentQuest() {
|
||||
if(isScriptedQuest && !scriptedQuestFiles.contains(questId)) {
|
||||
if (isScriptedQuest && !scriptedQuestFiles.contains(questId)) {
|
||||
nonScriptedQuests.add(questId);
|
||||
}
|
||||
if(isExpiredQuest) {
|
||||
if (isExpiredQuest) {
|
||||
expiredQuests.add(questId);
|
||||
}
|
||||
|
||||
|
||||
questDependencies.put(questId, questDependencyList);
|
||||
}
|
||||
|
||||
|
||||
private static void instantiateQuestScriptFiles(String directoryName) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
@@ -255,130 +197,126 @@ public class MapleQuestlineFetcher {
|
||||
for (File file : fList) {
|
||||
if (file.isFile()) {
|
||||
String fname = file.getName();
|
||||
|
||||
|
||||
try {
|
||||
Integer questid = Integer.parseInt(fname.substring(0, fname.indexOf('.')));
|
||||
scriptedQuestFiles.add(questid);
|
||||
} catch(NumberFormatException nfe) {}
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void readQuestsWithMissingScripts() throws IOException {
|
||||
String line;
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(checkName), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(CHECK_NAME), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateTokenCheck(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void readQuestsWithSkillReward() throws IOException {
|
||||
String line;
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(actName), "UTF-8");
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(ACT_NAME), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateTokenAct(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void calculateSkillRelatedMissingQuestScripts() {
|
||||
Stack<Integer> frontierQuests = skillObtainableQuests;
|
||||
Set<Integer> solvedQuests = new HashSet<>();
|
||||
|
||||
while(!frontierQuests.isEmpty()) {
|
||||
|
||||
while (!frontierQuests.isEmpty()) {
|
||||
Integer questid = frontierQuests.pop();
|
||||
solvedQuests.add(questid);
|
||||
|
||||
if(nonScriptedQuests.contains(questid)) {
|
||||
|
||||
if (nonScriptedQuests.contains(questid)) {
|
||||
skillObtainableNonScriptedQuests.add(questid);
|
||||
nonScriptedQuests.remove(questid);
|
||||
}
|
||||
|
||||
|
||||
List<Integer> questDependency = questDependencies.get(questid);
|
||||
for(Integer i : questDependency) {
|
||||
if(!solvedQuests.contains(i)) {
|
||||
for (Integer i : questDependency) {
|
||||
if (!solvedQuests.contains(i)) {
|
||||
frontierQuests.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleQuestlineFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the server-side WZ.xmls.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
private static List<Integer> getSortedListEntries(Set<Integer> set) {
|
||||
List<Integer> list = new ArrayList<>(set);
|
||||
Collections.sort(list);
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileResults() {
|
||||
if(!skillObtainableNonScriptedQuests.isEmpty()) {
|
||||
if (!skillObtainableNonScriptedQuests.isEmpty()) {
|
||||
printWriter.println("SKILL-RELATED NON-SCRIPTED QUESTS");
|
||||
for(Integer nsq : getSortedListEntries(skillObtainableNonScriptedQuests)) {
|
||||
for (Integer nsq : getSortedListEntries(skillObtainableNonScriptedQuests)) {
|
||||
printWriter.println(" " + nsq + (expiredQuests.contains(nsq) ? " EXPIRED" : ""));
|
||||
}
|
||||
|
||||
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
|
||||
printWriter.println("\nCOMMON NON-SCRIPTED QUESTS");
|
||||
for(Integer nsq : getSortedListEntries(nonScriptedQuests)) {
|
||||
for (Integer nsq : getSortedListEntries(nonScriptedQuests)) {
|
||||
printWriter.println(" " + nsq + (expiredQuests.contains(nsq) ? " EXPIRED" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReportQuestlineData() {
|
||||
|
||||
private static void reportQuestlineData() {
|
||||
// This will reference one line at a time
|
||||
|
||||
|
||||
try {
|
||||
System.out.println("Reading quest scripts...");
|
||||
instantiateQuestScriptFiles(directoryName + "/scripts/quest");
|
||||
|
||||
instantiateQuestScriptFiles(ToolConstants.SCRIPTS_PATH + "/quest");
|
||||
|
||||
System.out.println("Reading WZs...");
|
||||
readQuestsWithSkillReward();
|
||||
readQuestsWithMissingScripts();
|
||||
|
||||
|
||||
System.out.println("Calculating skill related quests...");
|
||||
calculateSkillRelatedMissingQuestScripts();
|
||||
|
||||
|
||||
System.out.println("Reporting results...");
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printReportFileHeader();
|
||||
printReportFileResults();
|
||||
|
||||
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
catch(FileNotFoundException ex) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open quest file.");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading quest file.");
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private static List<Pair<Integer, List<Integer>>> getSortedMapEntries(Map<Integer, List<Integer>> map) {
|
||||
List<Pair<Integer, List<Integer>>> list = new ArrayList<>(map.size());
|
||||
@@ -387,27 +325,27 @@ public class MapleQuestlineFetcher {
|
||||
for(Integer i : e.getValue()) {
|
||||
il.add(i);
|
||||
}
|
||||
|
||||
|
||||
Collections.sort(il, new Comparator<Integer>() {
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
list.add(new Pair<>(e.getKey(), il));
|
||||
}
|
||||
|
||||
|
||||
Collections.sort(list, new Comparator<Pair<Integer, List<Integer>>>() {
|
||||
@Override
|
||||
public int compare(Pair<Integer, List<Integer>> o1, Pair<Integer, List<Integer>> o2) {
|
||||
return o1.getLeft() - o2.getLeft();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private static void DumpQuestlineData() {
|
||||
for(Pair<Integer, List<Integer>> questDependency : getSortedMapEntries(questDependencies)) {
|
||||
if(!questDependency.right.isEmpty()) {
|
||||
@@ -416,9 +354,9 @@ public class MapleQuestlineFetcher {
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
ReportQuestlineData();
|
||||
reportQuestlineData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
112
src/main/java/tools/mapletools/ReactorDropFetcher.java
Normal file
112
src/main/java/tools/mapletools/ReactorDropFetcher.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application reports in reactor ids that have drops on the SQL table but are
|
||||
* not yet coded.
|
||||
*/
|
||||
public class ReactorDropFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("reactor_drop_report.txt");
|
||||
private static final String REACTOR_SCRIPT_PATH = ToolConstants.SCRIPTS_PATH + "/reactor";
|
||||
private static final Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static final Set<Integer> reactors = new HashSet<>();
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleReactorDropFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account several data info from the underlying DB and the server-side files.");
|
||||
printWriter.println();
|
||||
}
|
||||
|
||||
private static int getReactorIdFromFilename(String name) {
|
||||
try {
|
||||
return Integer.parseInt(name.substring(0, name.indexOf('.')));
|
||||
} catch (Exception e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeScriptedReactorids(String directoryName) {
|
||||
File directory = new File(directoryName);
|
||||
|
||||
// get all the files from a directory
|
||||
File[] fList = directory.listFiles();
|
||||
for (File file : fList) {
|
||||
if (file.isFile()) {
|
||||
reactors.remove(getReactorIdFromFilename(file.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadReactoridsOnDB() throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT DISTINCT reactorid FROM reactordrops;");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
reactors.add(rs.getInt("reactorid"));
|
||||
}
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
}
|
||||
|
||||
private static List<Integer> getSortedReactorids() {
|
||||
List<Integer> sortedReactors = new ArrayList<>(reactors);
|
||||
Collections.sort(sortedReactors);
|
||||
|
||||
return sortedReactors;
|
||||
}
|
||||
|
||||
private static void fetchMissingReactorDrops() throws SQLException {
|
||||
loadReactoridsOnDB();
|
||||
removeScriptedReactorids(REACTOR_SCRIPT_PATH);
|
||||
}
|
||||
|
||||
private static void reportMissingReactorDrops() throws SQLException {
|
||||
if (!reactors.isEmpty()) {
|
||||
printWriter.println("MISSING REACTOR DROP SCRIPTS");
|
||||
for (Integer reactorid : getSortedReactorids()) {
|
||||
printWriter.println(" " + reactorid);
|
||||
}
|
||||
printWriter.println("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportMissingReactors() {
|
||||
try {
|
||||
System.out.println("Fetching reactors from DB...");
|
||||
fetchMissingReactorDrops();
|
||||
|
||||
con.close();
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
// report suspects of missing quest drop data, as well as those drop data that may have incorrect questids.
|
||||
System.out.println("Reporting results...");
|
||||
printReportFileHeader();
|
||||
reportMissingReactorDrops();
|
||||
|
||||
printWriter.close();
|
||||
System.out.println("Done!");
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Warning: Could not establish connection to database to report quest data.");
|
||||
System.out.println(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
reportMissingReactors();
|
||||
}
|
||||
}
|
||||
30
src/main/java/tools/mapletools/SimpleDatabaseConnection.java
Normal file
30
src/main/java/tools/mapletools/SimpleDatabaseConnection.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
final class SimpleDatabaseConnection {
|
||||
private SimpleDatabaseConnection() {}
|
||||
|
||||
static Connection getConnection() {
|
||||
muffleLogging();
|
||||
DatabaseConnection.initializeConnectionPool();
|
||||
|
||||
try {
|
||||
return DatabaseConnection.getConnection();
|
||||
} catch (SQLException e) {
|
||||
throw new IllegalStateException("Failed to get database connection", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void muffleLogging() {
|
||||
final Level minimumVisibleLevel = Level.WARN;
|
||||
Configurator.setLevel(LogManager.getLogger(com.zaxxer.hikari.HikariDataSource.class).getName(), minimumVisibleLevel);
|
||||
Configurator.setRootLevel(minimumVisibleLevel);
|
||||
}
|
||||
}
|
||||
@@ -1,78 +1,55 @@
|
||||
/*
|
||||
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 mapleskillmakerfetcher;
|
||||
import provider.wz.WZFiles;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* The objective of this program is to uncover all maker data from the
|
||||
* ItemMaker.wz.xml files and generate a SQL file with every data info
|
||||
* for the Maker DB tables.
|
||||
*
|
||||
*/
|
||||
|
||||
public class MapleSkillMakerFetcher {
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
public class SkillMakerFetcher {
|
||||
private static final File INPUT_FILE = new File(WZFiles.ETC.getFile(), "ItemMake.img.xml");
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("maker-data.sql");
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
|
||||
static String fileName = "../../wz/Etc.wz/ItemMake.img.xml";
|
||||
static String newFile = "lib/MakerData.sql";
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static byte state = 0;
|
||||
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
static byte status = 0;
|
||||
static byte state = 0;
|
||||
|
||||
static int initialStringLength = 50;
|
||||
|
||||
// maker data fields
|
||||
static int id = -1;
|
||||
static int itemid = -1;
|
||||
static int reqLevel = -1;
|
||||
static int reqMakerLevel = -1;
|
||||
static int reqItem = -1;
|
||||
static int reqMeso = -1;
|
||||
static int reqEquip = -1;
|
||||
static int catalyst = -1;
|
||||
static int quantity = -1;
|
||||
static int tuc = -1;
|
||||
|
||||
static int recipePos = -1;
|
||||
static int recipeProb = -1;
|
||||
static int recipeCount = -1;
|
||||
static int recipeItem = -1;
|
||||
|
||||
private static int id = -1;
|
||||
private static int itemid = -1;
|
||||
private static int reqLevel = -1;
|
||||
private static int reqMakerLevel = -1;
|
||||
private static int reqItem = -1;
|
||||
private static int reqMeso = -1;
|
||||
private static int reqEquip = -1;
|
||||
private static int catalyst = -1;
|
||||
private static int quantity = -1;
|
||||
private static int tuc = -1;
|
||||
|
||||
private static int recipePos = -1;
|
||||
private static int recipeProb = -1;
|
||||
private static int recipeCount = -1;
|
||||
private static int recipeItem = -1;
|
||||
|
||||
static List<int[]> recipeList = null;
|
||||
static List<int[]> randomList = null;
|
||||
static List<MapleMakerItemEntry> makerList = new ArrayList<>(100);
|
||||
|
||||
static List<MakerItemEntry> makerList = new ArrayList<>(100);
|
||||
|
||||
private static void resetMakerDataFields() {
|
||||
reqLevel = 0;
|
||||
reqMakerLevel = 0;
|
||||
@@ -82,16 +59,16 @@ public class MapleSkillMakerFetcher {
|
||||
catalyst = 0;
|
||||
quantity = 0;
|
||||
tuc = 0;
|
||||
|
||||
|
||||
recipePos = 0;
|
||||
recipeProb = 0;
|
||||
recipeCount = 0;
|
||||
recipeItem = 0;
|
||||
|
||||
|
||||
recipeList = null;
|
||||
randomList = null;
|
||||
}
|
||||
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -101,16 +78,16 @@ public class MapleSkillMakerFetcher {
|
||||
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);
|
||||
String s = d.trim();
|
||||
s.replaceFirst("^0+(?!$)", "");
|
||||
|
||||
return(s);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -120,157 +97,125 @@ public class MapleSkillMakerFetcher {
|
||||
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);
|
||||
String s = d.trim();
|
||||
s.replaceFirst("^0+(?!$)", "");
|
||||
|
||||
return(s);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
private static int[] generateRecipeItem() {
|
||||
int pair[] = new int[2];
|
||||
int[] pair = new int[2];
|
||||
pair[0] = recipeItem;
|
||||
pair[1] = recipeCount;
|
||||
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
|
||||
private static int[] generateRandomItem() {
|
||||
int tuple[] = new int[3];
|
||||
int[] tuple = new int[3];
|
||||
tuple[0] = recipeItem;
|
||||
tuple[1] = recipeCount;
|
||||
tuple[2] = recipeProb;
|
||||
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
|
||||
if(status == 2) { //close item maker data
|
||||
|
||||
if (status == 2) { //close item maker data
|
||||
generateUpdatedItemFee(); // for equipments, this will try to update reqMeso to be conformant with the client.
|
||||
makerList.add(new MapleMakerItemEntry(id, itemid, reqLevel, reqMakerLevel, reqItem, reqMeso, reqEquip, catalyst, quantity, tuc, recipeCount, recipeItem, recipeList, randomList));
|
||||
makerList.add(new MakerItemEntry(id, itemid, reqLevel, reqMakerLevel, reqItem, reqMeso, reqEquip, catalyst, quantity, tuc, recipeCount, recipeItem, recipeList, randomList));
|
||||
resetMakerDataFields();
|
||||
} else if(status == 4) { //close recipe/random item
|
||||
if(state == 0) recipeList.add(generateRecipeItem());
|
||||
else if(state == 1) randomList.add(generateRandomItem());
|
||||
} else if (status == 4) { //close recipe/random item
|
||||
if (state == 0) {
|
||||
recipeList.add(generateRecipeItem());
|
||||
} else if (state == 1) {
|
||||
randomList.add(generateRandomItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting id
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting id
|
||||
d = getName(token);
|
||||
id = Integer.parseInt(d);
|
||||
System.out.println("Parsing maker id " + id);
|
||||
}
|
||||
else if(status == 2) { //getting target item id
|
||||
} else if (status == 2) { //getting target item id
|
||||
d = getName(token);
|
||||
itemid = Integer.parseInt(d);
|
||||
}
|
||||
else if(status == 3) {
|
||||
} else if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
switch(d) {
|
||||
case "recipe":
|
||||
|
||||
switch (d) {
|
||||
case "recipe" -> {
|
||||
recipeList = new LinkedList<>();
|
||||
state = 0;
|
||||
break;
|
||||
|
||||
case "randomReward":
|
||||
}
|
||||
case "randomReward" -> {
|
||||
randomList = new LinkedList<>();
|
||||
state = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
forwardCursor(3); // unused content, read until end of block
|
||||
break;
|
||||
}
|
||||
default -> forwardCursor(3); // unused content, read until end of block
|
||||
}
|
||||
}
|
||||
else if(status == 4) { // inside recipe/random
|
||||
} else if (status == 4) { // inside recipe/random
|
||||
d = getName(token);
|
||||
recipePos = Integer.parseInt(d);
|
||||
}
|
||||
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if(status == 3) {
|
||||
if (status == 3) {
|
||||
d = getName(token);
|
||||
|
||||
switch(d) {
|
||||
case "itemNum":
|
||||
quantity = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "meso":
|
||||
reqMeso = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "reqItem":
|
||||
reqItem = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "reqLevel":
|
||||
reqLevel = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "reqSkillLevel":
|
||||
reqMakerLevel = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "tuc":
|
||||
tuc = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "catalyst":
|
||||
catalyst = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
case "reqEquip":
|
||||
reqEquip = Integer.valueOf(getValue(token));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
switch (d) {
|
||||
case "itemNum" -> quantity = Integer.parseInt(getValue(token));
|
||||
case "meso" -> reqMeso = Integer.parseInt(getValue(token));
|
||||
case "reqItem" -> reqItem = Integer.parseInt(getValue(token));
|
||||
case "reqLevel" -> reqLevel = Integer.parseInt(getValue(token));
|
||||
case "reqSkillLevel" -> reqMakerLevel = Integer.parseInt(getValue(token));
|
||||
case "tuc" -> tuc = Integer.parseInt(getValue(token));
|
||||
case "catalyst" -> catalyst = Integer.parseInt(getValue(token));
|
||||
case "reqEquip" -> reqEquip = Integer.parseInt(getValue(token));
|
||||
default -> {
|
||||
System.out.println("Unhandled case: '" + d + "'");
|
||||
state = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(status == 5) { // inside recipe/random item
|
||||
} else if (status == 5) { // inside recipe/random item
|
||||
d = getName(token);
|
||||
if(d.equals("item")) {
|
||||
if (d.equals("item")) {
|
||||
recipeItem = Integer.parseInt(getValue(token));
|
||||
} else {
|
||||
if(state == 0) {
|
||||
if (state == 0) {
|
||||
recipeCount = Integer.parseInt(getValue(token));
|
||||
} else {
|
||||
if(d.equals("itemNum")) {
|
||||
if (d.equals("itemNum")) {
|
||||
recipeCount = Integer.parseInt(getValue(token));
|
||||
} else {
|
||||
recipeProb = Integer.parseInt(getValue(token));
|
||||
@@ -280,17 +225,17 @@ public class MapleSkillMakerFetcher {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void generateUpdatedItemFee() {
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
float adjPrice = reqMeso;
|
||||
|
||||
if(itemid < 2000000) {
|
||||
|
||||
if (itemid < 2000000) {
|
||||
Map<String, Integer> stats = ii.getEquipStats(itemid);
|
||||
if(stats != null) {
|
||||
if (stats != null) {
|
||||
int val = itemid / 100000;
|
||||
|
||||
if(val == 13 || val == 14) { // is weapon-type
|
||||
|
||||
if (val == 13 || val == 14) { // is weapon-type
|
||||
adjPrice /= 10;
|
||||
adjPrice += reqMeso;
|
||||
|
||||
@@ -314,82 +259,78 @@ public class MapleSkillMakerFetcher {
|
||||
reqMeso = 1000 * (int) Math.ceil(adjPrice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void WriteMakerTableFile() {
|
||||
printWriter.println(" # SQL File autogenerated from the MapleSkillMakerFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data is conformant with the ItemMake.img.xml file used to compile this.");
|
||||
printWriter.println();
|
||||
|
||||
|
||||
StringBuilder sb_create = new StringBuilder("INSERT IGNORE INTO `makercreatedata` (`id`, `itemid`, `req_level`, `req_maker_level`, `req_meso`, `req_item`, `req_equip`, `catalyst`, `quantity`, `tuc`) VALUES\r\n");
|
||||
StringBuilder sb_recipe = new StringBuilder("INSERT IGNORE INTO `makerrecipedata` (`itemid`, `req_item`, `count`) VALUES\r\n");
|
||||
StringBuilder sb_reward = new StringBuilder("INSERT IGNORE INTO `makerrewarddata` (`itemid`, `rewardid`, `quantity`, `prob`) VALUES\r\n");
|
||||
|
||||
for(MapleMakerItemEntry it : makerList) {
|
||||
|
||||
for (MakerItemEntry it : makerList) {
|
||||
sb_create.append(" (" + it.id + ", " + it.itemid + ", " + it.reqLevel + ", " + it.reqMakerLevel + ", " + it.reqMeso + ", " + it.reqItem + ", " + it.reqEquip + ", " + it.catalyst + ", " + it.quantity + ", " + it.tuc + "),\r\n");
|
||||
|
||||
if(it.recipeList != null) {
|
||||
for(int[] rit : it.recipeList) {
|
||||
sb_recipe.append(" (" + it.itemid + ", " + rit[0] + ", " + rit[1] + "),\r\n");
|
||||
|
||||
if (it.recipeList != null) {
|
||||
for (int[] rit : it.recipeList) {
|
||||
sb_recipe.append(" (" + it.itemid + ", " + rit[0] + ", " + rit[1] + "),\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
if(it.randomList != null) {
|
||||
for(int[] rit : it.randomList) {
|
||||
|
||||
if (it.randomList != null) {
|
||||
for (int[] rit : it.randomList) {
|
||||
sb_reward.append(" (" + it.itemid + ", " + rit[0] + ", " + rit[1] + ", " + rit[2] + "),\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sb_create.setLength(sb_create.length() - 3);
|
||||
sb_create.append(";\r\n");
|
||||
|
||||
|
||||
sb_recipe.setLength(sb_recipe.length() - 3);
|
||||
sb_recipe.append(";\r\n");
|
||||
|
||||
|
||||
sb_reward.setLength(sb_reward.length() - 3);
|
||||
sb_reward.append(";");
|
||||
|
||||
|
||||
printWriter.println(sb_create);
|
||||
printWriter.println(sb_recipe);
|
||||
printWriter.println(sb_reward);
|
||||
}
|
||||
|
||||
private static void WriteMakerTableData() {
|
||||
private static void writeMakerTableData() {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
resetMakerDataFields();
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
|
||||
WriteMakerTableFile();
|
||||
|
||||
printWriter.close();
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
catch(FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + fileName + "'");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
System.out.println("Error reading file '" + fileName + "'");
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + INPUT_FILE + "'");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + INPUT_FILE + "'");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
WriteMakerTableData();
|
||||
DatabaseConnection.initializeConnectionPool(); // Using MapleItemInformationProvider which loads som unrelated things from the db
|
||||
writeMakerTableData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,57 +1,31 @@
|
||||
/*
|
||||
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 mapleskillmakerreagentindexer;
|
||||
import provider.wz.WZFiles;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* The main objective of this program is to index relevant reagent data
|
||||
* from the Item.wz folder and generate a SQL table with them, to be used
|
||||
* by the server source.
|
||||
*
|
||||
*/
|
||||
public class MapleSkillMakerReagentIndexer {
|
||||
static String host = "jdbc:mysql://localhost:3306/cosmic";
|
||||
static String driver = "com.mysql.jdbc.Driver";
|
||||
static String username = "cosmic_server";
|
||||
static String password = "snailshell";
|
||||
public class SkillMakerReagentIndexer {
|
||||
private static final File INPUT_FILE = new File(WZFiles.ITEM.getFile(), "Etc/0425.img.xml");
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("maker-reagent-data.sql");
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final List<Pair<Integer, Pair<String, Integer>>> reagentList = new ArrayList<>();
|
||||
|
||||
static String fileName = "../../wz/Item.wz/Etc/0425.img.xml";
|
||||
static String newFile = "lib/MakerReagentData.sql";
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static byte status = 0;
|
||||
private static int id = -1;
|
||||
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
static byte status = 0;
|
||||
|
||||
static int id = -1;
|
||||
static List<Pair<Integer, Pair<String, Integer>>> reagentList = new ArrayList<>();
|
||||
|
||||
static int initialStringLength = 50;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -61,13 +35,13 @@ public class MapleSkillMakerReagentIndexer {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -77,140 +51,132 @@ public class MapleSkillMakerReagentIndexer {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
if(status == 1) { //getting id
|
||||
} else if (token.contains("imgdir")) {
|
||||
if (status == 1) { //getting id
|
||||
d = getName(token);
|
||||
id = Integer.parseInt(d);
|
||||
System.out.println("Parsing maker reagent id " + id);
|
||||
} else if(status == 2) {
|
||||
} else if (status == 2) {
|
||||
d = getName(token);
|
||||
if(!d.equals("info")) {
|
||||
if (!d.equals("info")) {
|
||||
System.out.println("not info");
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status += 1;
|
||||
} else {
|
||||
if(status == 3) {
|
||||
if(token.contains("int")) {
|
||||
if (status == 3) {
|
||||
if (token.contains("int")) {
|
||||
d = getName(token);
|
||||
|
||||
if(d.contains("inc") || d.contains("rand")) {
|
||||
|
||||
if (d.contains("inc") || d.contains("rand")) {
|
||||
Integer v = Integer.valueOf(getValue(token));
|
||||
Pair<String, Integer> reagBuff = new Pair<>(d, v);
|
||||
|
||||
|
||||
Pair<Integer, Pair<String, Integer>> reagItem = new Pair<>(id, reagBuff);
|
||||
reagentList.add(reagItem);
|
||||
}
|
||||
} else {
|
||||
if(token.contains("canvas")) {
|
||||
if (token.contains("canvas")) {
|
||||
forwardCursor(status + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void SortReagentList() {
|
||||
Collections.sort(reagentList, (p1, p2) -> p1.getLeft().compareTo(p2.getLeft()));
|
||||
reagentList.sort((p1, p2) -> p1.getLeft().compareTo(p2.getLeft()));
|
||||
}
|
||||
|
||||
|
||||
private static void WriteMakerReagentTableFile() {
|
||||
printWriter.println(" # SQL File autogenerated from the MapleSkillMakerReagentIndexer feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data is conformant with the Item.wz folder used to compile this.");
|
||||
printWriter.println();
|
||||
|
||||
|
||||
printWriter.println("CREATE TABLE IF NOT EXISTS `makerreagentdata` (");
|
||||
printWriter.println(" `itemid` int(11) NOT NULL,");
|
||||
printWriter.println(" `stat` varchar(20) NOT NULL,");
|
||||
printWriter.println(" `value` smallint(6) NOT NULL,");
|
||||
printWriter.println(" PRIMARY KEY (`itemid`)");
|
||||
printWriter.println(") ENGINE=MyISAM DEFAULT CHARSET=latin1;");
|
||||
printWriter.println(");");
|
||||
printWriter.println();
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder("INSERT IGNORE INTO `makerreagentdata` (`itemid`, `stat`, `value`) VALUES\r\n");
|
||||
|
||||
for(Pair<Integer, Pair<String, Integer>> it : reagentList) {
|
||||
|
||||
for (Pair<Integer, Pair<String, Integer>> it : reagentList) {
|
||||
sb.append(" (" + it.left + ", \"" + it.right.left + "\", " + it.right.right + "),\r\n");
|
||||
}
|
||||
|
||||
|
||||
sb.setLength(sb.length() - 3);
|
||||
sb.append(";");
|
||||
|
||||
|
||||
printWriter.println(sb);
|
||||
}
|
||||
|
||||
private static void WriteMakerReagentTableData() {
|
||||
private static void writeMakerReagentTableData() {
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
fileReader = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(INPUT_FILE), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
|
||||
|
||||
SortReagentList();
|
||||
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
WriteMakerReagentTableFile();
|
||||
printWriter.close();
|
||||
}
|
||||
|
||||
catch(FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + fileName + "'");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
System.out.println("Error reading file '" + fileName + "'");
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open file '" + OUTPUT_FILE + "'");
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + OUTPUT_FILE + "'");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
WriteMakerReagentTableData();
|
||||
writeMakerReagentTableData();
|
||||
}
|
||||
}
|
||||
@@ -1,94 +1,74 @@
|
||||
/*
|
||||
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 mapleskillbookchancefetcher;
|
||||
|
||||
import life.MapleLifeFactory;
|
||||
import life.MapleMonsterStats;
|
||||
import tools.DatabaseConnection;
|
||||
import server.life.MapleMonsterStats;
|
||||
import tools.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This application traces missing meso drop data on the underlying DB (that must be
|
||||
* defined on the DatabaseConnection file of this project) and generates a
|
||||
* SQL file that proposes missing drop entries for the drop_data table.
|
||||
*
|
||||
* <p>
|
||||
* The meso range is calculated accordingly with the target mob stats, such as level
|
||||
* and if it's a boss or not, similarly as how it has been done for the actual meso
|
||||
* drops.
|
||||
*
|
||||
*/
|
||||
public class MapleSkillbookChanceFetcher {
|
||||
public class SkillbookChanceFetcher {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("skillbook_drop_data.sql");
|
||||
private static final Map<Pair<Integer, Integer>, Integer> skillbookChances = new HashMap<>();
|
||||
|
||||
private static PrintWriter printWriter;
|
||||
private static String newFile = "lib/skillbook_drop_data.sql";
|
||||
|
||||
private static Map<Integer, MapleMonsterStats> mobStats;
|
||||
private static Map<Pair<Integer, Integer>, Integer> skillbookChances = new HashMap<>();
|
||||
|
||||
private static List<Entry<Pair<Integer, Integer>, Integer>> sortedSkillbookChances() {
|
||||
List<Entry<Pair<Integer, Integer>, Integer>> skillbookChancesList = new ArrayList<>(skillbookChances.entrySet());
|
||||
|
||||
Collections.sort(skillbookChancesList, (o1, o2) -> {
|
||||
|
||||
private static List<Map.Entry<Pair<Integer, Integer>, Integer>> sortedSkillbookChances() {
|
||||
List<Map.Entry<Pair<Integer, Integer>, Integer>> skillbookChancesList = new ArrayList<>(skillbookChances.entrySet());
|
||||
|
||||
skillbookChancesList.sort((o1, o2) -> {
|
||||
if (o1.getKey().getLeft().equals(o2.getKey().getLeft())) {
|
||||
return o1.getKey().getRight() < o2.getKey().getRight() ? -1 : (o1.getKey().getRight().equals(o2.getKey().getRight()) ? 0 : 1);
|
||||
}
|
||||
|
||||
return (o1.getKey().getLeft() < o2.getKey().getLeft()) ? -1 : 1;
|
||||
});
|
||||
|
||||
|
||||
return skillbookChancesList;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isLegendSkillUpgradeBook(int itemid) {
|
||||
int itemidBranch = itemid / 10000;
|
||||
return (itemidBranch == 228 && itemid >= 2280013 || itemidBranch == 229 && itemid >= 2290126); // drop rate of Legends are higher
|
||||
}
|
||||
|
||||
|
||||
private static void fetchSkillbookDropChances() {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
|
||||
Connection con = SimpleDatabaseConnection.getConnection();
|
||||
|
||||
try {
|
||||
PreparedStatement ps = con.prepareStatement("SELECT dropperid, itemid FROM drop_data WHERE itemid >= 2280000 AND itemid < 2300000");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
|
||||
while(rs.next()) {
|
||||
|
||||
while (rs.next()) {
|
||||
int mobid = rs.getInt("dropperid");
|
||||
int itemid = rs.getInt("itemid");
|
||||
|
||||
|
||||
int expectedChance = 250;
|
||||
|
||||
|
||||
if (mobStats.get(mobid) != null) {
|
||||
int level = mobStats.get(mobid).getLevel();
|
||||
expectedChance *= Math.max(2, (level - 80) / 15);
|
||||
|
||||
|
||||
if (mobStats.get(mobid).isBoss()) {
|
||||
expectedChance *= 20;
|
||||
} else {
|
||||
@@ -97,53 +77,52 @@ public class MapleSkillbookChanceFetcher {
|
||||
} else {
|
||||
expectedChance = 1287;
|
||||
}
|
||||
|
||||
|
||||
if (isLegendSkillUpgradeBook(itemid)) { // drop rate of Legends seems to be higher than explorers, in retrospect from values in DB
|
||||
expectedChance *= 3;
|
||||
}
|
||||
|
||||
|
||||
skillbookChances.put(new Pair<>(mobid, itemid), expectedChance);
|
||||
}
|
||||
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printSkillbookChanceUpdateSqlHeader() {
|
||||
printWriter.println(" # SQL File autogenerated from the MapleSkillbookChanceFetcher feature by Ronan Lana.");
|
||||
printWriter.println(" # Generated data takes into account mob stats such as level and boss for the chance rates.");
|
||||
printWriter.println();
|
||||
|
||||
|
||||
printWriter.println(" REPLACE INTO drop_data (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`) VALUES");
|
||||
}
|
||||
|
||||
|
||||
private static void generateSkillbookChanceUpdateFile() {
|
||||
try {
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
|
||||
printSkillbookChanceUpdateSqlHeader();
|
||||
|
||||
List<Entry<Pair<Integer, Integer>, Integer>> skillbookChancesList = sortedSkillbookChances();
|
||||
for (Entry<Pair<Integer, Integer>, Integer> e : skillbookChancesList) {
|
||||
|
||||
List<Map.Entry<Pair<Integer, Integer>, Integer>> skillbookChancesList = sortedSkillbookChances();
|
||||
for (Map.Entry<Pair<Integer, Integer>, Integer> e : skillbookChancesList) {
|
||||
printWriter.println("(" + e.getKey().getLeft() + ", " + e.getKey().getRight() + ", 1, 1, 0, " + e.getValue() + "),");
|
||||
}
|
||||
|
||||
|
||||
printWriter.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// load mob stats from WZ
|
||||
mobStats = MapleLifeFactory.getAllMonsterStats();
|
||||
|
||||
mobStats = MonsterStatFetcher.getAllMonsterStats();
|
||||
|
||||
fetchSkillbookDropChances();
|
||||
generateSkillbookChanceUpdateFile();
|
||||
}
|
||||
|
||||
}
|
||||
157
src/main/java/tools/mapletools/SkillbookStackUpdate.java
Normal file
157
src/main/java/tools/mapletools/SkillbookStackUpdate.java
Normal file
@@ -0,0 +1,157 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import provider.wz.WZFiles;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author RonanLana
|
||||
* <p>
|
||||
* This application parses skillbook XMLs, filling up stack amount of those
|
||||
* items to 100 (eliminating limitations on held skillbooks, now using
|
||||
* default stack quantity expected from USE items).
|
||||
* <p>
|
||||
* Estimated parse time: 10 seconds
|
||||
*/
|
||||
public class SkillbookStackUpdate {
|
||||
private static final File INPUT_DIRECTORY = new File(WZFiles.ITEM.getFile(), "Consume");
|
||||
private static final File OUTPUT_DIRECTORY = ToolConstants.getOutputFile("skillbook-update");
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static int status = 0;
|
||||
|
||||
private static boolean isSkillMasteryBook(int itemid) {
|
||||
return itemid >= 2280000 && itemid < 2300000;
|
||||
}
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("name");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
if (j < i) {
|
||||
return "0"; //node value containing 'name' in it's scope, cheap fix since we don't deal with strings anyway
|
||||
}
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
String d;
|
||||
|
||||
i = token.lastIndexOf("value");
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
printWriter.println(token);
|
||||
}
|
||||
|
||||
private static void translateItemToken(String token) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
if (status == 2) { //itemid
|
||||
int itemid = Integer.parseInt(getName(token));
|
||||
|
||||
if (!isSkillMasteryBook(itemid)) {
|
||||
printWriter.println(token);
|
||||
forwardCursor(status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (status == 3) {
|
||||
if (getName(token).contentEquals("slotMax")) {
|
||||
printWriter.println(" <int name=\"slotMax\" value=\"100\"/>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printWriter.println(token);
|
||||
}
|
||||
|
||||
private static void parseItemFile(File file, File outputFile) {
|
||||
setupDirectories(outputFile);
|
||||
// This will reference one line at a time
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
printWriter = new PrintWriter(outputFile);
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateItemToken(line);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
printWriter.close();
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading file '" + file.getName() + "'");
|
||||
ex.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void setupDirectories(File file) {
|
||||
if (!file.getParentFile().exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseItemDirectory(File inputDirectory, File outputDirectory) {
|
||||
for (File f : inputDirectory.listFiles()) {
|
||||
parseItemFile(f, new File(outputDirectory, f.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Reading item files...");
|
||||
parseItemDirectory(INPUT_DIRECTORY, OUTPUT_DIRECTORY);
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
}
|
||||
18
src/main/java/tools/mapletools/ToolConstants.java
Normal file
18
src/main/java/tools/mapletools/ToolConstants.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package tools.mapletools;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
class ToolConstants {
|
||||
static final File INPUT_DIRECTORY = new File("tools/input");
|
||||
static final File OUTPUT_DIRECTORY = new File("tools/output");
|
||||
static final String SCRIPTS_PATH = "scripts";
|
||||
static final String HANDBOOK_PATH = "handbook";
|
||||
|
||||
static File getInputFile(String fileName) {
|
||||
return new File(INPUT_DIRECTORY, fileName);
|
||||
}
|
||||
|
||||
static File getOutputFile(String fileName) {
|
||||
return new File(OUTPUT_DIRECTORY, fileName);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,32 @@
|
||||
/*
|
||||
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 mapleworldmapchecker;
|
||||
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 Map.wz file inputted and reports areas (mapids) that are supposed to be referenced
|
||||
throughout the map tree (area map -> continent map -> world map) but are currently missing.
|
||||
|
||||
* <p>
|
||||
* This application parses the Map.wz file inputted and reports areas (mapids) that are supposed to be referenced
|
||||
* throughout the map tree (area map -> continent map -> world map) but are currently missing.
|
||||
*/
|
||||
public class MapleWorldmapChecker {
|
||||
|
||||
static String newFile = "lib/Report.txt";
|
||||
static PrintWriter printWriter = null;
|
||||
static InputStreamReader fileReader = null;
|
||||
static BufferedReader bufferedReader = null;
|
||||
|
||||
static String worldmapPath = "../../wz/Map.wz/WorldMap";
|
||||
static int initialStringLength = 50;
|
||||
|
||||
static Map<String, Set<Integer>> worldMapids = new HashMap<>();
|
||||
static Map<String, String> parentWorldmaps = new HashMap<>();
|
||||
static Set<String> rootWorldmaps = new HashSet<>();
|
||||
//static String rootWorldmap = "";
|
||||
|
||||
static Set<Integer> currentWorldMapids;
|
||||
static String currentParent;
|
||||
|
||||
static byte status = 0;
|
||||
static boolean isInfo;
|
||||
|
||||
public class WorldmapChecker {
|
||||
private static final File OUTPUT_FILE = ToolConstants.getOutputFile("worldmap_report.txt");
|
||||
private static final int INITIAL_STRING_LENGTH = 50;
|
||||
private static final Map<String, Set<Integer>> worldMapids = new HashMap<>();
|
||||
private static final Map<String, String> parentWorldmaps = new HashMap<>();
|
||||
private static final Set<String> rootWorldmaps = new HashSet<>();
|
||||
|
||||
private static PrintWriter printWriter = null;
|
||||
private static BufferedReader bufferedReader = null;
|
||||
private static Set<Integer> currentWorldMapids;
|
||||
private static String currentParent;
|
||||
private static byte status = 0;
|
||||
private static boolean isInfo;
|
||||
|
||||
private static String getName(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -61,13 +36,13 @@ public class MapleWorldmapChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static String getValue(String token) {
|
||||
int i, j;
|
||||
char[] dest;
|
||||
@@ -77,68 +52,57 @@ public class MapleWorldmapChecker {
|
||||
i = token.indexOf("\"", i) + 1; //lower bound of the string
|
||||
j = token.indexOf("\"", i); //upper bound
|
||||
|
||||
dest = new char[initialStringLength];
|
||||
dest = new char[INITIAL_STRING_LENGTH];
|
||||
token.getChars(i, j, dest, 0);
|
||||
|
||||
d = new String(dest);
|
||||
return(d.trim());
|
||||
return (d.trim());
|
||||
}
|
||||
|
||||
|
||||
private static void forwardCursor(int st) {
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
while(status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
while (status >= st && (line = bufferedReader.readLine()) != null) {
|
||||
simpleToken(line);
|
||||
}
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void simpleToken(String token) {
|
||||
if(token.contains("/imgdir")) {
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void translateToken(String token) {
|
||||
String d;
|
||||
|
||||
if(token.contains("/imgdir")) {
|
||||
|
||||
if (token.contains("/imgdir")) {
|
||||
status -= 1;
|
||||
}
|
||||
else if(token.contains("imgdir")) {
|
||||
} else if (token.contains("imgdir")) {
|
||||
status += 1;
|
||||
|
||||
|
||||
if (status == 2) {
|
||||
d = getName(token);
|
||||
|
||||
|
||||
switch (d) {
|
||||
case "MapList":
|
||||
isInfo = false;
|
||||
break;
|
||||
|
||||
case "info":
|
||||
isInfo = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
forwardCursor(status);
|
||||
case "MapList" -> isInfo = false;
|
||||
case "info" -> isInfo = true;
|
||||
default -> forwardCursor(status);
|
||||
}
|
||||
} else if (status == 4) {
|
||||
d = getName(token);
|
||||
|
||||
|
||||
if (!d.contentEquals("mapNo")) {
|
||||
forwardCursor(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (status == 4) {
|
||||
currentWorldMapids.add(Integer.valueOf(getValue(token)));
|
||||
} else if (status == 2 && isInfo) {
|
||||
@@ -151,64 +115,63 @@ public class MapleWorldmapChecker {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("failed '" + token + "'");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void parseWorldmapFile(File worldmapFile) throws IOException {
|
||||
String line;
|
||||
|
||||
fileReader = new InputStreamReader(new FileInputStream(worldmapFile), "UTF-8");
|
||||
|
||||
InputStreamReader fileReader = new InputStreamReader(new FileInputStream(worldmapFile), StandardCharsets.UTF_8);
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
|
||||
currentParent = "";
|
||||
status = 0;
|
||||
|
||||
|
||||
currentWorldMapids = new HashSet<>();
|
||||
while((line = bufferedReader.readLine()) != null) {
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
translateToken(line);
|
||||
}
|
||||
|
||||
|
||||
String worldmapName = worldmapFile.getName();
|
||||
worldMapids.put(worldmapName, currentWorldMapids);
|
||||
|
||||
if (!currentParent.isEmpty()) parentWorldmaps.put(worldmapName, currentParent);
|
||||
else rootWorldmaps.add(worldmapName);
|
||||
|
||||
if (!currentParent.isEmpty()) {
|
||||
parentWorldmaps.put(worldmapName, currentParent);
|
||||
} else {
|
||||
rootWorldmaps.add(worldmapName);
|
||||
}
|
||||
|
||||
bufferedReader.close();
|
||||
fileReader.close();
|
||||
}
|
||||
|
||||
|
||||
private static void parseWorldmapDirectory() {
|
||||
System.out.println("Parsing directory '" + worldmapPath + "'");
|
||||
File folder = new File(worldmapPath);
|
||||
File folder = new File(WZFiles.MAP.getFilePath(), "WorldMap");
|
||||
System.out.println("Parsing directory '" + folder.getPath() + "'");
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.isFile()) {
|
||||
try {
|
||||
parseWorldmapFile(file);
|
||||
}
|
||||
catch(FileNotFoundException ex) {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.out.println("Unable to open worldmap file " + file.getAbsolutePath() + ".");
|
||||
}
|
||||
catch(IOException ex) {
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Error reading worldmap file " + file.getAbsolutePath() + ".");
|
||||
}
|
||||
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printReportFileHeader() {
|
||||
printWriter.println(" # Report File autogenerated from the MapleWorldmapChecker 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(List<Pair<String, List<Pair<Integer, String>>>> results) {
|
||||
printWriter.println("Missing mapid references in top hierarchy:\n");
|
||||
for (Pair<String, List<Pair<Integer, String>>> res : results) {
|
||||
@@ -221,32 +184,32 @@ public class MapleWorldmapChecker {
|
||||
printWriter.println("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void verifyWorldmapTreeMapids() {
|
||||
try {
|
||||
printWriter = new PrintWriter(newFile, "UTF-8");
|
||||
printWriter = new PrintWriter(OUTPUT_FILE, StandardCharsets.UTF_8);
|
||||
printReportFileHeader();
|
||||
|
||||
|
||||
if (rootWorldmaps.size() > 1) {
|
||||
printWriter.println("[WARNING] Detected several root worldmaps: " + rootWorldmaps + "\n");
|
||||
}
|
||||
|
||||
|
||||
Set<String> worldmaps = new HashSet<>(parentWorldmaps.keySet());
|
||||
worldmaps.addAll(rootWorldmaps);
|
||||
|
||||
|
||||
Map<String, Set<Integer>> tempMapids = new HashMap<>(worldMapids.size());
|
||||
for (Entry<String, Set<Integer>> e : worldMapids.entrySet()) {
|
||||
for (Map.Entry<String, Set<Integer>> e : worldMapids.entrySet()) {
|
||||
tempMapids.put(e.getKey(), new HashSet<>(e.getValue()));
|
||||
}
|
||||
|
||||
|
||||
Map<String, List<Pair<Integer, String>>> unreferencedMapids = new HashMap<>();
|
||||
|
||||
|
||||
for (String s : worldmaps) {
|
||||
List<Pair<Integer, String>> currentUnreferencedMapids = new ArrayList<>();
|
||||
|
||||
for (Integer i : tempMapids.get(s)) {
|
||||
String parent = parentWorldmaps.get(s);
|
||||
|
||||
|
||||
while (parent != null) {
|
||||
Set<Integer> mapids = worldMapids.get(parent);
|
||||
if (!mapids.contains(i)) {
|
||||
@@ -255,39 +218,39 @@ public class MapleWorldmapChecker {
|
||||
} else {
|
||||
tempMapids.get(parent).remove(i);
|
||||
}
|
||||
|
||||
|
||||
parent = parentWorldmaps.get(parent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!currentUnreferencedMapids.isEmpty()) {
|
||||
unreferencedMapids.put(s, currentUnreferencedMapids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!unreferencedMapids.isEmpty()) {
|
||||
List<Pair<String, List<Pair<Integer, String>>>> unreferencedEntries = new ArrayList<>(20);
|
||||
for (Entry<String, List<Pair<Integer, String>>> e : unreferencedMapids.entrySet()) {
|
||||
for (Map.Entry<String, List<Pair<Integer, String>>> e : unreferencedMapids.entrySet()) {
|
||||
List<Pair<Integer, String>> list = new ArrayList<>(e.getValue());
|
||||
Collections.sort(list, (o1, o2) -> o1.getLeft().compareTo(o2.getLeft()));
|
||||
list.sort((o1, o2) -> o1.getLeft().compareTo(o2.getLeft()));
|
||||
|
||||
unreferencedEntries.add(new Pair<>(e.getKey(), list));
|
||||
}
|
||||
|
||||
Collections.sort(unreferencedEntries, (o1, o2) -> o1.getLeft().compareTo(o2.getLeft()));
|
||||
|
||||
unreferencedEntries.sort((o1, o2) -> o1.getLeft().compareTo(o2.getLeft()));
|
||||
|
||||
printReportFileResults(unreferencedEntries);
|
||||
}
|
||||
|
||||
|
||||
printWriter.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
parseWorldmapDirectory();
|
||||
verifyWorldmapTreeMapids();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,766 +0,0 @@
|
||||
# SQL File autogenerated from the MapleArrowFetcher feature by Ronan Lana.
|
||||
# Generated data takes into account mob stats such as level and boss for the raw arrow ranges.
|
||||
# Only current arrows entries on the DB it was compiled are being updated here.
|
||||
|
||||
UPDATE drop_data
|
||||
SET minimum_quantity = CASE
|
||||
WHEN dropperid = 100100 AND itemid = 2060000 THEN 1
|
||||
WHEN dropperid = 100100 AND itemid = 2061000 THEN 1
|
||||
WHEN dropperid = 100101 AND itemid = 2060000 THEN 2
|
||||
WHEN dropperid = 100101 AND itemid = 2061000 THEN 2
|
||||
WHEN dropperid = 100120 AND itemid = 2060000 THEN 1
|
||||
WHEN dropperid = 100120 AND itemid = 2061000 THEN 1
|
||||
WHEN dropperid = 100121 AND itemid = 2060000 THEN 4
|
||||
WHEN dropperid = 100123 AND itemid = 2061000 THEN 9
|
||||
WHEN dropperid = 100124 AND itemid = 2060000 THEN 11
|
||||
WHEN dropperid = 100124 AND itemid = 2061000 THEN 11
|
||||
WHEN dropperid = 120100 AND itemid = 2060000 THEN 2
|
||||
WHEN dropperid = 120100 AND itemid = 2061000 THEN 2
|
||||
WHEN dropperid = 130100 AND itemid = 2060000 THEN 5
|
||||
WHEN dropperid = 130100 AND itemid = 2061000 THEN 5
|
||||
WHEN dropperid = 130101 AND itemid = 2060000 THEN 5
|
||||
WHEN dropperid = 130101 AND itemid = 2061000 THEN 5
|
||||
WHEN dropperid = 210100 AND itemid = 2060000 THEN 7
|
||||
WHEN dropperid = 210100 AND itemid = 2061000 THEN 7
|
||||
WHEN dropperid = 1110100 AND itemid = 2060000 THEN 19
|
||||
WHEN dropperid = 1110100 AND itemid = 2061000 THEN 19
|
||||
WHEN dropperid = 1110101 AND itemid = 2060000 THEN 13
|
||||
WHEN dropperid = 1110101 AND itemid = 2061000 THEN 13
|
||||
WHEN dropperid = 1110130 AND itemid = 2060000 THEN 19
|
||||
WHEN dropperid = 1110130 AND itemid = 2061000 THEN 19
|
||||
WHEN dropperid = 1120100 AND itemid = 2060000 THEN 15
|
||||
WHEN dropperid = 1120100 AND itemid = 2061000 THEN 15
|
||||
WHEN dropperid = 1130100 AND itemid = 2060000 THEN 22
|
||||
WHEN dropperid = 1130100 AND itemid = 2061000 THEN 22
|
||||
WHEN dropperid = 1140100 AND itemid = 2060000 THEN 24
|
||||
WHEN dropperid = 1140100 AND itemid = 2061000 THEN 24
|
||||
WHEN dropperid = 1140130 AND itemid = 2060000 THEN 24
|
||||
WHEN dropperid = 1140130 AND itemid = 2061000 THEN 24
|
||||
WHEN dropperid = 1210100 AND itemid = 2060000 THEN 9
|
||||
WHEN dropperid = 1210100 AND itemid = 2061000 THEN 9
|
||||
WHEN dropperid = 1210101 AND itemid = 2060000 THEN 13
|
||||
WHEN dropperid = 1210101 AND itemid = 2061000 THEN 13
|
||||
WHEN dropperid = 1210102 AND itemid = 2060000 THEN 10
|
||||
WHEN dropperid = 1210102 AND itemid = 2061000 THEN 10
|
||||
WHEN dropperid = 1210103 AND itemid = 2060000 THEN 19
|
||||
WHEN dropperid = 1210103 AND itemid = 2061000 THEN 19
|
||||
WHEN dropperid = 2100100 AND itemid = 2060000 THEN 26
|
||||
WHEN dropperid = 2100100 AND itemid = 2061000 THEN 26
|
||||
WHEN dropperid = 2100101 AND itemid = 2060000 THEN 27
|
||||
WHEN dropperid = 2100101 AND itemid = 2061000 THEN 27
|
||||
WHEN dropperid = 2100102 AND itemid = 2060000 THEN 28
|
||||
WHEN dropperid = 2100102 AND itemid = 2061000 THEN 28
|
||||
WHEN dropperid = 2100103 AND itemid = 2060000 THEN 32
|
||||
WHEN dropperid = 2100103 AND itemid = 2061000 THEN 32
|
||||
WHEN dropperid = 2100104 AND itemid = 2060000 THEN 36
|
||||
WHEN dropperid = 2100104 AND itemid = 2061000 THEN 36
|
||||
WHEN dropperid = 2100105 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 2100105 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 2100106 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 2100106 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 2100107 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 2100107 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 2100108 AND itemid = 2060000 THEN 37
|
||||
WHEN dropperid = 2100108 AND itemid = 2061000 THEN 37
|
||||
WHEN dropperid = 2110200 AND itemid = 2060000 THEN 28
|
||||
WHEN dropperid = 2110200 AND itemid = 2061000 THEN 28
|
||||
WHEN dropperid = 2110300 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 2110300 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 2110301 AND itemid = 2060000 THEN 37
|
||||
WHEN dropperid = 2110301 AND itemid = 2061000 THEN 37
|
||||
WHEN dropperid = 2130100 AND itemid = 2060000 THEN 28
|
||||
WHEN dropperid = 2130100 AND itemid = 2061000 THEN 28
|
||||
WHEN dropperid = 2220000 AND itemid = 2060000 THEN 36
|
||||
WHEN dropperid = 2220000 AND itemid = 2061000 THEN 36
|
||||
WHEN dropperid = 2220100 AND itemid = 2060000 THEN 26
|
||||
WHEN dropperid = 2220100 AND itemid = 2061000 THEN 26
|
||||
WHEN dropperid = 2230100 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 2230100 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 2230101 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 2230101 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 2230102 AND itemid = 2060000 THEN 32
|
||||
WHEN dropperid = 2230102 AND itemid = 2061000 THEN 32
|
||||
WHEN dropperid = 2230103 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 2230103 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 2230104 AND itemid = 2060000 THEN 36
|
||||
WHEN dropperid = 2230104 AND itemid = 2061000 THEN 36
|
||||
WHEN dropperid = 2230105 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 2230105 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 2230106 AND itemid = 2060000 THEN 32
|
||||
WHEN dropperid = 2230106 AND itemid = 2061000 THEN 32
|
||||
WHEN dropperid = 2230107 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 2230107 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 2230108 AND itemid = 2060000 THEN 28
|
||||
WHEN dropperid = 2230108 AND itemid = 2061000 THEN 28
|
||||
WHEN dropperid = 2230109 AND itemid = 2060000 THEN 36
|
||||
WHEN dropperid = 2230109 AND itemid = 2061000 THEN 36
|
||||
WHEN dropperid = 2230110 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 2230110 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 2230111 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 2230111 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 2230131 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 2230131 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 2230200 AND itemid = 2060000 THEN 37
|
||||
WHEN dropperid = 2230200 AND itemid = 2061000 THEN 37
|
||||
WHEN dropperid = 2300100 AND itemid = 2060000 THEN 26
|
||||
WHEN dropperid = 2300100 AND itemid = 2061000 THEN 26
|
||||
WHEN dropperid = 3000000 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3000000 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3000005 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3000005 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3000006 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3000006 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3100101 AND itemid = 2060000 THEN 41
|
||||
WHEN dropperid = 3100101 AND itemid = 2061000 THEN 41
|
||||
WHEN dropperid = 3100102 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3100102 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3110101 AND itemid = 2060000 THEN 41
|
||||
WHEN dropperid = 3110101 AND itemid = 2061000 THEN 41
|
||||
WHEN dropperid = 3110102 AND itemid = 2060000 THEN 41
|
||||
WHEN dropperid = 3110102 AND itemid = 2061000 THEN 41
|
||||
WHEN dropperid = 3110300 AND itemid = 2060000 THEN 41
|
||||
WHEN dropperid = 3110300 AND itemid = 2061000 THEN 41
|
||||
WHEN dropperid = 3110301 AND itemid = 2060000 THEN 41
|
||||
WHEN dropperid = 3110301 AND itemid = 2061000 THEN 41
|
||||
WHEN dropperid = 3110302 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 3110302 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 3110303 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3110303 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3210100 AND itemid = 2060005 THEN 6
|
||||
WHEN dropperid = 3210203 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 3210203 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 3210204 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 3210204 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 3210205 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 3210205 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 3210206 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 3210206 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 3210207 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 3210207 AND itemid = 2060005 THEN 7
|
||||
WHEN dropperid = 3210207 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 3210208 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 3210208 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 3210450 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 3210450 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 3210800 AND itemid = 2060005 THEN 8
|
||||
WHEN dropperid = 3220000 AND itemid = 2060000 THEN 63
|
||||
WHEN dropperid = 3220000 AND itemid = 2061000 THEN 63
|
||||
WHEN dropperid = 3230100 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 3230100 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 3230103 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3230103 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3230200 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 3230200 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 3230302 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 3230302 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 3230303 AND itemid = 2060000 THEN 48
|
||||
WHEN dropperid = 3230303 AND itemid = 2061000 THEN 48
|
||||
WHEN dropperid = 3230304 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3230304 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3230305 AND itemid = 2060000 THEN 51
|
||||
WHEN dropperid = 3230305 AND itemid = 2061000 THEN 51
|
||||
WHEN dropperid = 3230306 AND itemid = 2060000 THEN 48
|
||||
WHEN dropperid = 3230306 AND itemid = 2061000 THEN 48
|
||||
WHEN dropperid = 3230307 AND itemid = 2060000 THEN 40
|
||||
WHEN dropperid = 3230307 AND itemid = 2061000 THEN 40
|
||||
WHEN dropperid = 3230308 AND itemid = 2060000 THEN 51
|
||||
WHEN dropperid = 3230308 AND itemid = 2061000 THEN 51
|
||||
WHEN dropperid = 3230400 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3230400 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3230405 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3230405 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3300000 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3300000 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3300001 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 3300001 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 3300002 AND itemid = 2060000 THEN 40
|
||||
WHEN dropperid = 3300002 AND itemid = 2061000 THEN 40
|
||||
WHEN dropperid = 3300003 AND itemid = 2060000 THEN 41
|
||||
WHEN dropperid = 3300003 AND itemid = 2061000 THEN 41
|
||||
WHEN dropperid = 3300004 AND itemid = 2060000 THEN 43
|
||||
WHEN dropperid = 3300004 AND itemid = 2061000 THEN 43
|
||||
WHEN dropperid = 3300006 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 3300006 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 3300007 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 3300007 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 3300008 AND itemid = 2060000 THEN 69
|
||||
WHEN dropperid = 3300008 AND itemid = 2061000 THEN 69
|
||||
WHEN dropperid = 4110300 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 4110300 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 4110301 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4110301 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4130103 AND itemid = 2060000 THEN 85
|
||||
WHEN dropperid = 4130103 AND itemid = 2061000 THEN 85
|
||||
WHEN dropperid = 4230103 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 4230103 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 4230106 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230106 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230108 AND itemid = 2060000 THEN 56
|
||||
WHEN dropperid = 4230108 AND itemid = 2061000 THEN 56
|
||||
WHEN dropperid = 4230109 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 4230109 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 4230110 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230110 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230111 AND itemid = 2060000 THEN 53
|
||||
WHEN dropperid = 4230111 AND itemid = 2061000 THEN 53
|
||||
WHEN dropperid = 4230112 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 4230112 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 4230113 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 4230113 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 4230114 AND itemid = 2060000 THEN 53
|
||||
WHEN dropperid = 4230114 AND itemid = 2061000 THEN 53
|
||||
WHEN dropperid = 4230115 AND itemid = 2060000 THEN 60
|
||||
WHEN dropperid = 4230115 AND itemid = 2061000 THEN 60
|
||||
WHEN dropperid = 4230116 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 4230116 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 4230117 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 4230117 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 4230118 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230118 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230119 AND itemid = 2060000 THEN 53
|
||||
WHEN dropperid = 4230119 AND itemid = 2061000 THEN 53
|
||||
WHEN dropperid = 4230120 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 4230120 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 4230121 AND itemid = 2060000 THEN 60
|
||||
WHEN dropperid = 4230121 AND itemid = 2061000 THEN 60
|
||||
WHEN dropperid = 4230123 AND itemid = 2060000 THEN 56
|
||||
WHEN dropperid = 4230123 AND itemid = 2061000 THEN 56
|
||||
WHEN dropperid = 4230124 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 4230124 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 4230125 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 4230125 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 4230126 AND itemid = 2060000 THEN 61
|
||||
WHEN dropperid = 4230126 AND itemid = 2061000 THEN 61
|
||||
WHEN dropperid = 4230201 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 4230201 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 4230300 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230300 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230400 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230400 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230500 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 4230500 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 4230501 AND itemid = 2060000 THEN 53
|
||||
WHEN dropperid = 4230501 AND itemid = 2061000 THEN 53
|
||||
WHEN dropperid = 4230502 AND itemid = 2060000 THEN 56
|
||||
WHEN dropperid = 4230502 AND itemid = 2061000 THEN 56
|
||||
WHEN dropperid = 4230503 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230503 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230504 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 4230504 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 4230600 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 4230600 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 4240000 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 4240000 AND itemid = 2061000 THEN 64
|
||||
WHEN dropperid = 5120100 AND itemid = 2060000 THEN 98
|
||||
WHEN dropperid = 5120100 AND itemid = 2061000 THEN 98
|
||||
WHEN dropperid = 5130104 AND itemid = 2060000 THEN 71
|
||||
WHEN dropperid = 5130104 AND itemid = 2061000 THEN 71
|
||||
WHEN dropperid = 5140000 AND itemid = 2060000 THEN 75
|
||||
WHEN dropperid = 5140000 AND itemid = 2061000 THEN 75
|
||||
WHEN dropperid = 5150000 AND itemid = 2060000 THEN 77
|
||||
WHEN dropperid = 5150000 AND itemid = 2061000 THEN 77
|
||||
WHEN dropperid = 5200000 AND itemid = 2060001 THEN 15
|
||||
WHEN dropperid = 5200000 AND itemid = 2061001 THEN 15
|
||||
WHEN dropperid = 5200001 AND itemid = 2060001 THEN 19
|
||||
WHEN dropperid = 5200001 AND itemid = 2061001 THEN 19
|
||||
WHEN dropperid = 5200002 AND itemid = 2060001 THEN 19
|
||||
WHEN dropperid = 5200002 AND itemid = 2061001 THEN 19
|
||||
WHEN dropperid = 5220000 AND itemid = 2060000 THEN 100
|
||||
WHEN dropperid = 5220000 AND itemid = 2061000 THEN 100
|
||||
WHEN dropperid = 5220002 AND itemid = 2060000 THEN 91
|
||||
WHEN dropperid = 5220002 AND itemid = 2061000 THEN 91
|
||||
WHEN dropperid = 5220003 AND itemid = 2060000 THEN 107
|
||||
WHEN dropperid = 5220003 AND itemid = 2061000 THEN 107
|
||||
WHEN dropperid = 5400000 AND itemid = 2060001 THEN 22
|
||||
WHEN dropperid = 5400000 AND itemid = 2061001 THEN 22
|
||||
WHEN dropperid = 6220000 AND itemid = 2060000 THEN 118
|
||||
WHEN dropperid = 6220000 AND itemid = 2061000 THEN 118
|
||||
WHEN dropperid = 7120103 AND itemid = 2060003 THEN 22
|
||||
WHEN dropperid = 7220000 AND itemid = 2060001 THEN 64
|
||||
WHEN dropperid = 7220000 AND itemid = 2061001 THEN 64
|
||||
WHEN dropperid = 7220001 AND itemid = 2060001 THEN 63
|
||||
WHEN dropperid = 7220001 AND itemid = 2061001 THEN 63
|
||||
WHEN dropperid = 7220002 AND itemid = 2060001 THEN 70
|
||||
WHEN dropperid = 7220002 AND itemid = 2061001 THEN 70
|
||||
WHEN dropperid = 8220000 AND itemid = 2060001 THEN 75
|
||||
WHEN dropperid = 8220000 AND itemid = 2061001 THEN 75
|
||||
WHEN dropperid = 8220001 AND itemid = 2060001 THEN 82
|
||||
WHEN dropperid = 8220001 AND itemid = 2061001 THEN 82
|
||||
WHEN dropperid = 9300011 AND itemid = 2060000 THEN 51
|
||||
WHEN dropperid = 9300011 AND itemid = 2061000 THEN 51
|
||||
WHEN dropperid = 9300060 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 9300060 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 9300131 AND itemid = 2060000 THEN 51
|
||||
WHEN dropperid = 9300131 AND itemid = 2061000 THEN 51
|
||||
WHEN dropperid = 9300132 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 9300132 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 9300133 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 9300160 AND itemid = 2060000 THEN 82
|
||||
WHEN dropperid = 9300160 AND itemid = 2061000 THEN 82
|
||||
WHEN dropperid = 9300161 AND itemid = 2060000 THEN 82
|
||||
WHEN dropperid = 9300161 AND itemid = 2061000 THEN 82
|
||||
WHEN dropperid = 9300274 AND itemid = 2060000 THEN 10
|
||||
WHEN dropperid = 9300274 AND itemid = 2061000 THEN 10
|
||||
WHEN dropperid = 9300332 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 9300334 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 9300341 AND itemid = 2060000 THEN 7
|
||||
WHEN dropperid = 9300341 AND itemid = 2061000 THEN 7
|
||||
WHEN dropperid = 9300342 AND itemid = 2060000 THEN 10
|
||||
WHEN dropperid = 9300342 AND itemid = 2061000 THEN 10
|
||||
WHEN dropperid = 9300343 AND itemid = 2060000 THEN 9
|
||||
WHEN dropperid = 9300343 AND itemid = 2061000 THEN 9
|
||||
WHEN dropperid = 9303005 AND itemid = 2060001 THEN 17
|
||||
WHEN dropperid = 9303005 AND itemid = 2061001 THEN 17
|
||||
WHEN dropperid = 9303008 AND itemid = 2060001 THEN 17
|
||||
WHEN dropperid = 9303008 AND itemid = 2061001 THEN 17
|
||||
WHEN dropperid = 9303009 AND itemid = 2060001 THEN 33
|
||||
WHEN dropperid = 9303009 AND itemid = 2061001 THEN 33
|
||||
WHEN dropperid = 9400000 AND itemid = 2060001 THEN 16
|
||||
WHEN dropperid = 9400009 AND itemid = 2060001 THEN 130
|
||||
WHEN dropperid = 9400011 AND itemid = 2060002 THEN 17
|
||||
WHEN dropperid = 9400100 AND itemid = 2060003 THEN 14
|
||||
WHEN dropperid = 9400101 AND itemid = 2061003 THEN 15
|
||||
WHEN dropperid = 9400204 AND itemid = 2060003 THEN 17
|
||||
WHEN dropperid = 9400239 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 9400239 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 9400244 AND itemid = 2060000 THEN 77
|
||||
WHEN dropperid = 9400244 AND itemid = 2061000 THEN 77
|
||||
WHEN dropperid = 9400248 AND itemid = 2060000 THEN 31
|
||||
WHEN dropperid = 9400248 AND itemid = 2061000 THEN 31
|
||||
WHEN dropperid = 9400540 AND itemid = 2060004 THEN 6
|
||||
WHEN dropperid = 9400540 AND itemid = 2061004 THEN 6
|
||||
WHEN dropperid = 9400541 AND itemid = 2060004 THEN 6
|
||||
WHEN dropperid = 9400541 AND itemid = 2061004 THEN 6
|
||||
WHEN dropperid = 9400542 AND itemid = 2060004 THEN 9
|
||||
WHEN dropperid = 9400542 AND itemid = 2061004 THEN 9
|
||||
WHEN dropperid = 9400543 AND itemid = 2060004 THEN 10
|
||||
WHEN dropperid = 9400543 AND itemid = 2061004 THEN 10
|
||||
WHEN dropperid = 9400547 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 9400547 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 9400548 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 9400548 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 9400550 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 9400550 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 9400558 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 9400558 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 9400563 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 9400563 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 9400638 AND itemid = 2060000 THEN 26
|
||||
WHEN dropperid = 9400638 AND itemid = 2061000 THEN 26
|
||||
WHEN dropperid = 9420500 AND itemid = 2060000 THEN 36
|
||||
WHEN dropperid = 9420500 AND itemid = 2061000 THEN 36
|
||||
WHEN dropperid = 9420502 AND itemid = 2060000 THEN 23
|
||||
WHEN dropperid = 9420502 AND itemid = 2061000 THEN 23
|
||||
WHEN dropperid = 9420506 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 9420506 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 9420508 AND itemid = 2060000 THEN 56
|
||||
WHEN dropperid = 9420508 AND itemid = 2061000 THEN 56
|
||||
WHEN dropperid = 9420527 AND itemid = 2060001 THEN 29
|
||||
WHEN dropperid = 9420527 AND itemid = 2061001 THEN 29
|
||||
WHEN dropperid = 9420531 AND itemid = 2060001 THEN 38
|
||||
WHEN dropperid = 9420531 AND itemid = 2061001 THEN 38
|
||||
WHEN dropperid = 9500112 AND itemid = 2060001 THEN 22
|
||||
WHEN dropperid = 9500112 AND itemid = 2061001 THEN 22
|
||||
WHEN dropperid = 9500119 AND itemid = 2060000 THEN 51
|
||||
WHEN dropperid = 9500119 AND itemid = 2061000 THEN 51
|
||||
WHEN dropperid = 9500120 AND itemid = 2060000 THEN 58
|
||||
WHEN dropperid = 9500120 AND itemid = 2061000 THEN 58
|
||||
WHEN dropperid = 9500122 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 9500123 AND itemid = 2060000 THEN 77
|
||||
WHEN dropperid = 9500123 AND itemid = 2061000 THEN 77
|
||||
WHEN dropperid = 9500308 AND itemid = 2060000 THEN 91
|
||||
WHEN dropperid = 9500308 AND itemid = 2061000 THEN 91
|
||||
WHEN dropperid = 9500310 AND itemid = 2060000 THEN 107
|
||||
WHEN dropperid = 9500310 AND itemid = 2061000 THEN 107
|
||||
WHEN dropperid = 9500312 AND itemid = 2060001 THEN 63
|
||||
WHEN dropperid = 9500312 AND itemid = 2061001 THEN 63
|
||||
WHEN dropperid = 9500313 AND itemid = 2060001 THEN 64
|
||||
WHEN dropperid = 9500313 AND itemid = 2061001 THEN 64
|
||||
WHEN dropperid = 9500314 AND itemid = 2060001 THEN 70
|
||||
WHEN dropperid = 9500314 AND itemid = 2061001 THEN 70
|
||||
WHEN dropperid = 9500321 AND itemid = 2060001 THEN 6
|
||||
WHEN dropperid = 9500321 AND itemid = 2061001 THEN 6
|
||||
WHEN dropperid = 9500366 AND itemid = 2060000 THEN 19
|
||||
WHEN dropperid = 9500369 AND itemid = 2060000 THEN 19
|
||||
ELSE minimum_quantity END,
|
||||
maximum_quantity = CASE
|
||||
WHEN dropperid = 100100 AND itemid = 2060000 THEN 2
|
||||
WHEN dropperid = 100100 AND itemid = 2061000 THEN 2
|
||||
WHEN dropperid = 100101 AND itemid = 2060000 THEN 3
|
||||
WHEN dropperid = 100101 AND itemid = 2061000 THEN 3
|
||||
WHEN dropperid = 100120 AND itemid = 2060000 THEN 2
|
||||
WHEN dropperid = 100120 AND itemid = 2061000 THEN 2
|
||||
WHEN dropperid = 100121 AND itemid = 2060000 THEN 5
|
||||
WHEN dropperid = 100123 AND itemid = 2061000 THEN 12
|
||||
WHEN dropperid = 100124 AND itemid = 2060000 THEN 14
|
||||
WHEN dropperid = 100124 AND itemid = 2061000 THEN 14
|
||||
WHEN dropperid = 120100 AND itemid = 2060000 THEN 3
|
||||
WHEN dropperid = 120100 AND itemid = 2061000 THEN 3
|
||||
WHEN dropperid = 130100 AND itemid = 2060000 THEN 7
|
||||
WHEN dropperid = 130100 AND itemid = 2061000 THEN 7
|
||||
WHEN dropperid = 130101 AND itemid = 2060000 THEN 7
|
||||
WHEN dropperid = 130101 AND itemid = 2061000 THEN 7
|
||||
WHEN dropperid = 210100 AND itemid = 2060000 THEN 9
|
||||
WHEN dropperid = 210100 AND itemid = 2061000 THEN 9
|
||||
WHEN dropperid = 1110100 AND itemid = 2060000 THEN 24
|
||||
WHEN dropperid = 1110100 AND itemid = 2061000 THEN 24
|
||||
WHEN dropperid = 1110101 AND itemid = 2060000 THEN 17
|
||||
WHEN dropperid = 1110101 AND itemid = 2061000 THEN 17
|
||||
WHEN dropperid = 1110130 AND itemid = 2060000 THEN 24
|
||||
WHEN dropperid = 1110130 AND itemid = 2061000 THEN 24
|
||||
WHEN dropperid = 1120100 AND itemid = 2060000 THEN 19
|
||||
WHEN dropperid = 1120100 AND itemid = 2061000 THEN 19
|
||||
WHEN dropperid = 1130100 AND itemid = 2060000 THEN 28
|
||||
WHEN dropperid = 1130100 AND itemid = 2061000 THEN 28
|
||||
WHEN dropperid = 1140100 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 1140100 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 1140130 AND itemid = 2060000 THEN 30
|
||||
WHEN dropperid = 1140130 AND itemid = 2061000 THEN 30
|
||||
WHEN dropperid = 1210100 AND itemid = 2060000 THEN 12
|
||||
WHEN dropperid = 1210100 AND itemid = 2061000 THEN 12
|
||||
WHEN dropperid = 1210101 AND itemid = 2060000 THEN 17
|
||||
WHEN dropperid = 1210101 AND itemid = 2061000 THEN 17
|
||||
WHEN dropperid = 1210102 AND itemid = 2060000 THEN 13
|
||||
WHEN dropperid = 1210102 AND itemid = 2061000 THEN 13
|
||||
WHEN dropperid = 1210103 AND itemid = 2060000 THEN 24
|
||||
WHEN dropperid = 1210103 AND itemid = 2061000 THEN 24
|
||||
WHEN dropperid = 2100100 AND itemid = 2060000 THEN 33
|
||||
WHEN dropperid = 2100100 AND itemid = 2061000 THEN 33
|
||||
WHEN dropperid = 2100101 AND itemid = 2060000 THEN 34
|
||||
WHEN dropperid = 2100101 AND itemid = 2061000 THEN 34
|
||||
WHEN dropperid = 2100102 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 2100102 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 2100103 AND itemid = 2060000 THEN 40
|
||||
WHEN dropperid = 2100103 AND itemid = 2061000 THEN 40
|
||||
WHEN dropperid = 2100104 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 2100104 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 2100105 AND itemid = 2060000 THEN 38
|
||||
WHEN dropperid = 2100105 AND itemid = 2061000 THEN 38
|
||||
WHEN dropperid = 2100106 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 2100106 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 2100107 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 2100107 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 2100108 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 2100108 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 2110200 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 2110200 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 2110300 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 2110300 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 2110301 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 2110301 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 2130100 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 2130100 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 2220000 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 2220000 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 2220100 AND itemid = 2060000 THEN 33
|
||||
WHEN dropperid = 2220100 AND itemid = 2061000 THEN 33
|
||||
WHEN dropperid = 2230100 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 2230100 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 2230101 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 2230101 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 2230102 AND itemid = 2060000 THEN 40
|
||||
WHEN dropperid = 2230102 AND itemid = 2061000 THEN 40
|
||||
WHEN dropperid = 2230103 AND itemid = 2060000 THEN 38
|
||||
WHEN dropperid = 2230103 AND itemid = 2061000 THEN 38
|
||||
WHEN dropperid = 2230104 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 2230104 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 2230105 AND itemid = 2060000 THEN 38
|
||||
WHEN dropperid = 2230105 AND itemid = 2061000 THEN 38
|
||||
WHEN dropperid = 2230106 AND itemid = 2060000 THEN 40
|
||||
WHEN dropperid = 2230106 AND itemid = 2061000 THEN 40
|
||||
WHEN dropperid = 2230107 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 2230107 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 2230108 AND itemid = 2060000 THEN 35
|
||||
WHEN dropperid = 2230108 AND itemid = 2061000 THEN 35
|
||||
WHEN dropperid = 2230109 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 2230109 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 2230110 AND itemid = 2060000 THEN 38
|
||||
WHEN dropperid = 2230110 AND itemid = 2061000 THEN 38
|
||||
WHEN dropperid = 2230111 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 2230111 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 2230131 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 2230131 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 2230200 AND itemid = 2060000 THEN 47
|
||||
WHEN dropperid = 2230200 AND itemid = 2061000 THEN 47
|
||||
WHEN dropperid = 2300100 AND itemid = 2060000 THEN 33
|
||||
WHEN dropperid = 2300100 AND itemid = 2061000 THEN 33
|
||||
WHEN dropperid = 3000000 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3000000 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3000005 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3000005 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3000006 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3000006 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3100101 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 3100101 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 3100102 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3100102 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3110101 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 3110101 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 3110102 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 3110102 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 3110300 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 3110300 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 3110301 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 3110301 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 3110302 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 3110302 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 3110303 AND itemid = 2060000 THEN 62
|
||||
WHEN dropperid = 3110303 AND itemid = 2061000 THEN 62
|
||||
WHEN dropperid = 3210100 AND itemid = 2060005 THEN 8
|
||||
WHEN dropperid = 3210203 AND itemid = 2060000 THEN 59
|
||||
WHEN dropperid = 3210203 AND itemid = 2061000 THEN 59
|
||||
WHEN dropperid = 3210204 AND itemid = 2060000 THEN 55
|
||||
WHEN dropperid = 3210204 AND itemid = 2061000 THEN 55
|
||||
WHEN dropperid = 3210205 AND itemid = 2060000 THEN 55
|
||||
WHEN dropperid = 3210205 AND itemid = 2061000 THEN 55
|
||||
WHEN dropperid = 3210206 AND itemid = 2060000 THEN 59
|
||||
WHEN dropperid = 3210206 AND itemid = 2061000 THEN 59
|
||||
WHEN dropperid = 3210207 AND itemid = 2060000 THEN 55
|
||||
WHEN dropperid = 3210207 AND itemid = 2060005 THEN 9
|
||||
WHEN dropperid = 3210207 AND itemid = 2061000 THEN 55
|
||||
WHEN dropperid = 3210208 AND itemid = 2060000 THEN 59
|
||||
WHEN dropperid = 3210208 AND itemid = 2061000 THEN 59
|
||||
WHEN dropperid = 3210450 AND itemid = 2060000 THEN 59
|
||||
WHEN dropperid = 3210450 AND itemid = 2061000 THEN 59
|
||||
WHEN dropperid = 3210800 AND itemid = 2060005 THEN 10
|
||||
WHEN dropperid = 3220000 AND itemid = 2060000 THEN 79
|
||||
WHEN dropperid = 3220000 AND itemid = 2061000 THEN 79
|
||||
WHEN dropperid = 3230100 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 3230100 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 3230103 AND itemid = 2060000 THEN 62
|
||||
WHEN dropperid = 3230103 AND itemid = 2061000 THEN 62
|
||||
WHEN dropperid = 3230200 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 3230200 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 3230302 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 3230302 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 3230303 AND itemid = 2060000 THEN 60
|
||||
WHEN dropperid = 3230303 AND itemid = 2061000 THEN 60
|
||||
WHEN dropperid = 3230304 AND itemid = 2060000 THEN 62
|
||||
WHEN dropperid = 3230304 AND itemid = 2061000 THEN 62
|
||||
WHEN dropperid = 3230305 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 3230305 AND itemid = 2061000 THEN 64
|
||||
WHEN dropperid = 3230306 AND itemid = 2060000 THEN 60
|
||||
WHEN dropperid = 3230306 AND itemid = 2061000 THEN 60
|
||||
WHEN dropperid = 3230307 AND itemid = 2060000 THEN 50
|
||||
WHEN dropperid = 3230307 AND itemid = 2061000 THEN 50
|
||||
WHEN dropperid = 3230308 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 3230308 AND itemid = 2061000 THEN 64
|
||||
WHEN dropperid = 3230400 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3230400 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3230405 AND itemid = 2060000 THEN 62
|
||||
WHEN dropperid = 3230405 AND itemid = 2061000 THEN 62
|
||||
WHEN dropperid = 3300000 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3300000 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3300001 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 3300001 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 3300002 AND itemid = 2060000 THEN 50
|
||||
WHEN dropperid = 3300002 AND itemid = 2061000 THEN 50
|
||||
WHEN dropperid = 3300003 AND itemid = 2060000 THEN 52
|
||||
WHEN dropperid = 3300003 AND itemid = 2061000 THEN 52
|
||||
WHEN dropperid = 3300004 AND itemid = 2060000 THEN 54
|
||||
WHEN dropperid = 3300004 AND itemid = 2061000 THEN 54
|
||||
WHEN dropperid = 3300006 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 3300006 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 3300007 AND itemid = 2060000 THEN 57
|
||||
WHEN dropperid = 3300007 AND itemid = 2061000 THEN 57
|
||||
WHEN dropperid = 3300008 AND itemid = 2060000 THEN 87
|
||||
WHEN dropperid = 3300008 AND itemid = 2061000 THEN 87
|
||||
WHEN dropperid = 4110300 AND itemid = 2060000 THEN 68
|
||||
WHEN dropperid = 4110300 AND itemid = 2061000 THEN 68
|
||||
WHEN dropperid = 4110301 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4110301 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4130103 AND itemid = 2060000 THEN 107
|
||||
WHEN dropperid = 4130103 AND itemid = 2061000 THEN 107
|
||||
WHEN dropperid = 4230103 AND itemid = 2060000 THEN 68
|
||||
WHEN dropperid = 4230103 AND itemid = 2061000 THEN 68
|
||||
WHEN dropperid = 4230106 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230106 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230108 AND itemid = 2060000 THEN 70
|
||||
WHEN dropperid = 4230108 AND itemid = 2061000 THEN 70
|
||||
WHEN dropperid = 4230109 AND itemid = 2060000 THEN 68
|
||||
WHEN dropperid = 4230109 AND itemid = 2061000 THEN 68
|
||||
WHEN dropperid = 4230110 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230110 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230111 AND itemid = 2060000 THEN 67
|
||||
WHEN dropperid = 4230111 AND itemid = 2061000 THEN 67
|
||||
WHEN dropperid = 4230112 AND itemid = 2060000 THEN 72
|
||||
WHEN dropperid = 4230112 AND itemid = 2061000 THEN 72
|
||||
WHEN dropperid = 4230113 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 4230113 AND itemid = 2061000 THEN 65
|
||||
WHEN dropperid = 4230114 AND itemid = 2060000 THEN 67
|
||||
WHEN dropperid = 4230114 AND itemid = 2061000 THEN 67
|
||||
WHEN dropperid = 4230115 AND itemid = 2060000 THEN 75
|
||||
WHEN dropperid = 4230115 AND itemid = 2061000 THEN 75
|
||||
WHEN dropperid = 4230116 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 4230116 AND itemid = 2061000 THEN 65
|
||||
WHEN dropperid = 4230117 AND itemid = 2060000 THEN 68
|
||||
WHEN dropperid = 4230117 AND itemid = 2061000 THEN 68
|
||||
WHEN dropperid = 4230118 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230118 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230119 AND itemid = 2060000 THEN 67
|
||||
WHEN dropperid = 4230119 AND itemid = 2061000 THEN 67
|
||||
WHEN dropperid = 4230120 AND itemid = 2060000 THEN 72
|
||||
WHEN dropperid = 4230120 AND itemid = 2061000 THEN 72
|
||||
WHEN dropperid = 4230121 AND itemid = 2060000 THEN 75
|
||||
WHEN dropperid = 4230121 AND itemid = 2061000 THEN 75
|
||||
WHEN dropperid = 4230123 AND itemid = 2060000 THEN 70
|
||||
WHEN dropperid = 4230123 AND itemid = 2061000 THEN 70
|
||||
WHEN dropperid = 4230124 AND itemid = 2060000 THEN 68
|
||||
WHEN dropperid = 4230124 AND itemid = 2061000 THEN 68
|
||||
WHEN dropperid = 4230125 AND itemid = 2060000 THEN 72
|
||||
WHEN dropperid = 4230125 AND itemid = 2061000 THEN 72
|
||||
WHEN dropperid = 4230126 AND itemid = 2060000 THEN 77
|
||||
WHEN dropperid = 4230126 AND itemid = 2061000 THEN 77
|
||||
WHEN dropperid = 4230201 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 4230201 AND itemid = 2061000 THEN 65
|
||||
WHEN dropperid = 4230300 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230300 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230400 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230400 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230500 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 4230500 AND itemid = 2061000 THEN 65
|
||||
WHEN dropperid = 4230501 AND itemid = 2060000 THEN 67
|
||||
WHEN dropperid = 4230501 AND itemid = 2061000 THEN 67
|
||||
WHEN dropperid = 4230502 AND itemid = 2060000 THEN 70
|
||||
WHEN dropperid = 4230502 AND itemid = 2061000 THEN 70
|
||||
WHEN dropperid = 4230503 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230503 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230504 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 4230504 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 4230600 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 4230600 AND itemid = 2061000 THEN 65
|
||||
WHEN dropperid = 4240000 AND itemid = 2060000 THEN 80
|
||||
WHEN dropperid = 4240000 AND itemid = 2061000 THEN 80
|
||||
WHEN dropperid = 5120100 AND itemid = 2060000 THEN 123
|
||||
WHEN dropperid = 5120100 AND itemid = 2061000 THEN 123
|
||||
WHEN dropperid = 5130104 AND itemid = 2060000 THEN 89
|
||||
WHEN dropperid = 5130104 AND itemid = 2061000 THEN 89
|
||||
WHEN dropperid = 5140000 AND itemid = 2060000 THEN 94
|
||||
WHEN dropperid = 5140000 AND itemid = 2061000 THEN 94
|
||||
WHEN dropperid = 5150000 AND itemid = 2060000 THEN 97
|
||||
WHEN dropperid = 5150000 AND itemid = 2061000 THEN 97
|
||||
WHEN dropperid = 5200000 AND itemid = 2060001 THEN 19
|
||||
WHEN dropperid = 5200000 AND itemid = 2061001 THEN 19
|
||||
WHEN dropperid = 5200001 AND itemid = 2060001 THEN 24
|
||||
WHEN dropperid = 5200001 AND itemid = 2061001 THEN 24
|
||||
WHEN dropperid = 5200002 AND itemid = 2060001 THEN 24
|
||||
WHEN dropperid = 5200002 AND itemid = 2061001 THEN 24
|
||||
WHEN dropperid = 5220000 AND itemid = 2060000 THEN 125
|
||||
WHEN dropperid = 5220000 AND itemid = 2061000 THEN 125
|
||||
WHEN dropperid = 5220002 AND itemid = 2060000 THEN 114
|
||||
WHEN dropperid = 5220002 AND itemid = 2061000 THEN 114
|
||||
WHEN dropperid = 5220003 AND itemid = 2060000 THEN 134
|
||||
WHEN dropperid = 5220003 AND itemid = 2061000 THEN 134
|
||||
WHEN dropperid = 5400000 AND itemid = 2060001 THEN 28
|
||||
WHEN dropperid = 5400000 AND itemid = 2061001 THEN 28
|
||||
WHEN dropperid = 6220000 AND itemid = 2060000 THEN 148
|
||||
WHEN dropperid = 6220000 AND itemid = 2061000 THEN 148
|
||||
WHEN dropperid = 7120103 AND itemid = 2060003 THEN 28
|
||||
WHEN dropperid = 7220000 AND itemid = 2060001 THEN 81
|
||||
WHEN dropperid = 7220000 AND itemid = 2061001 THEN 81
|
||||
WHEN dropperid = 7220001 AND itemid = 2060001 THEN 79
|
||||
WHEN dropperid = 7220001 AND itemid = 2061001 THEN 79
|
||||
WHEN dropperid = 7220002 AND itemid = 2060001 THEN 87
|
||||
WHEN dropperid = 7220002 AND itemid = 2061001 THEN 87
|
||||
WHEN dropperid = 8220000 AND itemid = 2060001 THEN 94
|
||||
WHEN dropperid = 8220000 AND itemid = 2061001 THEN 94
|
||||
WHEN dropperid = 8220001 AND itemid = 2060001 THEN 102
|
||||
WHEN dropperid = 8220001 AND itemid = 2061001 THEN 102
|
||||
WHEN dropperid = 9300011 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 9300011 AND itemid = 2061000 THEN 64
|
||||
WHEN dropperid = 9300060 AND itemid = 2060000 THEN 68
|
||||
WHEN dropperid = 9300060 AND itemid = 2061000 THEN 68
|
||||
WHEN dropperid = 9300131 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 9300131 AND itemid = 2061000 THEN 64
|
||||
WHEN dropperid = 9300132 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 9300132 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 9300133 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 9300160 AND itemid = 2060000 THEN 103
|
||||
WHEN dropperid = 9300160 AND itemid = 2061000 THEN 103
|
||||
WHEN dropperid = 9300161 AND itemid = 2060000 THEN 103
|
||||
WHEN dropperid = 9300161 AND itemid = 2061000 THEN 103
|
||||
WHEN dropperid = 9300274 AND itemid = 2060000 THEN 13
|
||||
WHEN dropperid = 9300274 AND itemid = 2061000 THEN 13
|
||||
WHEN dropperid = 9300332 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 9300334 AND itemid = 2060000 THEN 80
|
||||
WHEN dropperid = 9300341 AND itemid = 2060000 THEN 9
|
||||
WHEN dropperid = 9300341 AND itemid = 2061000 THEN 9
|
||||
WHEN dropperid = 9300342 AND itemid = 2060000 THEN 13
|
||||
WHEN dropperid = 9300342 AND itemid = 2061000 THEN 13
|
||||
WHEN dropperid = 9300343 AND itemid = 2060000 THEN 12
|
||||
WHEN dropperid = 9300343 AND itemid = 2061000 THEN 12
|
||||
WHEN dropperid = 9303005 AND itemid = 2060001 THEN 21
|
||||
WHEN dropperid = 9303005 AND itemid = 2061001 THEN 21
|
||||
WHEN dropperid = 9303008 AND itemid = 2060001 THEN 21
|
||||
WHEN dropperid = 9303008 AND itemid = 2061001 THEN 21
|
||||
WHEN dropperid = 9303009 AND itemid = 2060001 THEN 41
|
||||
WHEN dropperid = 9303009 AND itemid = 2061001 THEN 41
|
||||
WHEN dropperid = 9400000 AND itemid = 2060001 THEN 20
|
||||
WHEN dropperid = 9400009 AND itemid = 2060001 THEN 163
|
||||
WHEN dropperid = 9400011 AND itemid = 2060002 THEN 21
|
||||
WHEN dropperid = 9400100 AND itemid = 2060003 THEN 18
|
||||
WHEN dropperid = 9400101 AND itemid = 2061003 THEN 19
|
||||
WHEN dropperid = 9400204 AND itemid = 2060003 THEN 22
|
||||
WHEN dropperid = 9400239 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 9400239 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 9400244 AND itemid = 2060000 THEN 97
|
||||
WHEN dropperid = 9400244 AND itemid = 2061000 THEN 97
|
||||
WHEN dropperid = 9400248 AND itemid = 2060000 THEN 39
|
||||
WHEN dropperid = 9400248 AND itemid = 2061000 THEN 39
|
||||
WHEN dropperid = 9400540 AND itemid = 2060004 THEN 8
|
||||
WHEN dropperid = 9400540 AND itemid = 2061004 THEN 8
|
||||
WHEN dropperid = 9400541 AND itemid = 2060004 THEN 8
|
||||
WHEN dropperid = 9400541 AND itemid = 2061004 THEN 8
|
||||
WHEN dropperid = 9400542 AND itemid = 2060004 THEN 11
|
||||
WHEN dropperid = 9400542 AND itemid = 2061004 THEN 11
|
||||
WHEN dropperid = 9400543 AND itemid = 2060004 THEN 13
|
||||
WHEN dropperid = 9400543 AND itemid = 2061004 THEN 13
|
||||
WHEN dropperid = 9400547 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 9400547 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 9400548 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 9400548 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 9400550 AND itemid = 2060000 THEN 44
|
||||
WHEN dropperid = 9400550 AND itemid = 2061000 THEN 44
|
||||
WHEN dropperid = 9400558 AND itemid = 2060000 THEN 49
|
||||
WHEN dropperid = 9400558 AND itemid = 2061000 THEN 49
|
||||
WHEN dropperid = 9400563 AND itemid = 2060000 THEN 65
|
||||
WHEN dropperid = 9400563 AND itemid = 2061000 THEN 65
|
||||
WHEN dropperid = 9400638 AND itemid = 2060000 THEN 33
|
||||
WHEN dropperid = 9400638 AND itemid = 2061000 THEN 33
|
||||
WHEN dropperid = 9420500 AND itemid = 2060000 THEN 45
|
||||
WHEN dropperid = 9420500 AND itemid = 2061000 THEN 45
|
||||
WHEN dropperid = 9420502 AND itemid = 2060000 THEN 29
|
||||
WHEN dropperid = 9420502 AND itemid = 2061000 THEN 29
|
||||
WHEN dropperid = 9420506 AND itemid = 2060000 THEN 38
|
||||
WHEN dropperid = 9420506 AND itemid = 2061000 THEN 38
|
||||
WHEN dropperid = 9420508 AND itemid = 2060000 THEN 70
|
||||
WHEN dropperid = 9420508 AND itemid = 2061000 THEN 70
|
||||
WHEN dropperid = 9420527 AND itemid = 2060001 THEN 36
|
||||
WHEN dropperid = 9420527 AND itemid = 2061001 THEN 36
|
||||
WHEN dropperid = 9420531 AND itemid = 2060001 THEN 48
|
||||
WHEN dropperid = 9420531 AND itemid = 2061001 THEN 48
|
||||
WHEN dropperid = 9500112 AND itemid = 2060001 THEN 28
|
||||
WHEN dropperid = 9500112 AND itemid = 2061001 THEN 28
|
||||
WHEN dropperid = 9500119 AND itemid = 2060000 THEN 64
|
||||
WHEN dropperid = 9500119 AND itemid = 2061000 THEN 64
|
||||
WHEN dropperid = 9500120 AND itemid = 2060000 THEN 73
|
||||
WHEN dropperid = 9500120 AND itemid = 2061000 THEN 73
|
||||
WHEN dropperid = 9500122 AND itemid = 2060000 THEN 80
|
||||
WHEN dropperid = 9500123 AND itemid = 2060000 THEN 97
|
||||
WHEN dropperid = 9500123 AND itemid = 2061000 THEN 97
|
||||
WHEN dropperid = 9500308 AND itemid = 2060000 THEN 114
|
||||
WHEN dropperid = 9500308 AND itemid = 2061000 THEN 114
|
||||
WHEN dropperid = 9500310 AND itemid = 2060000 THEN 134
|
||||
WHEN dropperid = 9500310 AND itemid = 2061000 THEN 134
|
||||
WHEN dropperid = 9500312 AND itemid = 2060001 THEN 79
|
||||
WHEN dropperid = 9500312 AND itemid = 2061001 THEN 79
|
||||
WHEN dropperid = 9500313 AND itemid = 2060001 THEN 81
|
||||
WHEN dropperid = 9500313 AND itemid = 2061001 THEN 81
|
||||
WHEN dropperid = 9500314 AND itemid = 2060001 THEN 87
|
||||
WHEN dropperid = 9500314 AND itemid = 2061001 THEN 87
|
||||
WHEN dropperid = 9500321 AND itemid = 2060001 THEN 8
|
||||
WHEN dropperid = 9500321 AND itemid = 2061001 THEN 8
|
||||
WHEN dropperid = 9500366 AND itemid = 2060000 THEN 24
|
||||
WHEN dropperid = 9500369 AND itemid = 2060000 THEN 24
|
||||
ELSE maximum_quantity END
|
||||
;
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 life;
|
||||
|
||||
public enum Element {
|
||||
NEUTRAL, FIRE, ICE, LIGHTING, POISON, HOLY, DARK;
|
||||
|
||||
public static Element getFromChar(char c) {
|
||||
switch (Character.toUpperCase(c)) {
|
||||
case 'F':
|
||||
return FIRE;
|
||||
case 'I':
|
||||
return ICE;
|
||||
case 'L':
|
||||
return LIGHTING;
|
||||
case 'S':
|
||||
return POISON;
|
||||
case 'H':
|
||||
return HOLY;
|
||||
case 'D':
|
||||
return DARK;
|
||||
case 'P':
|
||||
return NEUTRAL;
|
||||
}
|
||||
throw new IllegalArgumentException("unknown elemnt char " + c);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 life;
|
||||
|
||||
public enum ElementalEffectiveness {
|
||||
NORMAL, IMMUNE, STRONG, WEAK, NEUTRAL;
|
||||
|
||||
public static ElementalEffectiveness getByNumber(int num) {
|
||||
switch (num) {
|
||||
case 1:
|
||||
return IMMUNE;
|
||||
case 2:
|
||||
return STRONG;
|
||||
case 3:
|
||||
return WEAK;
|
||||
case 4:
|
||||
return NEUTRAL;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unkown effectiveness: " + num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 life;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataDirectoryEntry;
|
||||
import provider.MapleDataFileEntry;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import provider.wz.MapleDataType;
|
||||
import tools.Pair;
|
||||
|
||||
public class MapleLifeFactory {
|
||||
private static String wzPath = "../../wz";
|
||||
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/Mob.wz"));
|
||||
private final static MapleDataProvider stringDataWZ = MapleDataProviderFactory.getDataProvider(new File(wzPath + "/String.wz"));
|
||||
private static MapleData mobStringData = stringDataWZ.getData("Mob.img");
|
||||
private static MapleData npcStringData = stringDataWZ.getData("Npc.img");
|
||||
private static Map<Integer, MapleMonsterStats> monsterStats = new HashMap<>();
|
||||
|
||||
private static int getMonsterId(String fileName) {
|
||||
return Integer.parseInt(fileName.substring(0, 7));
|
||||
}
|
||||
|
||||
public static Map<Integer, MapleMonsterStats> getAllMonsterStats() {
|
||||
MapleDataDirectoryEntry root = data.getRoot();
|
||||
|
||||
System.out.print("Parsing mob stats... ");
|
||||
for (MapleDataFileEntry mFile : root.getFiles()) {
|
||||
try {
|
||||
String fileName = mFile.getName();
|
||||
|
||||
//System.out.println("Parsing '" + fileName + "'");
|
||||
MapleData monsterData = data.getData(fileName);
|
||||
if (monsterData == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Integer mid = getMonsterId(fileName);
|
||||
|
||||
MapleData monsterInfoData = monsterData.getChildByPath("info");
|
||||
MapleMonsterStats stats = new MapleMonsterStats();
|
||||
stats.setHp(MapleDataTool.getIntConvert("maxHP", monsterInfoData));
|
||||
stats.setFriendly(MapleDataTool.getIntConvert("damagedByMob", monsterInfoData, 0) == 1);
|
||||
stats.setPADamage(MapleDataTool.getIntConvert("PADamage", monsterInfoData));
|
||||
stats.setPDDamage(MapleDataTool.getIntConvert("PDDamage", monsterInfoData));
|
||||
stats.setMADamage(MapleDataTool.getIntConvert("MADamage", monsterInfoData));
|
||||
stats.setMDDamage(MapleDataTool.getIntConvert("MDDamage", monsterInfoData));
|
||||
stats.setMp(MapleDataTool.getIntConvert("maxMP", monsterInfoData, 0));
|
||||
stats.setExp(MapleDataTool.getIntConvert("exp", monsterInfoData, 0));
|
||||
stats.setLevel(MapleDataTool.getIntConvert("level", monsterInfoData));
|
||||
stats.setRemoveAfter(MapleDataTool.getIntConvert("removeAfter", monsterInfoData, 0));
|
||||
stats.setBoss(MapleDataTool.getIntConvert("boss", monsterInfoData, 0) > 0);
|
||||
stats.setExplosiveReward(MapleDataTool.getIntConvert("explosiveReward", monsterInfoData, 0) > 0);
|
||||
stats.setFfaLoot(MapleDataTool.getIntConvert("publicReward", monsterInfoData, 0) > 0);
|
||||
stats.setUndead(MapleDataTool.getIntConvert("undead", monsterInfoData, 0) > 0);
|
||||
stats.setName(MapleDataTool.getString(mid + "/name", mobStringData, "MISSINGNO"));
|
||||
stats.setBuffToGive(MapleDataTool.getIntConvert("buff", monsterInfoData, -1));
|
||||
stats.setCP(MapleDataTool.getIntConvert("getCP", monsterInfoData, 0));
|
||||
stats.setRemoveOnMiss(MapleDataTool.getIntConvert("removeOnMiss", monsterInfoData, 0) > 0);
|
||||
|
||||
MapleData special = monsterInfoData.getChildByPath("coolDamage");
|
||||
if (special != null) {
|
||||
int coolDmg = MapleDataTool.getIntConvert("coolDamage", monsterInfoData);
|
||||
int coolProb = MapleDataTool.getIntConvert("coolDamageProb", monsterInfoData, 0);
|
||||
stats.setCool(new Pair<>(coolDmg, coolProb));
|
||||
}
|
||||
special = monsterInfoData.getChildByPath("loseItem");
|
||||
if (special != null) {
|
||||
for (MapleData liData : special.getChildren()) {
|
||||
stats.addLoseItem(new loseItem(MapleDataTool.getInt(liData.getChildByPath("id")), (byte) MapleDataTool.getInt(liData.getChildByPath("prop")), (byte) MapleDataTool.getInt(liData.getChildByPath("x"))));
|
||||
}
|
||||
}
|
||||
special = monsterInfoData.getChildByPath("selfDestruction");
|
||||
if (special != null) {
|
||||
stats.setSelfDestruction(new selfDestruction((byte) MapleDataTool.getInt(special.getChildByPath("action")), MapleDataTool.getIntConvert("removeAfter", special, -1), MapleDataTool.getIntConvert("hp", special, -1)));
|
||||
}
|
||||
MapleData firstAttackData = monsterInfoData.getChildByPath("firstAttack");
|
||||
int firstAttack = 0;
|
||||
if (firstAttackData != null) {
|
||||
if (firstAttackData.getType() == MapleDataType.FLOAT) {
|
||||
firstAttack = Math.round(MapleDataTool.getFloat(firstAttackData));
|
||||
} else {
|
||||
firstAttack = MapleDataTool.getInt(firstAttackData);
|
||||
}
|
||||
}
|
||||
stats.setFirstAttack(firstAttack > 0);
|
||||
stats.setDropPeriod(MapleDataTool.getIntConvert("dropItemPeriod", monsterInfoData, 0) * 10000);
|
||||
|
||||
stats.setTagColor(MapleDataTool.getIntConvert("hpTagColor", monsterInfoData, 0));
|
||||
stats.setTagBgColor(MapleDataTool.getIntConvert("hpTagBgcolor", monsterInfoData, 0));
|
||||
|
||||
for (MapleData idata : monsterData) {
|
||||
if (!idata.getName().equals("info")) {
|
||||
int delay = 0;
|
||||
for (MapleData pic : idata.getChildren()) {
|
||||
delay += MapleDataTool.getIntConvert("delay", pic, 0);
|
||||
}
|
||||
stats.setAnimationTime(idata.getName(), delay);
|
||||
}
|
||||
}
|
||||
MapleData reviveInfo = monsterInfoData.getChildByPath("revive");
|
||||
if (reviveInfo != null) {
|
||||
List<Integer> revives = new LinkedList<>();
|
||||
for (MapleData data_ : reviveInfo) {
|
||||
revives.add(MapleDataTool.getInt(data_));
|
||||
}
|
||||
stats.setRevives(revives);
|
||||
}
|
||||
decodeElementalString(stats, MapleDataTool.getString("elemAttr", monsterInfoData, ""));
|
||||
MapleData monsterSkillData = monsterInfoData.getChildByPath("skill");
|
||||
if (monsterSkillData != null) {
|
||||
int i = 0;
|
||||
List<Pair<Integer, Integer>> skills = new ArrayList<>();
|
||||
while (monsterSkillData.getChildByPath(Integer.toString(i)) != null) {
|
||||
skills.add(new Pair<>(Integer.valueOf(MapleDataTool.getInt(i + "/skill", monsterSkillData, 0)), Integer.valueOf(MapleDataTool.getInt(i + "/level", monsterSkillData, 0))));
|
||||
i++;
|
||||
}
|
||||
stats.setSkills(skills);
|
||||
}
|
||||
MapleData banishData = monsterInfoData.getChildByPath("ban");
|
||||
if (banishData != null) {
|
||||
stats.setBanishInfo(new BanishInfo(MapleDataTool.getString("banMsg", banishData), MapleDataTool.getInt("banMap/0/field", banishData, -1), MapleDataTool.getString("banMap/0/portal", banishData, "sp")));
|
||||
}
|
||||
|
||||
monsterStats.put(mid, stats);
|
||||
} catch(NullPointerException npe) {
|
||||
//System.out.println("[SEVERE] " + mFile.getName() + " failed to load. Issue: " + npe.getMessage() + "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("done!");
|
||||
return monsterStats;
|
||||
}
|
||||
|
||||
private static void decodeElementalString(MapleMonsterStats stats, String elemAttr) {
|
||||
for (int i = 0; i < elemAttr.length(); i += 2) {
|
||||
stats.setEffectiveness(Element.getFromChar(elemAttr.charAt(i)), ElementalEffectiveness.getByNumber(Integer.valueOf(String.valueOf(elemAttr.charAt(i + 1)))));
|
||||
}
|
||||
}
|
||||
|
||||
public static class BanishInfo {
|
||||
|
||||
private int map;
|
||||
private String portal, msg;
|
||||
|
||||
public BanishInfo(String msg, int map, String portal) {
|
||||
this.msg = msg;
|
||||
this.map = map;
|
||||
this.portal = portal;
|
||||
}
|
||||
|
||||
public int getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getPortal() {
|
||||
return portal;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
public static class loseItem {
|
||||
|
||||
private int id;
|
||||
private byte chance, x;
|
||||
|
||||
private loseItem(int id, byte chance, byte x) {
|
||||
this.id = id;
|
||||
this.chance = chance;
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte getChance() {
|
||||
return chance;
|
||||
}
|
||||
|
||||
public byte getX() {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
public static class selfDestruction {
|
||||
|
||||
private byte action;
|
||||
private int removeAfter;
|
||||
private int hp;
|
||||
|
||||
private selfDestruction(byte action, int removeAfter, int hp) {
|
||||
this.action = action;
|
||||
this.removeAfter = removeAfter;
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
public int getHp() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
public byte getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public int removeAfter() {
|
||||
return removeAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 life;
|
||||
|
||||
import life.MapleLifeFactory.BanishInfo;
|
||||
import life.MapleLifeFactory.loseItem;
|
||||
import life.MapleLifeFactory.selfDestruction;
|
||||
import tools.Pair;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Frz
|
||||
*/
|
||||
public class MapleMonsterStats {
|
||||
private boolean changeable;
|
||||
private int exp, hp, mp, level, PADamage, PDDamage, MADamage, MDDamage, dropPeriod, cp, buffToGive, removeAfter;
|
||||
private boolean boss, undead, ffaLoot, isExplosiveReward, firstAttack, removeOnMiss;
|
||||
private String name;
|
||||
private Map<String, Integer> animationTimes = new HashMap<String, Integer>();
|
||||
private Map<Element, ElementalEffectiveness> resistance = new HashMap<Element, ElementalEffectiveness>();
|
||||
private List<Integer> revives = Collections.emptyList();
|
||||
private byte tagColor, tagBgColor;
|
||||
private List<Pair<Integer, Integer>> skills = new ArrayList<Pair<Integer, Integer>>();
|
||||
private Pair<Integer, Integer> cool = null;
|
||||
private BanishInfo banish = null;
|
||||
private List<loseItem> loseItem = null;
|
||||
private selfDestruction selfDestruction = null;
|
||||
private boolean friendly;
|
||||
|
||||
public void setChange(boolean change) {
|
||||
this.changeable = change;
|
||||
}
|
||||
|
||||
public boolean isChangeable() {
|
||||
return changeable;
|
||||
}
|
||||
|
||||
public int getExp() {
|
||||
return exp;
|
||||
}
|
||||
|
||||
public void setExp(int exp) {
|
||||
this.exp = exp;
|
||||
}
|
||||
|
||||
public int getHp() {
|
||||
return hp;
|
||||
}
|
||||
|
||||
public void setHp(int hp) {
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
public int getMp() {
|
||||
return mp;
|
||||
}
|
||||
|
||||
public void setMp(int mp) {
|
||||
this.mp = mp;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public int removeAfter() {
|
||||
return removeAfter;
|
||||
}
|
||||
|
||||
public void setRemoveAfter(int removeAfter) {
|
||||
this.removeAfter = removeAfter;
|
||||
}
|
||||
|
||||
public int getDropPeriod() {
|
||||
return dropPeriod;
|
||||
}
|
||||
|
||||
public void setDropPeriod(int dropPeriod) {
|
||||
this.dropPeriod = dropPeriod;
|
||||
}
|
||||
|
||||
public void setBoss(boolean boss) {
|
||||
this.boss = boss;
|
||||
}
|
||||
|
||||
public boolean isBoss() {
|
||||
return boss;
|
||||
}
|
||||
|
||||
public void setFfaLoot(boolean ffaLoot) {
|
||||
this.ffaLoot = ffaLoot;
|
||||
}
|
||||
|
||||
public boolean isFfaLoot() {
|
||||
return ffaLoot;
|
||||
}
|
||||
|
||||
public void setAnimationTime(String name, int delay) {
|
||||
animationTimes.put(name, delay);
|
||||
}
|
||||
|
||||
public int getAnimationTime(String name) {
|
||||
Integer ret = animationTimes.get(name);
|
||||
if (ret == null) {
|
||||
return 500;
|
||||
}
|
||||
return ret.intValue();
|
||||
}
|
||||
|
||||
public boolean isMobile() {
|
||||
return animationTimes.containsKey("move") || animationTimes.containsKey("fly");
|
||||
}
|
||||
|
||||
public List<Integer> getRevives() {
|
||||
return revives;
|
||||
}
|
||||
|
||||
public void setRevives(List<Integer> revives) {
|
||||
this.revives = revives;
|
||||
}
|
||||
|
||||
public void setUndead(boolean undead) {
|
||||
this.undead = undead;
|
||||
}
|
||||
|
||||
public boolean getUndead() {
|
||||
return undead;
|
||||
}
|
||||
|
||||
public void setEffectiveness(Element e, ElementalEffectiveness ee) {
|
||||
resistance.put(e, ee);
|
||||
}
|
||||
|
||||
public ElementalEffectiveness getEffectiveness(Element e) {
|
||||
ElementalEffectiveness elementalEffectiveness = resistance.get(e);
|
||||
if (elementalEffectiveness == null) {
|
||||
return ElementalEffectiveness.NORMAL;
|
||||
} else {
|
||||
return elementalEffectiveness;
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public byte getTagColor() {
|
||||
return tagColor;
|
||||
}
|
||||
|
||||
public void setTagColor(int tagColor) {
|
||||
this.tagColor = (byte) tagColor;
|
||||
}
|
||||
|
||||
public byte getTagBgColor() {
|
||||
return tagBgColor;
|
||||
}
|
||||
|
||||
public void setTagBgColor(int tagBgColor) {
|
||||
this.tagBgColor = (byte) tagBgColor;
|
||||
}
|
||||
|
||||
public void setSkills(List<Pair<Integer, Integer>> skills) {
|
||||
this.skills.addAll(skills);
|
||||
}
|
||||
|
||||
public List<Pair<Integer, Integer>> getSkills() {
|
||||
return Collections.unmodifiableList(this.skills);
|
||||
}
|
||||
|
||||
public int getNoSkills() {
|
||||
return this.skills.size();
|
||||
}
|
||||
|
||||
public boolean hasSkill(int skillId, int level) {
|
||||
for (Pair<Integer, Integer> skill : skills) {
|
||||
if (skill.getLeft() == skillId && skill.getRight() == level) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setFirstAttack(boolean firstAttack) {
|
||||
this.firstAttack = firstAttack;
|
||||
}
|
||||
|
||||
public boolean isFirstAttack() {
|
||||
return firstAttack;
|
||||
}
|
||||
|
||||
public void setBuffToGive(int buff) {
|
||||
this.buffToGive = buff;
|
||||
}
|
||||
|
||||
public int getBuffToGive() {
|
||||
return buffToGive;
|
||||
}
|
||||
|
||||
void removeEffectiveness(Element e) {
|
||||
resistance.remove(e);
|
||||
}
|
||||
|
||||
public BanishInfo getBanishInfo() {
|
||||
return banish;
|
||||
}
|
||||
|
||||
public void setBanishInfo(BanishInfo banish) {
|
||||
this.banish = banish;
|
||||
}
|
||||
|
||||
public int getPADamage() {
|
||||
return PADamage;
|
||||
}
|
||||
|
||||
public void setPADamage(int PADamage) {
|
||||
this.PADamage = PADamage;
|
||||
}
|
||||
|
||||
public int getCP() {
|
||||
return cp;
|
||||
}
|
||||
|
||||
public void setCP(int cp) {
|
||||
this.cp = cp;
|
||||
}
|
||||
|
||||
public List<loseItem> loseItem() {
|
||||
return loseItem;
|
||||
}
|
||||
|
||||
public void addLoseItem(loseItem li) {
|
||||
if (loseItem == null) {
|
||||
loseItem = new LinkedList<loseItem>();
|
||||
}
|
||||
loseItem.add(li);
|
||||
}
|
||||
|
||||
public selfDestruction selfDestruction() {
|
||||
return selfDestruction;
|
||||
}
|
||||
|
||||
public void setSelfDestruction(selfDestruction sd) {
|
||||
this.selfDestruction = sd;
|
||||
}
|
||||
|
||||
public void setExplosiveReward(boolean isExplosiveReward) {
|
||||
this.isExplosiveReward = isExplosiveReward;
|
||||
}
|
||||
|
||||
public boolean isExplosiveReward() {
|
||||
return isExplosiveReward;
|
||||
}
|
||||
|
||||
public void setRemoveOnMiss(boolean removeOnMiss) {
|
||||
this.removeOnMiss = removeOnMiss;
|
||||
}
|
||||
|
||||
public boolean removeOnMiss() {
|
||||
return removeOnMiss;
|
||||
}
|
||||
|
||||
public void setCool(Pair<Integer, Integer> cool) {
|
||||
this.cool = cool;
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getCool() {
|
||||
return cool;
|
||||
}
|
||||
|
||||
public int getPDDamage() {
|
||||
return PDDamage;
|
||||
}
|
||||
|
||||
public int getMADamage() {
|
||||
return MADamage;
|
||||
}
|
||||
|
||||
public int getMDDamage() {
|
||||
return MDDamage;
|
||||
}
|
||||
|
||||
public boolean isFriendly() {
|
||||
return friendly;
|
||||
}
|
||||
|
||||
public void setFriendly(boolean value) {
|
||||
this.friendly = value;
|
||||
}
|
||||
|
||||
public void setPDDamage(int PDDamage) {
|
||||
this.PDDamage = PDDamage;
|
||||
}
|
||||
|
||||
public void setMADamage(int MADamage) {
|
||||
this.MADamage = MADamage;
|
||||
}
|
||||
|
||||
public void setMDDamage(int MDDamage) {
|
||||
this.MDDamage = MDDamage;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public interface MapleCanvas {
|
||||
int getHeight();
|
||||
int getWidth();
|
||||
BufferedImage getImage();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
import java.util.List;
|
||||
import provider.wz.MapleDataType;
|
||||
|
||||
public interface MapleData extends MapleDataEntity, Iterable<MapleData> {
|
||||
@Override
|
||||
public String getName();
|
||||
public MapleDataType getType();
|
||||
public List<MapleData> getChildren();
|
||||
public MapleData getChildByPath(String path);
|
||||
public Object getData();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public interface MapleDataDirectoryEntry extends MapleDataEntry {
|
||||
public List<MapleDataDirectoryEntry> getSubdirectories();
|
||||
public List<MapleDataFileEntry> getFiles();
|
||||
public MapleDataEntry getEntry(String name);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public interface MapleDataEntity {
|
||||
public String getName();
|
||||
public MapleDataEntity getParent();
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public interface MapleDataEntry extends MapleDataEntity {
|
||||
public String getName();
|
||||
public int getSize();
|
||||
public int getChecksum();
|
||||
public int getOffset();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public interface MapleDataFileEntry extends MapleDataEntry {
|
||||
public void setOffset(int offset);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
public interface MapleDataProvider {
|
||||
MapleData getData(String path);
|
||||
MapleDataDirectoryEntry getRoot();
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import provider.wz.WZFile;
|
||||
import provider.wz.XMLWZFile;
|
||||
|
||||
public class MapleDataProviderFactory {
|
||||
private final static String wzPath = System.getProperty("wzpath");
|
||||
|
||||
private static MapleDataProvider getWZ(File in, boolean provideImages) {
|
||||
if (in.getName().toLowerCase().endsWith("wz") && !in.isDirectory()) {
|
||||
try {
|
||||
return new WZFile(in, provideImages);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Loading WZ File failed", e);
|
||||
}
|
||||
} else {
|
||||
return new XMLWZFile(in);
|
||||
}
|
||||
}
|
||||
|
||||
public static MapleDataProvider getDataProvider(File in) {
|
||||
return getWZ(in, false);
|
||||
}
|
||||
|
||||
public static MapleDataProvider getImageProvidingDataProvider(File in) {
|
||||
return getWZ(in, true);
|
||||
}
|
||||
|
||||
public static File fileInWZPath(String filename) {
|
||||
return new File(wzPath, filename);
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import provider.wz.MapleDataType;
|
||||
|
||||
public class MapleDataTool {
|
||||
public static String getString(MapleData data) {
|
||||
return ((String) data.getData());
|
||||
}
|
||||
|
||||
public static String getString(MapleData data, String def) {
|
||||
if (data == null || data.getData() == null) {
|
||||
return def;
|
||||
} else {
|
||||
return ((String) data.getData());
|
||||
}
|
||||
}
|
||||
|
||||
public static String getString(String path, MapleData data) {
|
||||
return getString(data.getChildByPath(path));
|
||||
}
|
||||
|
||||
public static String getString(String path, MapleData data, String def) {
|
||||
return getString(data.getChildByPath(path), def);
|
||||
}
|
||||
|
||||
public static double getDouble(MapleData data) {
|
||||
return ((Double) data.getData()).doubleValue();
|
||||
}
|
||||
|
||||
public static float getFloat(MapleData data) {
|
||||
return ((Float) data.getData()).floatValue();
|
||||
}
|
||||
|
||||
public static int getInt(MapleData data) {
|
||||
if (data == null || data.getData() == null) {
|
||||
return 0;// DEF?
|
||||
}
|
||||
return ((Integer) data.getData()).intValue();
|
||||
}
|
||||
|
||||
public static int getInt(String path, MapleData data) {
|
||||
return getInt(data.getChildByPath(path));
|
||||
}
|
||||
|
||||
public static int getIntConvert(MapleData data) {
|
||||
if (data.getType() == MapleDataType.STRING) {
|
||||
return Integer.parseInt(getString(data));
|
||||
} else {
|
||||
return getInt(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getIntConvert(String path, MapleData data) {
|
||||
MapleData d = data.getChildByPath(path);
|
||||
if (d.getType() == MapleDataType.STRING) {
|
||||
return Integer.parseInt(getString(d));
|
||||
} else {
|
||||
return getInt(d);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(MapleData data, int def) {
|
||||
if (data == null || data.getData() == null) {
|
||||
return def;
|
||||
} else if (data.getType() == MapleDataType.STRING) {
|
||||
return Integer.parseInt(getString(data));
|
||||
} else {
|
||||
return ((Integer) data.getData()).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(String path, MapleData data, int def) {
|
||||
return getInt(data.getChildByPath(path), def);
|
||||
}
|
||||
|
||||
public static int getIntConvert(String path, MapleData data, int def) {
|
||||
MapleData d = data.getChildByPath(path);
|
||||
if (d == null) {
|
||||
return def;
|
||||
}
|
||||
if (d.getType() == MapleDataType.STRING) {
|
||||
try {
|
||||
return Integer.parseInt(getString(d));
|
||||
} catch (NumberFormatException nfe) {
|
||||
nfe.printStackTrace();
|
||||
return def;
|
||||
}
|
||||
} else {
|
||||
return getInt(d, def);
|
||||
}
|
||||
}
|
||||
|
||||
public static BufferedImage getImage(MapleData data) {
|
||||
return ((MapleCanvas) data.getData()).getImage();
|
||||
}
|
||||
|
||||
public static Point getPoint(MapleData data) {
|
||||
return ((Point) data.getData());
|
||||
}
|
||||
|
||||
public static Point getPoint(String path, MapleData data) {
|
||||
return getPoint(data.getChildByPath(path));
|
||||
}
|
||||
|
||||
public static Point getPoint(String path, MapleData data, Point def) {
|
||||
final MapleData pointData = data.getChildByPath(path);
|
||||
if (pointData == null) {
|
||||
return def;
|
||||
}
|
||||
return getPoint(pointData);
|
||||
}
|
||||
|
||||
public static String getFullDataPath(MapleData data) {
|
||||
String path = "";
|
||||
MapleDataEntity myData = data;
|
||||
while (myData != null) {
|
||||
path = myData.getName() + "/" + path;
|
||||
myData = myData.getParent();
|
||||
}
|
||||
return path.substring(0, path.length() - 1);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import provider.MapleCanvas;
|
||||
|
||||
public class FileStoredPngMapleCanvas implements MapleCanvas {
|
||||
private File file;
|
||||
private int width;
|
||||
private int height;
|
||||
private BufferedImage image;
|
||||
|
||||
public FileStoredPngMapleCanvas(int width, int height, File fileIn) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.file = fileIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
loadImageIfNecessary();
|
||||
return image;
|
||||
}
|
||||
|
||||
private void loadImageIfNecessary() {
|
||||
if (image == null) {
|
||||
try {
|
||||
image = ImageIO.read(file);
|
||||
// replace the dimensions loaded from the wz by the REAL dimensions from the image - should be equal tho
|
||||
width = image.getWidth();
|
||||
height = image.getHeight();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
public class ImgMapleSound {
|
||||
private int dataLength, offset;
|
||||
|
||||
public ImgMapleSound(int dataLength, int offset) {
|
||||
this.dataLength = dataLength;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import tools.data.input.GenericLittleEndianAccessor;
|
||||
import tools.data.input.InputStreamByteStream;
|
||||
import tools.data.input.LittleEndianAccessor;
|
||||
|
||||
public class ListWZFile {
|
||||
private LittleEndianAccessor lea;
|
||||
private List<String> entries = new ArrayList<String>();
|
||||
private static Collection<String> modernImgs = new HashSet<String>();
|
||||
|
||||
public static byte[] xorBytes(byte[] a, byte[] b) {
|
||||
byte[] wusched = new byte[a.length];
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
wusched[i] = (byte) (a[i] ^ b[i]);
|
||||
}
|
||||
return wusched;
|
||||
}
|
||||
|
||||
public ListWZFile(File listwz) throws FileNotFoundException {
|
||||
lea = new GenericLittleEndianAccessor(new InputStreamByteStream(new BufferedInputStream(new FileInputStream(listwz))));
|
||||
while (lea.available() > 0) {
|
||||
int l = lea.readInt() * 2;
|
||||
byte[] chunk = new byte[l];
|
||||
for (int i = 0; i < chunk.length; i++) {
|
||||
chunk[i] = lea.readByte();
|
||||
}
|
||||
lea.readChar();
|
||||
final String value = String.valueOf(WZTool.readListString(chunk));
|
||||
entries.add(value);
|
||||
}
|
||||
entries = Collections.unmodifiableList(entries);
|
||||
}
|
||||
|
||||
public List<String> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
final String listWz = System.getProperty("listwz");
|
||||
if (listWz != null) {
|
||||
ListWZFile listwz;
|
||||
try {
|
||||
listwz = new ListWZFile(MapleDataProviderFactory.fileInWZPath("List.wz"));
|
||||
modernImgs = new HashSet<String>(listwz.getEntries());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isModernImgFile(String path) {
|
||||
return modernImgs.contains(path);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
public enum MapleDataType {
|
||||
NONE, IMG_0x00, SHORT, INT, FLOAT, DOUBLE, STRING, EXTENDED, PROPERTY, CANVAS, VECTOR, CONVEX, SOUND, UOL, UNKNOWN_TYPE, UNKNOWN_EXTENDED_TYPE;
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.image.PixelInterleavedSampleModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Inflater;
|
||||
import provider.MapleCanvas;
|
||||
|
||||
public class PNGMapleCanvas implements MapleCanvas {
|
||||
private static final int[] ZAHLEN = new int[]{2, 1, 0, 3};
|
||||
private int height;
|
||||
private int width;
|
||||
private int dataLength;
|
||||
private int format;
|
||||
private byte[] data;
|
||||
|
||||
public PNGMapleCanvas(int width, int height, int dataLength, int format, byte[] data) {
|
||||
super();
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.dataLength = dataLength;
|
||||
this.format = format;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
private byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getImage() {
|
||||
int sizeUncompressed = 0;
|
||||
int size8888 = 0;
|
||||
int maxWriteBuf = 2;
|
||||
int maxHeight = 3;
|
||||
byte[] writeBuf = new byte[maxWriteBuf];
|
||||
@SuppressWarnings ("unused")
|
||||
byte[] rowPointers = new byte[maxHeight];
|
||||
switch (getFormat()) {
|
||||
case 1:
|
||||
case 513:
|
||||
sizeUncompressed = getHeight() * getWidth() * 4;
|
||||
break;
|
||||
case 2:
|
||||
sizeUncompressed = getHeight() * getWidth() * 8;
|
||||
break;
|
||||
case 517:
|
||||
sizeUncompressed = getHeight() * getWidth() / 128;
|
||||
break;
|
||||
}
|
||||
size8888 = getHeight() * getWidth() * 8;
|
||||
if (size8888 > maxWriteBuf) {
|
||||
maxWriteBuf = size8888;
|
||||
writeBuf = new byte[maxWriteBuf];
|
||||
}
|
||||
if (getHeight() > maxHeight) {
|
||||
maxHeight = getHeight();
|
||||
rowPointers = new byte[maxHeight];
|
||||
}
|
||||
Inflater dec = new Inflater();
|
||||
dec.setInput(getData(), 0, dataLength);
|
||||
int declen = 0;
|
||||
byte[] uc = new byte[sizeUncompressed];
|
||||
try {
|
||||
declen = dec.inflate(uc);
|
||||
} catch (DataFormatException ex) {
|
||||
throw new RuntimeException("zlib fucks", ex);
|
||||
}
|
||||
dec.end();
|
||||
if (getFormat() == 1) {
|
||||
for (int i = 0; i < sizeUncompressed; i++) {
|
||||
byte low = (byte) (uc[i] & 0x0F);
|
||||
byte high = (byte) (uc[i] & 0xF0);
|
||||
writeBuf[(i << 1)] = (byte) (((low << 4) | low) & 0xFF);
|
||||
writeBuf[(i << 1) + 1] = (byte) (high | ((high >>> 4) & 0xF));
|
||||
}
|
||||
} else if (getFormat() == 2) {
|
||||
writeBuf = uc;
|
||||
} else if (getFormat() == 513) {
|
||||
for (int i = 0; i < declen; i += 2) {
|
||||
byte bBits = (byte) ((uc[i] & 0x1F) << 3);
|
||||
byte gBits = (byte) (((uc[i + 1] & 0x07) << 5) | ((uc[i] & 0xE0) >> 3));
|
||||
byte rBits = (byte) (uc[i + 1] & 0xF8);
|
||||
writeBuf[(i << 1)] = (byte) (bBits | (bBits >> 5));
|
||||
writeBuf[(i << 1) + 1] = (byte) (gBits | (gBits >> 6));
|
||||
writeBuf[(i << 1) + 2] = (byte) (rBits | (rBits >> 5));
|
||||
writeBuf[(i << 1) + 3] = (byte) 0xFF;
|
||||
}
|
||||
} else if (getFormat() == 517) {
|
||||
byte b = 0x00;
|
||||
int pixelIndex = 0;
|
||||
for (int i = 0; i < declen; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
b = (byte) (((uc[i] & (0x01 << (7 - j))) >> (7 - j)) * 255);
|
||||
for (int k = 0; k < 16; k++) {
|
||||
pixelIndex = (i << 9) + (j << 6) + k * 2;
|
||||
writeBuf[pixelIndex] = b;
|
||||
writeBuf[pixelIndex + 1] = b;
|
||||
writeBuf[pixelIndex + 2] = b;
|
||||
writeBuf[pixelIndex + 3] = (byte) 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DataBufferByte imgData = new DataBufferByte(writeBuf, sizeUncompressed);
|
||||
SampleModel sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, getWidth(), getHeight(), 4, getWidth() * 4, ZAHLEN);
|
||||
WritableRaster imgRaster = Raster.createWritableRaster(sm, imgData, new Point(0, 0));
|
||||
BufferedImage aa = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
aa.setData(imgRaster);
|
||||
return aa;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import provider.MapleDataDirectoryEntry;
|
||||
import provider.MapleDataEntity;
|
||||
import provider.MapleDataEntry;
|
||||
import provider.MapleDataFileEntry;
|
||||
|
||||
public class WZDirectoryEntry extends WZEntry implements MapleDataDirectoryEntry {
|
||||
private List<MapleDataDirectoryEntry> subdirs = new ArrayList<MapleDataDirectoryEntry>();
|
||||
private List<MapleDataFileEntry> files = new ArrayList<MapleDataFileEntry>();
|
||||
private Map<String, MapleDataEntry> entries = new HashMap<String, MapleDataEntry>();
|
||||
|
||||
public WZDirectoryEntry(String name, int size, int checksum, MapleDataEntity parent) {
|
||||
super(name, size, checksum, parent);
|
||||
}
|
||||
|
||||
public WZDirectoryEntry() {
|
||||
super(null, 0, 0, null);
|
||||
}
|
||||
|
||||
public void addDirectory(MapleDataDirectoryEntry dir) {
|
||||
subdirs.add(dir);
|
||||
entries.put(dir.getName(), dir);
|
||||
}
|
||||
|
||||
public void addFile(MapleDataFileEntry fileEntry) {
|
||||
files.add(fileEntry);
|
||||
entries.put(fileEntry.getName(), fileEntry);
|
||||
}
|
||||
|
||||
public List<MapleDataDirectoryEntry> getSubdirectories() {
|
||||
return Collections.unmodifiableList(subdirs);
|
||||
}
|
||||
|
||||
public List<MapleDataFileEntry> getFiles() {
|
||||
return Collections.unmodifiableList(files);
|
||||
}
|
||||
|
||||
public MapleDataEntry getEntry(String name) {
|
||||
return entries.get(name);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import provider.MapleDataEntity;
|
||||
import provider.MapleDataEntry;
|
||||
|
||||
public class WZEntry implements MapleDataEntry {
|
||||
private String name;
|
||||
private int size;
|
||||
private int checksum;
|
||||
private int offset;
|
||||
private MapleDataEntity parent;
|
||||
|
||||
public WZEntry(String name, int size, int checksum, MapleDataEntity parent) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
this.checksum = checksum;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int getChecksum() {
|
||||
return checksum;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public MapleDataEntity getParent() {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataDirectoryEntry;
|
||||
import provider.MapleDataFileEntry;
|
||||
import provider.MapleDataProvider;
|
||||
import tools.data.input.GenericLittleEndianAccessor;
|
||||
import tools.data.input.GenericSeekableLittleEndianAccessor;
|
||||
import tools.data.input.InputStreamByteStream;
|
||||
import tools.data.input.LittleEndianAccessor;
|
||||
import tools.data.input.RandomAccessByteStream;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public class WZFile implements MapleDataProvider {
|
||||
static {
|
||||
ListWZFile.init();
|
||||
}
|
||||
private File wzfile;
|
||||
private LittleEndianAccessor lea;
|
||||
private SeekableLittleEndianAccessor slea;
|
||||
private int headerSize;
|
||||
private WZDirectoryEntry root;
|
||||
private boolean provideImages;
|
||||
private int cOffset;
|
||||
|
||||
public WZFile(File wzfile, boolean provideImages) throws IOException {
|
||||
this.wzfile = wzfile;
|
||||
lea = new GenericLittleEndianAccessor(new InputStreamByteStream(new BufferedInputStream(new FileInputStream(wzfile))));
|
||||
RandomAccessFile raf = new RandomAccessFile(wzfile, "r");
|
||||
slea = new GenericSeekableLittleEndianAccessor(new RandomAccessByteStream(raf));
|
||||
root = new WZDirectoryEntry(wzfile.getName(), 0, 0, null);
|
||||
this.provideImages = provideImages;
|
||||
load();
|
||||
}
|
||||
|
||||
private void load() throws IOException {
|
||||
lea.readAsciiString(4);
|
||||
lea.readInt();
|
||||
lea.readInt();
|
||||
headerSize = lea.readInt();
|
||||
lea.readNullTerminatedAsciiString();
|
||||
lea.readShort();
|
||||
parseDirectory(root);
|
||||
cOffset = (int) lea.getBytesRead();
|
||||
getOffsets(root);
|
||||
}
|
||||
|
||||
private void getOffsets(MapleDataDirectoryEntry dir) {
|
||||
for (MapleDataFileEntry file : dir.getFiles()) {
|
||||
file.setOffset(cOffset);
|
||||
cOffset += file.getSize();
|
||||
}
|
||||
for (MapleDataDirectoryEntry sdir : dir.getSubdirectories()) {
|
||||
getOffsets(sdir);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDirectory(WZDirectoryEntry dir) {
|
||||
int entries = WZTool.readValue(lea);
|
||||
for (int i = 0; i < entries; i++) {
|
||||
byte marker = lea.readByte();
|
||||
String name = null;
|
||||
int size, checksum;
|
||||
switch (marker) {
|
||||
case 0x02:
|
||||
name = WZTool.readDecodedStringAtOffsetAndReset(slea, lea.readInt() + this.headerSize + 1);
|
||||
size = WZTool.readValue(lea);
|
||||
checksum = WZTool.readValue(lea);
|
||||
lea.readInt(); //dummy int
|
||||
dir.addFile(new WZFileEntry(name, size, checksum, dir));
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
name = WZTool.readDecodedString(lea);
|
||||
size = WZTool.readValue(lea);
|
||||
checksum = WZTool.readValue(lea);
|
||||
lea.readInt(); //dummy int
|
||||
if (marker == 3) {
|
||||
dir.addDirectory(new WZDirectoryEntry(name, size, checksum, dir));
|
||||
} else {
|
||||
dir.addFile(new WZFileEntry(name, size, checksum, dir));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
for (MapleDataDirectoryEntry idir : dir.getSubdirectories()) {
|
||||
parseDirectory((WZDirectoryEntry) idir);
|
||||
}
|
||||
}
|
||||
|
||||
public WZIMGFile getImgFile(String path) throws IOException {
|
||||
String segments[] = path.split("/");
|
||||
WZDirectoryEntry dir = root;
|
||||
for (int x = 0; x < segments.length - 1; x++) {
|
||||
dir = (WZDirectoryEntry) dir.getEntry(segments[x]);
|
||||
if (dir == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
WZFileEntry entry = (WZFileEntry) dir.getEntry(segments[segments.length - 1]);
|
||||
if (entry == null) {
|
||||
return null;
|
||||
}
|
||||
String fullPath = wzfile.getName().substring(0, wzfile.getName().length() - 3).toLowerCase() + "/" + path;
|
||||
return new WZIMGFile(this.wzfile, entry, provideImages, ListWZFile.isModernImgFile(fullPath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized MapleData getData(String path) {
|
||||
try {
|
||||
WZIMGFile imgFile = getImgFile(path);
|
||||
if (imgFile == null) {
|
||||
return null;
|
||||
}
|
||||
MapleData ret = imgFile.getRoot();
|
||||
return ret;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleDataDirectoryEntry getRoot() {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import provider.MapleDataEntity;
|
||||
import provider.MapleDataFileEntry;
|
||||
|
||||
public class WZFileEntry extends WZEntry implements MapleDataFileEntry {
|
||||
private int offset;
|
||||
|
||||
public WZFileEntry(String name, int size, int checksum, MapleDataEntity parent) {
|
||||
super(name, size, checksum, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(int offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataEntity;
|
||||
|
||||
public class WZIMGEntry implements MapleData {
|
||||
private String name;
|
||||
private MapleDataType type;
|
||||
private List<MapleData> children = new ArrayList<MapleData>(10);
|
||||
private Object data;
|
||||
private MapleDataEntity parent;
|
||||
|
||||
public WZIMGEntry(MapleDataEntity parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleDataType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MapleData> getChildren() {
|
||||
return Collections.unmodifiableList(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleData getChildByPath(String path) {
|
||||
String segments[] = path.split("/");
|
||||
if (segments[0].equals("..")) {
|
||||
return ((MapleData) getParent()).getChildByPath(path.substring(path.indexOf("/") + 1));
|
||||
}
|
||||
MapleData ret = this;
|
||||
for (int x = 0; x < segments.length; x++) {
|
||||
boolean foundChild = false;
|
||||
for (MapleData child : ret.getChildren()) {
|
||||
if (child.getName().equals(segments[x])) {
|
||||
ret = child;
|
||||
foundChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundChild) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setType(MapleDataType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setData(Object data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void addChild(WZIMGEntry entry) {
|
||||
children.add(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<MapleData> iterator() {
|
||||
return getChildren().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + ":" + getData();
|
||||
}
|
||||
|
||||
public MapleDataEntity getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
((ArrayList<MapleData>) children).trimToSize();
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import tools.data.input.GenericSeekableLittleEndianAccessor;
|
||||
import tools.data.input.RandomAccessByteStream;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public class WZIMGFile {
|
||||
private WZFileEntry file;
|
||||
private WZIMGEntry root;
|
||||
private boolean provideImages;
|
||||
@SuppressWarnings ("unused")
|
||||
private boolean modernImg;
|
||||
|
||||
public WZIMGFile(File wzfile, WZFileEntry file, boolean provideImages, boolean modernImg) throws IOException {
|
||||
RandomAccessFile raf = new RandomAccessFile(wzfile, "r");
|
||||
SeekableLittleEndianAccessor slea = new GenericSeekableLittleEndianAccessor(new RandomAccessByteStream(raf));
|
||||
slea.seek(file.getOffset());
|
||||
this.file = file;
|
||||
this.provideImages = provideImages;
|
||||
root = new WZIMGEntry(file.getParent());
|
||||
root.setName(file.getName());
|
||||
root.setType(MapleDataType.EXTENDED);
|
||||
this.modernImg = modernImg;
|
||||
parseExtended(root, slea, 0);
|
||||
root.finish();
|
||||
raf.close();
|
||||
}
|
||||
|
||||
protected void dumpImg(OutputStream out, SeekableLittleEndianAccessor slea) throws IOException {
|
||||
DataOutputStream os = new DataOutputStream(out);
|
||||
long oldPos = slea.getPosition();
|
||||
slea.seek(file.getOffset());
|
||||
for (int x = 0; x < file.getSize(); x++) {
|
||||
os.write(slea.readByte());
|
||||
}
|
||||
slea.seek(oldPos);
|
||||
}
|
||||
|
||||
public WZIMGEntry getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
private void parse(WZIMGEntry entry, SeekableLittleEndianAccessor slea) {
|
||||
byte marker = slea.readByte();
|
||||
switch (marker) {
|
||||
case 0: {
|
||||
String name = WZTool.readDecodedString(slea);
|
||||
entry.setName(name);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
String name = WZTool.readDecodedStringAtOffsetAndReset(slea, file.getOffset() + slea.readInt());
|
||||
entry.setName(name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
System.out.println("Unknown Image identifier: " + marker + " at offset " + (slea.getPosition() - file.getOffset()));
|
||||
}
|
||||
marker = slea.readByte();
|
||||
switch (marker) {
|
||||
case 0:
|
||||
entry.setType(MapleDataType.IMG_0x00);
|
||||
break;
|
||||
case 2:
|
||||
case 11: //??? no idea, since 0.49
|
||||
entry.setType(MapleDataType.SHORT);
|
||||
entry.setData(Short.valueOf(slea.readShort()));
|
||||
break;
|
||||
case 3:
|
||||
entry.setType(MapleDataType.INT);
|
||||
entry.setData(Integer.valueOf(WZTool.readValue(slea)));
|
||||
break;
|
||||
case 4:
|
||||
entry.setType(MapleDataType.FLOAT);
|
||||
entry.setData(Float.valueOf(WZTool.readFloatValue(slea)));
|
||||
break;
|
||||
case 5:
|
||||
entry.setType(MapleDataType.DOUBLE);
|
||||
entry.setData(Double.valueOf(slea.readDouble()));
|
||||
break;
|
||||
case 8:
|
||||
entry.setType(MapleDataType.STRING);
|
||||
byte iMarker = slea.readByte();
|
||||
if (iMarker == 0) {
|
||||
entry.setData(WZTool.readDecodedString(slea));
|
||||
} else if (iMarker == 1) {
|
||||
entry.setData(WZTool.readDecodedStringAtOffsetAndReset(slea, slea.readInt() + file.getOffset()));
|
||||
} else {
|
||||
System.out.println("Unknown String type " + iMarker);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
entry.setType(MapleDataType.EXTENDED);
|
||||
long endOfExtendedBlock = slea.readInt();
|
||||
endOfExtendedBlock += slea.getPosition();
|
||||
parseExtended(entry, slea, endOfExtendedBlock);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown Image type " + marker);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseExtended(WZIMGEntry entry, SeekableLittleEndianAccessor slea, long endOfExtendedBlock) {
|
||||
byte marker = slea.readByte();
|
||||
String type;
|
||||
switch (marker) {
|
||||
case 0x73:
|
||||
type = WZTool.readDecodedString(slea);
|
||||
break;
|
||||
case 0x1B:
|
||||
type = WZTool.readDecodedStringAtOffsetAndReset(slea, file.getOffset() + slea.readInt());
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown extended image identifier: " + marker + " at offset " +
|
||||
(slea.getPosition() - file.getOffset()));
|
||||
}
|
||||
if (type.equals("Property")) {
|
||||
entry.setType(MapleDataType.PROPERTY);
|
||||
slea.readByte();
|
||||
slea.readByte();
|
||||
int children = WZTool.readValue(slea);
|
||||
for (int i = 0; i < children; i++) {
|
||||
WZIMGEntry cEntry = new WZIMGEntry(entry);
|
||||
parse(cEntry, slea);
|
||||
cEntry.finish();
|
||||
entry.addChild(cEntry);
|
||||
}
|
||||
} else if (type.equals("Canvas")) {
|
||||
entry.setType(MapleDataType.CANVAS);
|
||||
slea.readByte();
|
||||
marker = slea.readByte();
|
||||
if (marker == 0) {
|
||||
// do nothing
|
||||
} else if (marker == 1) {
|
||||
slea.readByte();
|
||||
slea.readByte();
|
||||
int children = WZTool.readValue(slea);
|
||||
for (int i = 0; i < children; i++) {
|
||||
WZIMGEntry child = new WZIMGEntry(entry);
|
||||
parse(child, slea);
|
||||
child.finish();
|
||||
entry.addChild(child);
|
||||
}
|
||||
} else {
|
||||
System.out.println("Canvas marker != 1 (" + marker + ")");
|
||||
}
|
||||
int width = WZTool.readValue(slea);
|
||||
int height = WZTool.readValue(slea);
|
||||
int format = WZTool.readValue(slea);
|
||||
int format2 = slea.readByte();
|
||||
slea.readInt();
|
||||
int dataLength = slea.readInt() - 1;
|
||||
slea.readByte();
|
||||
if (provideImages) {
|
||||
byte[] pngdata = slea.read(dataLength);
|
||||
entry.setData(new PNGMapleCanvas(width, height, dataLength, format + format2, pngdata));
|
||||
} else {
|
||||
entry.setData(new PNGMapleCanvas(width, height, dataLength, format + format2, null));
|
||||
slea.skip(dataLength);
|
||||
}
|
||||
} else if (type.equals("Shape2D#Vector2D")) {
|
||||
entry.setType(MapleDataType.VECTOR);
|
||||
int x = WZTool.readValue(slea);
|
||||
int y = WZTool.readValue(slea);
|
||||
entry.setData(new Point(x, y));
|
||||
} else if (type.equals("Shape2D#Convex2D")) {
|
||||
int children = WZTool.readValue(slea);
|
||||
for (int i = 0; i < children; i++) {
|
||||
WZIMGEntry cEntry = new WZIMGEntry(entry);
|
||||
parseExtended(cEntry, slea, 0);
|
||||
cEntry.finish();
|
||||
entry.addChild(cEntry);
|
||||
}
|
||||
} else if (type.equals("Sound_DX8")) {
|
||||
entry.setType(MapleDataType.SOUND);
|
||||
slea.readByte();
|
||||
int dataLength = WZTool.readValue(slea);
|
||||
WZTool.readValue(slea); // no clue what this is
|
||||
int offset = (int) slea.getPosition();
|
||||
entry.setData(new ImgMapleSound(dataLength, offset - file.getOffset()));
|
||||
slea.seek(endOfExtendedBlock);
|
||||
} else if (type.equals("UOL")) {
|
||||
entry.setType(MapleDataType.UOL);
|
||||
slea.readByte();
|
||||
byte uolmarker = slea.readByte();
|
||||
switch (uolmarker) {
|
||||
case 0:
|
||||
entry.setData(WZTool.readDecodedString(slea));
|
||||
break;
|
||||
case 1:
|
||||
entry.setData(WZTool.readDecodedStringAtOffsetAndReset(slea, file.getOffset() + slea.readInt()));
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown UOL marker: " + uolmarker + " " + entry.getName());
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled extended type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import tools.data.input.LittleEndianAccessor;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/*
|
||||
* Ported Code, see WZFile.java for more info
|
||||
*/
|
||||
public class WZTool {
|
||||
private static byte[] encKey;
|
||||
|
||||
static {
|
||||
byte[] iv = new byte[]{(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,
|
||||
(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,
|
||||
(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,
|
||||
(byte) 0x4d, (byte) 0x23, (byte) 0xc7, (byte) 0x2b,};
|
||||
byte[] key = new byte[]{(byte) 0x13, 0x00, 0x00, 0x00,
|
||||
(byte) 0x08, 0x00, 0x00, 0x00,
|
||||
(byte) 0x06, 0x00, 0x00, 0x00,
|
||||
(byte) 0xB4, 0x00, 0x00, 0x00,
|
||||
(byte) 0x1B, 0x00, 0x00, 0x00,
|
||||
(byte) 0x0F, 0x00, 0x00, 0x00,
|
||||
(byte) 0x33, 0x00, 0x00, 0x00,
|
||||
(byte) 0x52, 0x00, 0x00, 0x00
|
||||
};
|
||||
Cipher cipher = null;
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
|
||||
try {
|
||||
cipher = Cipher.getInstance("AES");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
encKey = new byte[0xFFFF];
|
||||
for (int i = 0; i < (0xFFFF / 16); i++) {
|
||||
try {
|
||||
iv = cipher.doFinal(iv);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.arraycopy(iv, 0, encKey, (i * 16), 16);
|
||||
}
|
||||
try {
|
||||
iv = cipher.doFinal(iv);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.arraycopy(iv, 0, encKey, 65520, 15);
|
||||
}
|
||||
|
||||
public static byte[] readListString(byte[] str) {
|
||||
for (int i = 0; i < str.length; i++) {
|
||||
str[i] = (byte) (str[i] ^ encKey[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String readDecodedString(LittleEndianAccessor llea) {
|
||||
int strLength;
|
||||
byte b = llea.readByte();
|
||||
if (b == 0x00) {
|
||||
return "";
|
||||
}
|
||||
if (b >= 0) {
|
||||
if (b == 0x7F) {
|
||||
strLength = llea.readInt();
|
||||
} else {
|
||||
strLength = b;
|
||||
}
|
||||
if (strLength < 0) {
|
||||
return "";
|
||||
}
|
||||
byte str[] = new byte[strLength * 2];
|
||||
for (int i = 0; i < strLength * 2; i++) {
|
||||
str[i] = llea.readByte();
|
||||
}
|
||||
return DecryptUnicodeStr(str);
|
||||
} else {
|
||||
if (b == -128) {
|
||||
strLength = llea.readInt();
|
||||
} else {
|
||||
strLength = -b;
|
||||
}
|
||||
if (strLength < 0) {
|
||||
return "";
|
||||
}
|
||||
byte str[] = new byte[strLength];
|
||||
for (int i = 0; i < strLength; i++) {
|
||||
str[i] = llea.readByte();
|
||||
}
|
||||
return DecryptAsciiStr(str);
|
||||
}
|
||||
}
|
||||
|
||||
public static String DecryptAsciiStr(byte[] str) {
|
||||
byte xorByte = (byte) 0xAA;
|
||||
for (int i = 0; i < str.length; i++) {
|
||||
str[i] = (byte) (str[i] ^ xorByte ^ encKey[i]);
|
||||
xorByte++;
|
||||
}
|
||||
return new String(str);
|
||||
}
|
||||
|
||||
public static String DecryptUnicodeStr(byte[] str) {
|
||||
int xorByte = 0xAAAA;
|
||||
char[] charRet = new char[str.length / 2];
|
||||
for (int i = 0; i < str.length; i++) {
|
||||
str[i] = (byte) (str[i] ^ encKey[i]);
|
||||
}
|
||||
for (int i = 0; i < (str.length / 2); i++) {
|
||||
char toXor = (char) ((str[i] << 8) | str[i + 1]);
|
||||
charRet[i] = (char) (toXor ^ xorByte);
|
||||
xorByte++;
|
||||
}
|
||||
return String.valueOf(charRet);
|
||||
}
|
||||
|
||||
public static String readDecodedStringAtOffset(SeekableLittleEndianAccessor slea, int offset) {
|
||||
slea.seek(offset);
|
||||
return readDecodedString(slea);
|
||||
}
|
||||
|
||||
public static String readDecodedStringAtOffsetAndReset(SeekableLittleEndianAccessor slea, int offset) {
|
||||
long pos = 0;
|
||||
pos = slea.getPosition();
|
||||
slea.seek(offset);
|
||||
String ret = readDecodedString(slea);
|
||||
slea.seek(pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int readValue(LittleEndianAccessor lea) {
|
||||
byte b = lea.readByte();
|
||||
if (b == -128) {
|
||||
return lea.readInt();
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public static float readFloatValue(LittleEndianAccessor lea) {
|
||||
byte b = lea.readByte();
|
||||
if (b == -128) {
|
||||
return lea.readFloat();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.text.NumberFormat;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataEntity;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class XMLDomMapleData implements MapleData {
|
||||
private Node node;
|
||||
private File imageDataDir;
|
||||
private NumberFormat nf;
|
||||
|
||||
public XMLDomMapleData(FileInputStream fis, File imageDataDir) {
|
||||
try {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document document = documentBuilder.parse(fis);
|
||||
this.node = document.getFirstChild();
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (SAXException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.imageDataDir = imageDataDir;
|
||||
this.nf = NumberFormat.getInstance(Locale.FRANCE);
|
||||
}
|
||||
|
||||
private XMLDomMapleData(Node node) {
|
||||
this.node = node;
|
||||
this.nf = NumberFormat.getInstance(Locale.FRANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleData getChildByPath(String path) {
|
||||
String segments[] = path.split("/");
|
||||
if (segments[0].equals("..")) {
|
||||
return ((MapleData) getParent()).getChildByPath(path.substring(path.indexOf("/") + 1));
|
||||
}
|
||||
|
||||
Node myNode = node;
|
||||
for (int x = 0; x < segments.length; x++) {
|
||||
NodeList childNodes = myNode.getChildNodes();
|
||||
boolean foundChild = false;
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node childNode = childNodes.item(i);
|
||||
if (childNode.getNodeType() == Node.ELEMENT_NODE && childNode.getAttributes().getNamedItem("name").getNodeValue().equals(segments[x])) {
|
||||
myNode = childNode;
|
||||
foundChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundChild) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
XMLDomMapleData ret = new XMLDomMapleData(myNode);
|
||||
ret.imageDataDir = new File(imageDataDir, getName() + "/" + path).getParentFile();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MapleData> getChildren() {
|
||||
List<MapleData> ret = new ArrayList<MapleData>();
|
||||
NodeList childNodes = node.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node childNode = childNodes.item(i);
|
||||
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
XMLDomMapleData child = new XMLDomMapleData(childNode);
|
||||
child.imageDataDir = new File(imageDataDir, getName());
|
||||
ret.add(child);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getData() {
|
||||
NamedNodeMap attributes = node.getAttributes();
|
||||
MapleDataType type = getType();
|
||||
switch (type) {
|
||||
case DOUBLE:
|
||||
case FLOAT:
|
||||
case INT:
|
||||
case SHORT: {
|
||||
String value = attributes.getNamedItem("value").getNodeValue();
|
||||
Number nval;
|
||||
|
||||
try {
|
||||
nval = nf.parse(value);
|
||||
}
|
||||
catch(java.text.ParseException pe) {
|
||||
pe.printStackTrace();
|
||||
nval = 0.0f;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DOUBLE:
|
||||
return nval.doubleValue();
|
||||
case FLOAT:
|
||||
return nval.floatValue();
|
||||
case INT:
|
||||
return nval.intValue();
|
||||
case SHORT:
|
||||
return nval.shortValue();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
case STRING:
|
||||
case UOL: {
|
||||
String value = attributes.getNamedItem("value").getNodeValue();
|
||||
return value;
|
||||
}
|
||||
case VECTOR: {
|
||||
String x = attributes.getNamedItem("x").getNodeValue();
|
||||
String y = attributes.getNamedItem("y").getNodeValue();
|
||||
return new Point(Integer.parseInt(x), Integer.parseInt(y));
|
||||
}
|
||||
case CANVAS: {
|
||||
String width = attributes.getNamedItem("width").getNodeValue();
|
||||
String height = attributes.getNamedItem("height").getNodeValue();
|
||||
return new FileStoredPngMapleCanvas(Integer.parseInt(width), Integer.parseInt(height), new File(
|
||||
imageDataDir, getName() + ".png"));
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleDataType getType() {
|
||||
String nodeName = node.getNodeName();
|
||||
if (nodeName.equals("imgdir")) {
|
||||
return MapleDataType.PROPERTY;
|
||||
} else if (nodeName.equals("canvas")) {
|
||||
return MapleDataType.CANVAS;
|
||||
} else if (nodeName.equals("convex")) {
|
||||
return MapleDataType.CONVEX;
|
||||
} else if (nodeName.equals("sound")) {
|
||||
return MapleDataType.SOUND;
|
||||
} else if (nodeName.equals("uol")) {
|
||||
return MapleDataType.UOL;
|
||||
} else if (nodeName.equals("double")) {
|
||||
return MapleDataType.DOUBLE;
|
||||
} else if (nodeName.equals("float")) {
|
||||
return MapleDataType.FLOAT;
|
||||
} else if (nodeName.equals("int")) {
|
||||
return MapleDataType.INT;
|
||||
} else if (nodeName.equals("short")) {
|
||||
return MapleDataType.SHORT;
|
||||
} else if (nodeName.equals("string")) {
|
||||
return MapleDataType.STRING;
|
||||
} else if (nodeName.equals("vector")) {
|
||||
return MapleDataType.VECTOR;
|
||||
} else if (nodeName.equals("null")) {
|
||||
return MapleDataType.IMG_0x00;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleDataEntity getParent() {
|
||||
Node parentNode = node.getParentNode();
|
||||
if (parentNode.getNodeType() == Node.DOCUMENT_NODE) {
|
||||
return null;
|
||||
}
|
||||
XMLDomMapleData parentData = new XMLDomMapleData(parentNode);
|
||||
parentData.imageDataDir = imageDataDir.getParentFile();
|
||||
return parentData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return node.getAttributes().getNamedItem("name").getNodeValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<MapleData> iterator() {
|
||||
return getChildren().iterator();
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 provider.wz;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataDirectoryEntry;
|
||||
import provider.MapleDataProvider;
|
||||
|
||||
public class XMLWZFile implements MapleDataProvider {
|
||||
private File root;
|
||||
private WZDirectoryEntry rootForNavigation;
|
||||
|
||||
public XMLWZFile(File fileIn) {
|
||||
root = fileIn;
|
||||
rootForNavigation = new WZDirectoryEntry(fileIn.getName(), 0, 0, null);
|
||||
fillMapleDataEntitys(root, rootForNavigation);
|
||||
}
|
||||
|
||||
private void fillMapleDataEntitys(File lroot, WZDirectoryEntry wzdir) {
|
||||
for (File file : lroot.listFiles()) {
|
||||
String fileName = file.getName();
|
||||
if (file.isDirectory() && !fileName.endsWith(".img")) {
|
||||
WZDirectoryEntry newDir = new WZDirectoryEntry(fileName, 0, 0, wzdir);
|
||||
wzdir.addDirectory(newDir);
|
||||
fillMapleDataEntitys(file, newDir);
|
||||
} else if (fileName.endsWith(".xml")) {
|
||||
wzdir.addFile(new WZFileEntry(fileName.substring(0, fileName.length() - 4), 0, 0, wzdir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleData getData(String path) {
|
||||
File dataFile = new File(root, path + ".xml");
|
||||
File imageDataDir = new File(root, path);
|
||||
if (!dataFile.exists()) {
|
||||
return null;//bitches
|
||||
}
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream(dataFile);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException("Datafile " + path + " does not exist in " + root.getAbsolutePath());
|
||||
}
|
||||
final XMLDomMapleData domMapleData;
|
||||
try {
|
||||
domMapleData = new XMLDomMapleData(fis, imageDataDir.getParentFile());
|
||||
} finally {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return domMapleData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleDataDirectoryEntry getRoot() {
|
||||
return rootForNavigation;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package tools;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author Frz (Big Daddy)
|
||||
* @author The Real Spookster - some modifications to this beautiful code
|
||||
*/
|
||||
public class DatabaseConnection {
|
||||
private static String DB_URL = "jdbc:mysql://localhost:3306/cosmic";
|
||||
private static String DB_USER = "cosmic_server";
|
||||
private static String DB_PASS = "snailshell";
|
||||
|
||||
public static final int RETURN_GENERATED_KEYS = 1;
|
||||
|
||||
private static ThreadLocal<Connection> con = new ThreadLocalConnection();
|
||||
|
||||
public static Connection getConnection() {
|
||||
Connection c = con.get();
|
||||
try {
|
||||
c.getMetaData();
|
||||
} catch (SQLException e) { // connection is dead, therefore discard old object 5ever
|
||||
con.remove();
|
||||
c = con.get();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private static class ThreadLocalConnection extends ThreadLocal<Connection> {
|
||||
|
||||
@Override
|
||||
protected Connection initialValue() {
|
||||
try {
|
||||
Class.forName("com.mysql.jdbc.Driver"); // touch the mysql driver
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.out.println("[SEVERE] SQL Driver Not Found. Consider death by clams.");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
|
||||
} catch (SQLException e) {
|
||||
System.out.println("[SEVERE] Unable to make database connection.");
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 tools;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class HexTool {
|
||||
private static final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
private static String toString(byte byteValue) {
|
||||
int tmp = byteValue << 8;
|
||||
char[] retstr = new char[]{HEX[(tmp >> 12) & 0x0F], HEX[(tmp >> 8) & 0x0F]};
|
||||
return String.valueOf(retstr);
|
||||
}
|
||||
|
||||
public static String toString(byte[] bytes) {
|
||||
StringBuilder hexed = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
hexed.append(toString(bytes[i]));
|
||||
hexed.append(' ');
|
||||
}
|
||||
return hexed.substring(0, hexed.length() - 1);
|
||||
}
|
||||
|
||||
public static byte[] getByteArrayFromHexString(String hex) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int nexti = 0;
|
||||
int nextb = 0;
|
||||
boolean highoc = true;
|
||||
outer:
|
||||
for (;;) {
|
||||
int number = -1;
|
||||
while (number == -1) {
|
||||
if (nexti == hex.length()) {
|
||||
break outer;
|
||||
}
|
||||
char chr = hex.charAt(nexti);
|
||||
if (chr >= '0' && chr <= '9') {
|
||||
number = chr - '0';
|
||||
} else if (chr >= 'a' && chr <= 'f') {
|
||||
number = chr - 'a' + 10;
|
||||
} else if (chr >= 'A' && chr <= 'F') {
|
||||
number = chr - 'A' + 10;
|
||||
} else {
|
||||
number = -1;
|
||||
}
|
||||
nexti++;
|
||||
}
|
||||
if (highoc) {
|
||||
nextb = number << 4;
|
||||
highoc = false;
|
||||
} else {
|
||||
nextb |= number;
|
||||
highoc = true;
|
||||
baos.write(nextb);
|
||||
}
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -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 tools;
|
||||
|
||||
/**
|
||||
* 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,72 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 tools.data.input;
|
||||
|
||||
import java.io.IOException;
|
||||
import tools.HexTool;
|
||||
|
||||
public class ByteArrayByteStream implements SeekableInputStreamBytestream {
|
||||
private int pos = 0;
|
||||
private long bytesRead = 0;
|
||||
private byte[] arr;
|
||||
|
||||
public ByteArrayByteStream(byte[] arr) {
|
||||
this.arr = arr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPosition() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(long offset) throws IOException {
|
||||
pos = (int) offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBytesRead() {
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readByte() {
|
||||
bytesRead++;
|
||||
return ((int) arr[pos++]) & 0xFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String nows = "kevintjuh93 pwns";//I lol'd
|
||||
if (arr.length - pos > 0) {
|
||||
byte[] now = new byte[arr.length - pos];
|
||||
System.arraycopy(arr, pos, now, 0, arr.length - pos);
|
||||
nows = HexTool.toString(now);
|
||||
}
|
||||
return "All: " + HexTool.toString(arr) + "\nNow: " + nows;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long available() {
|
||||
return arr.length - pos;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 tools.data.input;
|
||||
|
||||
/**
|
||||
* Represents an abstract stream of bytes.
|
||||
*
|
||||
* @author Frz
|
||||
* @version 1.0
|
||||
* @since Revision 323
|
||||
*/
|
||||
public interface ByteInputStream {
|
||||
int readByte();
|
||||
long getBytesRead();
|
||||
long available();
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 tools.data.input;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* Provides a generic interface to a Little Endian stream of bytes.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Frz
|
||||
* @since Revision 323
|
||||
*/
|
||||
public class GenericLittleEndianAccessor implements LittleEndianAccessor {
|
||||
private ByteInputStream bs;
|
||||
|
||||
/**
|
||||
* Class constructor - Wraps the accessor around a stream of bytes.
|
||||
*
|
||||
* @param bs The byte stream to wrap the accessor around.
|
||||
*/
|
||||
public GenericLittleEndianAccessor(ByteInputStream bs) {
|
||||
this.bs = bs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single byte from the stream.
|
||||
*
|
||||
* @return The byte read.
|
||||
* @see tools.data.input.ByteInputStream#readByte
|
||||
*/
|
||||
@Override
|
||||
public byte readByte() {
|
||||
return (byte) bs.readByte();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an integer from the stream.
|
||||
*
|
||||
* @return The integer read.
|
||||
*/
|
||||
@Override
|
||||
public int readInt() {
|
||||
return bs.readByte() + (bs.readByte() << 8) + (bs.readByte() << 16) + (bs.readByte() << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a short integer from the stream.
|
||||
*
|
||||
* @return The short read.
|
||||
*/
|
||||
@Override
|
||||
public short readShort() {
|
||||
return (short) (bs.readByte() + (bs.readByte() << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a single character from the stream.
|
||||
*
|
||||
* @return The character read.
|
||||
*/
|
||||
@Override
|
||||
public char readChar() {
|
||||
return (char) readShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a long integer from the stream.
|
||||
*
|
||||
* @return The long integer read.
|
||||
*/
|
||||
@Override
|
||||
public long readLong() {
|
||||
long byte1 = bs.readByte();
|
||||
long byte2 = bs.readByte();
|
||||
long byte3 = bs.readByte();
|
||||
long byte4 = bs.readByte();
|
||||
long byte5 = bs.readByte();
|
||||
long byte6 = bs.readByte();
|
||||
long byte7 = bs.readByte();
|
||||
long byte8 = bs.readByte();
|
||||
return (byte8 << 56) + (byte7 << 48) + (byte6 << 40) + (byte5 << 32) + (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a floating point integer from the stream.
|
||||
*
|
||||
* @return The float-type integer read.
|
||||
*/
|
||||
@Override
|
||||
public float readFloat() {
|
||||
return Float.intBitsToFloat(readInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a double-precision integer from the stream.
|
||||
*
|
||||
* @return The double-type integer read.
|
||||
*/
|
||||
@Override
|
||||
public double readDouble() {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an ASCII string from the stream with length <code>n</code>.
|
||||
*
|
||||
* @param n Number of characters to read.
|
||||
* @return The string read.
|
||||
*/
|
||||
public final String readAsciiString(int n) {
|
||||
char ret[] = new char[n];
|
||||
for (int x = 0; x < n; x++) {
|
||||
ret[x] = (char) readByte();
|
||||
}
|
||||
return String.valueOf(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a null-terminated string from the stream.
|
||||
*
|
||||
* @return The string read.
|
||||
*/
|
||||
public final String readNullTerminatedAsciiString() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte b;
|
||||
while (true) {
|
||||
b = readByte();
|
||||
if (b == 0) {
|
||||
break;
|
||||
}
|
||||
baos.write(b);
|
||||
}
|
||||
byte[] buf = baos.toByteArray();
|
||||
char[] chrBuf = new char[buf.length];
|
||||
for (int x = 0; x < buf.length; x++) {
|
||||
chrBuf[x] = (char) buf[x];
|
||||
}
|
||||
return String.valueOf(chrBuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of bytes read from the stream so far.
|
||||
*
|
||||
* @return A long integer representing the number of bytes read.
|
||||
* @see tools.data.input.ByteInputStream#getBytesRead()
|
||||
*/
|
||||
public long getBytesRead() {
|
||||
return bs.getBytesRead();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a MapleStory convention lengthed ASCII string.
|
||||
* This consists of a short integer telling the length of the string,
|
||||
* then the string itself.
|
||||
*
|
||||
* @return The string read.
|
||||
*/
|
||||
@Override
|
||||
public String readMapleAsciiString() {
|
||||
return readAsciiString(readShort());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads <code>num</code> bytes off the stream.
|
||||
*
|
||||
* @param num The number of bytes to read.
|
||||
* @return An array of bytes with the length of <code>num</code>
|
||||
*/
|
||||
@Override
|
||||
public byte[] read(int num) {
|
||||
byte[] ret = new byte[num];
|
||||
for (int x = 0; x < num; x++) {
|
||||
ret[x] = readByte();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a MapleStory Position information.
|
||||
* This consists of 2 short integer.
|
||||
*
|
||||
* @return The Position read.
|
||||
*/
|
||||
@Override
|
||||
public final Point readPos() {
|
||||
final int x = readShort();
|
||||
final int y = readShort();
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the current position of the stream <code>num</code> bytes ahead.
|
||||
*
|
||||
* @param num Number of bytes to skip.
|
||||
*/
|
||||
@Override
|
||||
public void skip(int num) {
|
||||
for (int x = 0; x < num; x++) {
|
||||
readByte();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see tools.data.input.ByteInputStream#available
|
||||
*/
|
||||
@Override
|
||||
public long available() {
|
||||
return bs.available();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return bs.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 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 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 tools.data.input;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Provides an abstract accessor to a generic Little Endian byte stream. This
|
||||
* accessor is seekable.
|
||||
*
|
||||
* @author Frz
|
||||
* @version 1.0
|
||||
* @since Revision 323
|
||||
* @see tools.data.input.GenericLittleEndianAccessor
|
||||
*/
|
||||
public class GenericSeekableLittleEndianAccessor extends GenericLittleEndianAccessor implements SeekableLittleEndianAccessor {
|
||||
private SeekableInputStreamBytestream bs;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Provide a seekable input stream to wrap this object around.
|
||||
*
|
||||
* @param bs The byte stream to wrap this around.
|
||||
*/
|
||||
public GenericSeekableLittleEndianAccessor(SeekableInputStreamBytestream bs) {
|
||||
super(bs);
|
||||
this.bs = bs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek the pointer to <code>offset</code>
|
||||
*
|
||||
* @param offset The offset to seek to.
|
||||
* @see tools.data.input.SeekableInputStreamBytestream#seek
|
||||
*/
|
||||
@Override
|
||||
public void seek(long offset) {
|
||||
try {
|
||||
bs.seek(offset);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Seek failed " + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position of the pointer.
|
||||
*
|
||||
* @return The current position of the pointer as a long integer.
|
||||
* @see tools.data.input.SeekableInputStreamBytestream#getPosition
|
||||
*/
|
||||
@Override
|
||||
public long getPosition() {
|
||||
try {
|
||||
return bs.getPosition();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("getPosition failed" + e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip <code>num</code> number of bytes in the stream.
|
||||
*
|
||||
* @param num The number of bytes to skip.
|
||||
*/
|
||||
@Override
|
||||
public void skip(int num) {
|
||||
seek(getPosition() + num);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user