Quest & Command tweak + MapleCashDropFetcher + Cash drop tidyup

Solved a possible exploit on starting/completing non-scripted quests.
Added missing drop data for Aran's puppeteer questline.
Moved GM tier level of some commands.
Applied proper synchronization for BuddyList modules.
Issued commands now requires "@" heading for normal players and donators (GM level < 2) and "!" for Jr. GM and above (GM level >= 2).
Added custom feature: a message will be sent to acquaintances of a player (friends, family, guild, spouse) when they change/upgrade jobs.
Removed cash drop entries from the DB.
New tool: MapleCashDropFetcher. Reports on a text file all cash-type drop data on DB.
This commit is contained in:
ronancpl
2018-04-14 13:38:14 -03:00
parent 6d91c79f28
commit 6a63f9d95e
38 changed files with 3472 additions and 1057 deletions

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="MapleCashDropFetcher" default="default" basedir=".">
<description>Builds, tests, and runs the project MapleCashDropFetcher.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="MapleCashDropFetcher-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@@ -0,0 +1,11 @@
# Report File autogenerated from the MapleCashDropFetcher feature by Ronan Lana.
# Generated data takes into account several data info from the underlying DB and the server-side WZ.xmls.
NX DROPS ON drop_data
5240005 : 2100100
5490000 : 9410066
5490001 : 9410066

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
build.xml.data.CRC32=928d5bb0
build.xml.script.CRC32=27a7b03c
build.xml.stylesheet.CRC32=8064a381@1.75.2.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=928d5bb0
nbproject/build-impl.xml.script.CRC32=34e6e8ba
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48

View File

@@ -0,0 +1,77 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=MapleCashDropFetcher
application.vendor=USER
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Os arquivos em build.classes.dir que devem ser exclu\u00eddos do jar de distribui\u00e7\u00e3o
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/MapleCashDropFetcher.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
file.reference.mysql-connector-java-bin.jar=../../cores/mysql-connector-java-bin.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.mysql-connector-java-bin.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
javac.source=1.7
javac.target=1.7
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=maplecashdropfetcher.MapleCashDropFetcher
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=JDK_1.7
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>MapleCashDropFetcher</name>
<explicit-platform explicit-source-supported="true"/>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@@ -0,0 +1,406 @@
/*
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
Copyleft (L) 2017 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 maplecashdropfetcher;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
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;
/**
*
* @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
*/
public class MapleCashDropFetcher {
static String host = "jdbc:mysql://localhost:3306/heavenms";
static String driver = "com.mysql.jdbc.Driver";
static String username = "root";
static String password = "";
static String wzPath = "../../wz";
static String directoryName = "../..";
static String newFile = "lib/CashDropReport.txt";
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 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];
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[initialStringLength];
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 inspectEquipWzEntry() {
String line = null;
try {
while((line = bufferedReader.readLine()) != null) {
translateEquipToken(line);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
private static void translateEquipToken(String token) {
if(token.contains("/imgdir")) {
status -= 1;
}
else if(token.contains("imgdir")) {
if(status == 1) {
if(!getName(token).equals("info")) {
forwardCursor(status);
}
}
status += 1;
}
else {
if(status == 2) {
String d = getName(token);
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) {
translateItemToken(line);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
private static void translateItemToken(String token) {
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")) {
forwardCursor(status);
}
}
status += 1;
}
else {
if(status == 3) {
String d = getName(token);
if(d.equals("cash")) {
if(!getValue(token).equals("0")) {
nxItems.add(currentItemid);
}
forwardCursor(status);
}
}
}
}
private static void printReportFileHeader() {
printWriter.println(" # Report File autogenerated from the MapleCashDropFetcher feature by Ronan Lana.");
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);
// 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 int getItemIdFromFilename(String name) {
try {
return Integer.valueOf(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()) {
int itemid = rs.getInt("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) {
PreparedStatement ps = con.prepareStatement("SELECT " + getDropElementName(dropdata) + " FROM " + getDropTableName(dropdata) + " WHERE itemid = ?");
ps.setInt(1, nx);
ResultSet rs = ps.executeQuery();
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()) {
List<Pair<Integer, Integer>> nxEntries = getNxDropsEntries(dropdata);
printWriter.println("NX DROPS ON " + getDropTableName(dropdata));
for(Pair<Integer, Integer> nx : nxEntries) {
printWriter.println(nx.left + " : " + nx.right);
}
printWriter.println("\n\n\n");
}
}
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) {
//System.out.println("Parsing " + f.getAbsolutePath());
int itemid = getItemIdFromFilename(f.getName());
if(itemid < 0) {
continue;
}
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
bufferedReader = new BufferedReader(fileReader);
currentItemid = itemid;
inspectEquipWzEntry();
bufferedReader.close();
fileReader.close();
}
System.out.println("Reading Item.wz ...");
files = new ArrayList<>();
listFiles(wzPath + "/Item.wz", files);
for(File f : files) {
//System.out.println("Parsing " + f.getAbsolutePath());
fileReader = new InputStreamReader(new FileInputStream(f), "UTF-8");
bufferedReader = new BufferedReader(fileReader);
if(f.getName().length() <= itemFileNameSize) {
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) {
continue;
}
currentItemid = itemid;
inspectEquipWzEntry();
}
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");
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) {
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) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ReportNxDropData();
}
}

View File

@@ -0,0 +1,51 @@
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/heavenms";
private static String DB_USER = "root";
private static String DB_PASS = "";
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;
}
}
}
}

View File

@@ -0,0 +1,121 @@
/*
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 by 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;
}
}

View File

@@ -2,8 +2,6 @@
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/tools/MapleMesoFetcher/src/maplemesofetcher/MapleMesoFetcher.java</file>
</group>
<group/>
</open-files>
</project-private>

View File

@@ -2,33 +2,28 @@
# Generated data takes into account several data info from the underlying DB and the server-side WZ.xmls.
INCORRECT QUESTIDS ON DB
4001342 : 7777 -> 28175
2022055 : -1 -> 9330 EXPIRED
2022056 : -1 -> 9330 EXPIRED
4001352 : 28205 -> 28206
4001366 : 28194 -> 28195
4001367 : 28257 -> 28262
4001368 : 28258 -> 28262
4001369 : 28259 -> 28262
4001370 : 28260 -> 28262
4001371 : 28261 -> 28262
4001372 : 28344 -> 28282
4031107 : -1 -> 3409
4031116 : -1 -> 3419
4031130 : 0 -> 3238
4031164 : 0 -> 2084
4031171 : 0 -> 7101
4031172 : 7103 -> 7106
4031189 : 0 -> 3448
4031218 : 0 -> 3071
4031223 : 3607 -> 3608
4031343 : 6904 -> 6905
4031344 : 6904 -> 6905
4031405 : 0 -> 4207
4031405 : 0 -> 4207 EXPIRED
4031511 : 6904 -> 6914
4031512 : 6914 -> 6915
4031514 : 6924 -> 6925
4031515 : 6924 -> 6925
4031517 : 6934 -> 6935
4031518 : 6934 -> 6935
4031856 : 0 -> 2191
4031857 : 0 -> 2192
4031860 : 6944 -> 6945
4031861 : 6944 -> 6945
4031871 : 6350 -> 28344
4032319 : -1 -> 21723
4032324 : 21736 -> 21737
4032339 : 0 -> 21303
@@ -38,283 +33,195 @@ INCORRECT QUESTIDS ON DB
ITEMS WITH NO QUEST DROP DATA ON DB
1002436 - 2075
1102057 - 7103
1102061 - 3066
1302014 - 2048
2022053 - 9330
2022054 - 9330
2022055 - 9330
2022056 - 9330
2022057 - 9332
2022281 - 8569
2100016 - 3223
2100017 - 3419
2100018 - 3236
2100019 - 3238
3994139 - 10360
4001118 - 3814
4001340 - 28167
4001347 - 28229
4001348 - 28231
4001349 - 28235
4001350 - 28235
4001351 - 28237
4001352 - 28206
2022053 - 9330 EXPIRED
2022054 - 9330 EXPIRED
2022057 - 9332 EXPIRED
3994139 - 10360 EXPIRED
4000142 - 1018
4001353 - 28227
4001366 - 28195
4031014 - 2020
4031015 - 2022
4031019 - 9411
4031015 - 2020
4031020 - 2050
4031025 - 2052
4031026 - 2053
4031028 - 2054
4031032 - 2051
4031039 - 2055
4031040 - 2056
4031041 - 2057
4031042 - 2035
4031063 - 9260
4031063 - 9260 EXPIRED
4031064 - 8012
4031107 - 3409
4031116 - 3419
4031117 - 3421
4031122 - 9340
4031124 - 9340
4031134 - 3443
4031136 - 3439
4031141 - 3407
4031142 - 3407
4031143 - 3407
4031122 - 9340 EXPIRED
4031124 - 9340 EXPIRED
4031144 - 2047
4031150 - 2067
4031157 - 2074
4031158 - 2074
4031165 - 2086
4031167 - 9052
4031168 - 9055
4031169 - 9058
4031167 - 9052 EXPIRED
4031168 - 9055 EXPIRED
4031169 - 9058 EXPIRED
4031180 - 8020
4031181 - 9140
4031182 - 9140
4031183 - 9140
4031184 - 9150
4031185 - 9150
4031186 - 9150
4031190 - 3054
4031181 - 9140 EXPIRED
4031182 - 9140 EXPIRED
4031183 - 9140 EXPIRED
4031184 - 9150 EXPIRED
4031185 - 9150 EXPIRED
4031186 - 9150 EXPIRED
4031190 - 3055
4031191 - 3063
4031192 - 8700
4031198 - 3043
4031199 - 3046
4031200 - 3069
4031192 - 8700 EXPIRED
4031199 - 3045
4031201 - 3048
4031202 - 3050
4031207 - 3443
4031220 - 9210
4031225 - 3606
4031226 - 9321
4031220 - 9210 EXPIRED
4031226 - 9321 EXPIRED
4031227 - 4103 EXPIRED
4031230 - 3619
4031231 - 3620
4031235 - 3607
4031235 - 3615
4031236 - 3616
4031237 - 3605
4031238 - 3611
4031237 - 3617
4031238 - 3618
4031243 - 3443
4031257 - 9350
4031258 - 9351
4031270 - 3629
4031271 - 9351
4031272 - 9352
4031274 - 3083
4031275 - 3083
4031276 - 3083
4031277 - 3083
4031278 - 3083
4031280 - 3632
4031290 - 4106
4031291 - 4006
4031292 - 4009
4031293 - 4010
4031296 - 4010
4031297 - 9386
4031298 - 3636
4031301 - 9391
4031302 - 9503
4031303 - 4008
4031304 - 9392
4031321 - 9504
4031352 - 4005
4031354 - 4013
4031388 - 4218
4031418 - 8823
4031419 - 8823
4031420 - 8823
4031421 - 8823
4031425 - 8822
4031257 - 9350 EXPIRED
4031270 - 3630
4031271 - 9351 EXPIRED
4031272 - 9352 EXPIRED
4031280 - 3633
4031290 - 4104 EXPIRED
4031291 - 4006 EXPIRED
4031292 - 4006 EXPIRED
4031293 - 4006 EXPIRED
4031296 - 4010 EXPIRED
4031297 - 9386 EXPIRED
4031298 - 3639
4031301 - 9391 EXPIRED
4031302 - 9503 EXPIRED
4031303 - 4007 EXPIRED
4031304 - 9392 EXPIRED
4031321 - 9504 EXPIRED
4031352 - 4005 EXPIRED
4031354 - 4013 EXPIRED
4031388 - 4218 EXPIRED
4031418 - 8823 EXPIRED
4031419 - 8823 EXPIRED
4031420 - 8823 EXPIRED
4031421 - 8823 EXPIRED
4031448 - 6134
4031450 - 6263
4031452 - 6201
4031454 - 6281
4031455 - 6280
4031456 - 6230
4031462 - 6210
4031468 - 6222
4031471 - 6153
4031478 - 6210
4031488 - 6312
4031495 - 6192
4031504 - 9640
4031505 - 9641
4031506 - 9642
4031507 - 6002
4031508 - 6002
4031504 - 9640 EXPIRED
4031505 - 9641 EXPIRED
4031506 - 9642 EXPIRED
4031554 - 3821
4031557 - 9710
4031558 - 9711
4031559 - 9712
4031560 - 9713
4031561 - 9714
4031563 - 8850
4031564 - 8851
4031565 - 8852
4031566 - 8853
4031567 - 8854
4031568 - 3911
4031570 - 3939
4031571 - 3941
4031574 - 3935
4031557 - 9710 EXPIRED
4031558 - 9711 EXPIRED
4031559 - 9712 EXPIRED
4031560 - 9713 EXPIRED
4031561 - 9714 EXPIRED
4031563 - 8855
4031564 - 8856
4031565 - 8857
4031566 - 8858
4031567 - 8859
4031570 - 3938
4031571 - 3940
4031578 - 3923
4031581 - 3937
4031582 - 3901
4031584 - 9731
4031585 - 9732
4031586 - 9740
4031587 - 9741
4031588 - 9742
4031590 - 8881
4031608 - 9803
4031611 - 9804
4031612 - 9805
4031582 - 3949
4031584 - 9731 EXPIRED
4031585 - 9732 EXPIRED
4031586 - 9740 EXPIRED
4031587 - 9741 EXPIRED
4031588 - 9742 EXPIRED
4031590 - 8881 EXPIRED
4031608 - 9803 EXPIRED
4031611 - 9804 EXPIRED
4031612 - 9805 EXPIRED
4031625 - 9820
4031661 - 9861
4031662 - 9866
4031667 - 9863
4031683 - 1115
4031684 - 1116
4031685 - 1117
4031686 - 1118
4031687 - 1119
4031688 - 1120
4031689 - 1121
4031690 - 1122
4031691 - 1123
4031692 - 1124
4031695 - 3335
4031661 - 9861 EXPIRED
4031662 - 9866 EXPIRED
4031667 - 9863 EXPIRED
4031696 - 3334
4031697 - 3322
4031703 - 3302
4031708 - 3309
4031709 - 3310
4031737 - 3343
4031764 - 4949
4031766 - 4959
4031767 - 4947
4031768 - 4953
4031769 - 4946
4031770 - 4946
4031771 - 4944
4031764 - 4949 EXPIRED
4031766 - 4959 EXPIRED
4031767 - 4947 EXPIRED
4031769 - 4946 EXPIRED
4031770 - 4946 EXPIRED
4031772 - 4942
4031774 - 3361
4031785 - 3376
4031789 - 3844
4031796 - 3362
4031797 - 3367
4031798 - 3366
4031801 - 1040
4031806 - 3380
4031812 - 4950
4031833 - 9946
4031837 - 9945
4031806 - 3379
4031812 - 4950 EXPIRED
4031837 - 9942 EXPIRED
4031839 - 2162
4031881 - 4484
4031894 - 2214
4031850 - 2180
4031881 - 4484 EXPIRED
4031921 - 4646
4031927 - 3454
4031928 - 3454
4031945 - 9987
4032037 - 9154
4032038 - 9154
4032039 - 9154
4032055 - 4675
4032087 - 10081
4032092 - 28003
4032119 - 28109
4032037 - 9154 EXPIRED
4032038 - 9154 EXPIRED
4032039 - 9154 EXPIRED
4032087 - 10081 EXPIRED
4032119 - 28109 EXPIRED
4032136 - 20710
4032138 - 20713
4032138 - 20712
4032142 - 20716
4032143 - 20717
4032196 - 20528
4032197 - 20528
4032198 - 20528
4032233 - 8298
4032234 - 8299
4032235 - 8299
4032236 - 8299
4032237 - 8299
4032238 - 8299
4032239 - 8299
4032247 - 28103
4032248 - 28108
4032264 - 10240
4032265 - 10241
4032266 - 10240
4032270 - 10241
4032271 - 10260
4032272 - 10268
4032273 - 10268
4032275 - 10261
4032276 - 10262
4032277 - 10263
4032278 - 10270
4032279 - 10271
4032280 - 10272
4032281 - 10270
4032282 - 10271
4032283 - 10272
4032284 - 10264
4032285 - 10265
4032286 - 10266
4032287 - 10267
4032307 - 28121
4032308 - 28122
4032317 - 21717
4032318 - 21718
4032319 - 21723
4032321 - 21727
4032325 - 21752
4032233 - 8298 EXPIRED
4032234 - 8299 EXPIRED
4032235 - 8299 EXPIRED
4032236 - 8299 EXPIRED
4032237 - 8299 EXPIRED
4032238 - 8299 EXPIRED
4032239 - 8298 EXPIRED
4032248 - 28108 EXPIRED
4032264 - 10240 EXPIRED
4032265 - 10241 EXPIRED
4032266 - 10240 EXPIRED
4032270 - 10241 EXPIRED
4032271 - 10260 EXPIRED
4032272 - 10268 EXPIRED
4032273 - 10268 EXPIRED
4032275 - 10261 EXPIRED
4032276 - 10262 EXPIRED
4032277 - 10263 EXPIRED
4032278 - 10270 EXPIRED
4032279 - 10271 EXPIRED
4032280 - 10272 EXPIRED
4032281 - 10270 EXPIRED
4032282 - 10271 EXPIRED
4032283 - 10272 EXPIRED
4032284 - 10264 EXPIRED
4032285 - 10265 EXPIRED
4032286 - 10266 EXPIRED
4032287 - 10267 EXPIRED
4032306 - 28120 EXPIRED
4032307 - 28121 EXPIRED
4032308 - 28122 EXPIRED
4032325 - 21751
4032326 - 21752
4032331 - 21601
4032333 - 21608
4032335 - 21617
4032342 - 21743
4032348 - 10300
4032349 - 10301
4032350 - 10302
4032374 - 2405
4032376 - 2406
4032377 - 2407
4032378 - 2408
4032379 - 2409
4032348 - 10300 EXPIRED
4032349 - 10301 EXPIRED
4032350 - 10302 EXPIRED
4032401 - 2261
4032402 - 2263
4032404 - 28128
4032404 - 28128 EXPIRED
4032423 - 21767
4032435 - 28307
4032436 - 28314
4032437 - 28321
4032443 - 28317
4032496 - 28238
4032512 - 3720
4161000 - 9322
4032435 - 28307 EXPIRED
4032436 - 28314 EXPIRED
4032437 - 28321 EXPIRED
4161000 - 9322 EXPIRED
@@ -322,87 +229,27 @@ ITEMS WITH NO QUEST DROP DATA ON DB
COMPLETE QUEST ITEMS WITH ZERO QUANTITY
1018:
4000142
2052:
4031025
2053:
4031026
2054:
4031028
2167:
4031841
2168:
4031842
2169:
4031843
2173:
4031846
2180:
4031850
2183:
4031851
2185:
4031852
3010:
4031050
6340:
4031872
6350:
4031871
6360:
4031869
6361:
4031870
6380:
4031873
6390:
4031874
8142:
4000300
4000301
8218:
8218 EXPIRED:
4031664
4031665
4031666
8886:
8886 EXPIRED:
4031659
8887:
8887 EXPIRED:
4031658
8888:
8888 EXPIRED:
4031660
10430:
4220152
28104:
4032247
28120:
4032306

View File

@@ -72,7 +72,6 @@ public class MapleQuestItemFetcher {
static String password = "";
static String wzPath = "../../wz";
static String fileName = "../../wz/Quest.wz/Act.img.xml";
static String directoryName = "../..";
static String newFile = "lib/QuestReport.txt";
@@ -134,6 +133,28 @@ public class MapleQuestItemFetcher {
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 inspectQuestItemList(int st) {
String line = null;
@@ -152,24 +173,28 @@ public class MapleQuestItemFetcher {
if(ii.isQuestItem(currentItemid)) {
if(currentCount != 0) {
if(isCompleteState == 1) {
Set<Integer> qi = completeQuestItems.get(questId);
if(qi == null) {
Set<Integer> newSet = new HashSet<>();
newSet.add(currentItemid);
if(currentCount < 0) {
Set<Integer> qi = completeQuestItems.get(questId);
if(qi == null) {
Set<Integer> newSet = new HashSet<>();
newSet.add(currentItemid);
completeQuestItems.put(questId, newSet);
} else {
qi.add(currentItemid);
completeQuestItems.put(questId, newSet);
} else {
qi.add(currentItemid);
}
}
} else {
Set<Integer> qi = startQuestItems.get(questId);
if(qi == null) {
Set<Integer> newSet = new HashSet<>();
newSet.add(currentItemid);
if(currentCount > 0) {
Set<Integer> qi = startQuestItems.get(questId);
if(qi == null) {
Set<Integer> newSet = new HashSet<>();
newSet.add(currentItemid);
startQuestItems.put(questId, newSet);
} else {
qi.add(currentItemid);
startQuestItems.put(questId, newSet);
} else {
qi.add(currentItemid);
}
}
}
} else {
@@ -222,7 +247,7 @@ public class MapleQuestItemFetcher {
}
}
private static void translateToken(String token) {
private static void translateActToken(String token) {
String d;
int temp;
@@ -244,6 +269,8 @@ public class MapleQuestItemFetcher {
if(d.contains("item")) {
temp = status;
inspectQuestItemList(temp);
} else {
forwardCursor(status);
}
}
@@ -258,6 +285,37 @@ public class MapleQuestItemFetcher {
}
}
}
private static void translateCheckToken(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(status == 3) {
d = getName(token);
if(d.equals("end")) {
limitedQuestids.add(questId);
}
}
}
}
private static void calculateQuestItemDiff() {
// This will remove started quest items from the "to complete" item set.
@@ -289,32 +347,46 @@ public class MapleQuestItemFetcher {
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()) {
int curQuest = rs.getInt(1);
if(curQuest != iq.getRight()) {
Set<Integer> sqSet = startQuestItems.get(curQuest);
if(sqSet != null && sqSet.contains(iq.getLeft())) {
continue;
}
int[] mixed = new int[3];
mixed[0] = iq.getLeft();
mixed[1] = curQuest;
mixed[2] = iq.getRight();
mixedQuestidItems.put(iq.getLeft(), mixed);
}
}
itemsWithQuest.remove(iq);
}
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) {
PreparedStatement ps = con.prepareStatement("SELECT questid FROM drop_data WHERE itemid = ?;");
ps.setInt(1, iq.getLeft());
ResultSet rs = ps.executeQuery();
if (rs.isBeforeFirst()) {
while(rs.next()) {
int curQuest = rs.getInt(1);
if(curQuest != iq.getRight()) {
int[] mixed = new int[3];
mixed[0] = iq.getLeft();
mixed[1] = curQuest;
mixed[2] = iq.getRight();
mixedQuestidItems.put(iq.getLeft(), mixed);
}
}
itemsWithQuest.remove(iq);
}
rs.close();
ps.close();
filterQuestDropsOnTable(iq, itemsWithQuest, true);
filterQuestDropsOnTable(iq, itemsWithQuest, false);
}
}
catch(SQLException e) {
@@ -431,17 +503,30 @@ public class MapleQuestItemFetcher {
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");
bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
translateToken(line);
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");
bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
translateActToken(line);
}
bufferedReader.close();