Move MapleQuestItemFetcher to main module

This commit is contained in:
P0nk
2021-07-11 12:00:05 +02:00
parent f8ef9afdd9
commit 56f3511395
47 changed files with 188 additions and 5050 deletions

View File

@@ -1,258 +0,0 @@
# Report File autogenerated from the MapleQuestItemFetcher feature by Ronan Lana.
# Generated data takes into account several data info from the underlying DB, server source files and the server-side WZ.xmls.
INCORRECT QUESTIDS ON DB
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
4031189 : 0 -> 3448
4031218 : 0 -> 3071
4031223 : 3607 -> 3608
4031405 : 0 -> 4207 EXPIRED
4031511 : 6904 -> 6914
4031856 : 0 -> 2191
4031857 : 0 -> 2192
4032319 : -1 -> 21723
4032324 : 21736 -> 21737
4032339 : 0 -> 21303
ITEMS WITH NO QUEST DROP DATA ON DB
1302014 - 2048
2022053 - 9330 EXPIRED
2022054 - 9330 EXPIRED
2022057 - 9332 EXPIRED
3994139 - 10360 EXPIRED
4000142 - 1018
4001353 - 28227
4031014 - 2020
4031015 - 2020
4031020 - 2050
4031025 - 2052
4031026 - 2053
4031028 - 2054
4031032 - 2051
4031039 - 2055
4031040 - 2056
4031041 - 2057
4031042 - 2035
4031063 - 9260 EXPIRED
4031064 - 8012
4031117 - 3421
4031122 - 9340 EXPIRED
4031124 - 9340 EXPIRED
4031144 - 2047
4031167 - 9052 EXPIRED
4031168 - 9055 EXPIRED
4031169 - 9058 EXPIRED
4031180 - 8020
4031181 - 9140 EXPIRED
4031182 - 9140 EXPIRED
4031183 - 9140 EXPIRED
4031184 - 9150 EXPIRED
4031185 - 9150 EXPIRED
4031186 - 9150 EXPIRED
4031190 - 3055
4031191 - 3063
4031192 - 8700 EXPIRED
4031199 - 3045
4031201 - 3048
4031202 - 3050
4031207 - 3443
4031220 - 9210 EXPIRED
4031226 - 9321 EXPIRED
4031227 - 4103 EXPIRED
4031230 - 3619
4031235 - 3615
4031236 - 3616
4031237 - 3617
4031238 - 3618
4031243 - 3443
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
4031455 - 6280
4031456 - 6230
4031462 - 6210
4031468 - 6222
4031478 - 6210
4031488 - 6312
4031504 - 9640 EXPIRED
4031505 - 9641 EXPIRED
4031506 - 9642 EXPIRED
4031554 - 3821
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
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 EXPIRED
4031662 - 9866 EXPIRED
4031667 - 9863 EXPIRED
4031696 - 3334
4031697 - 3322
4031708 - 3309
4031764 - 4949 EXPIRED
4031766 - 4959 EXPIRED
4031767 - 4947 EXPIRED
4031769 - 4946 EXPIRED
4031770 - 4946 EXPIRED
4031772 - 4942
4031774 - 3361
4031785 - 3376
4031796 - 3362
4031797 - 3367
4031806 - 3379
4031812 - 4950 EXPIRED
4031837 - 9942 EXPIRED
4031839 - 2162
4031850 - 2180
4031881 - 4484 EXPIRED
4031921 - 4646
4032037 - 9154 EXPIRED
4032038 - 9154 EXPIRED
4032039 - 9154 EXPIRED
4032087 - 10081 EXPIRED
4032119 - 28109 EXPIRED
4032136 - 20710
4032138 - 20712
4032142 - 20716
4032196 - 20528
4032197 - 20528
4032198 - 20528
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
4032348 - 10300 EXPIRED
4032349 - 10301 EXPIRED
4032350 - 10302 EXPIRED
4032401 - 2261
4032402 - 2263
4032404 - 28128 EXPIRED
4032423 - 21767
4032435 - 28307 EXPIRED
4032436 - 28314 EXPIRED
4032437 - 28321 EXPIRED
4161000 - 9322 EXPIRED
COMPLETE QUEST ITEMS WITH ZERO QUANTITY
8142:
4000300
4000301
8218 EXPIRED:
4031664
4031665
4031666
8886 EXPIRED:
4031659
8887 EXPIRED:
4031658
8888 EXPIRED:
4031660
28104:
4032247

View File

@@ -1,591 +0,0 @@
/*
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;
import org.apache.commons.io.FileUtils;
import tools.MapleItemInformationProvider;
import tools.Pair;
import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.Map.Entry;
/**
*
* @author RonanLana
*
* 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.
*
* 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";
static String wzPath = "../../wz";
static String directoryName = "../..";
static String newFile = "lib/QuestReport.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 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 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 inspectQuestItemList(int st) {
String line = null;
try {
while(status >= st && (line = bufferedReader.readLine()) != null) {
readItemToken(line);
}
}
catch(Exception e) {
e.printStackTrace();
}
}
private static void processCurrentItem() {
try {
if(ii.isQuestItem(currentItemid)) {
if(currentCount != 0) {
if(isCompleteState == 1) {
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);
}
}
} else {
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);
}
}
}
} else {
if(isCompleteState == 1) {
Set<Integer> qi = zeroedCompleteQuestItems.get(questId);
if(qi == null) {
Set<Integer> newSet = new HashSet<>();
newSet.add(currentItemid);
zeroedCompleteQuestItems.put(questId, newSet);
} else {
qi.add(currentItemid);
}
} else {
Set<Integer> qi = zeroedStartQuestItems.get(questId);
if(qi == null) {
Set<Integer> newSet = new HashSet<>();
newSet.add(currentItemid);
zeroedStartQuestItems.put(questId, newSet);
} else {
qi.add(currentItemid);
}
}
}
}
} catch(Exception e) {}
}
private static void readItemToken(String token) {
if(token.contains("/imgdir")) {
status -= 1;
processCurrentItem();
currentItemid = 0;
currentCount = 0;
}
else if(token.contains("imgdir")) {
status += 1;
}
else {
String d = getName(token);
if(d.equals("id")) {
currentItemid = Integer.parseInt(getValue(token));
} else if(d.equals("count")) {
currentCount = Integer.parseInt(getValue(token));
}
}
}
private static void translateActToken(String token) {
String d;
int temp;
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) {
d = getName(token);
if(d.contains("item")) {
temp = status;
inspectQuestItemList(temp);
} else {
forwardCursor(status);
}
}
status += 1;
} else {
if(status == 3) {
d = getName(token);
if(d.equals("end")) {
limitedQuestids.add(questId);
}
}
}
}
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.
for(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()) {
completeQuestItems.remove(qd.getKey());
}
}
}
}
}
}
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.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()) {
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) {
filterQuestDropsOnTable(iq, itemsWithQuest, true);
filterQuestDropsOnTable(iq, itemsWithQuest, false);
}
}
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();
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");
List<Pair<Integer, Integer>> copyItemsWithQuest = new ArrayList<>(itemsWithQuest);
for(Pair<Integer, Integer> iq : copyItemsWithQuest) {
if(foundMatchingDataOnFile(fileContent, String.valueOf(iq.getLeft()))) {
itemsWithQuest.remove(iq);
}
}
} 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());
list.addAll(map.entrySet());
Collections.sort(list, (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());
list.addAll(map.entrySet());
Collections.sort(list, (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()) {
List<Integer> il = new ArrayList<>(2);
il.addAll(e.getValue());
Collections.sort(il, (o1, o2) -> o1 - o2);
list.add(new Pair<>(e.getKey(), il));
}
Collections.sort(list, (o1, o2) -> o1.getLeft() - o2.getLeft());
return list;
}
private static String getExpiredStringLabel(int questid) {
return (!limitedQuestids.contains(questid) ? "" : " EXPIRED");
}
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) {
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();
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");
printReportFileHeader();
if(!mixedQuestidItems.isEmpty()) {
printWriter.println("INCORRECT QUESTIDS ON DB");
for(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()) {
Map<Integer, Integer> mapIwq = new HashMap<>(itemsWithQuest.size());
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)) {
printWriter.println(iwq.getKey() + " - " + iwq.getValue() + getExpiredStringLabel(iwq.getValue()));
}
printWriter.println("\n\n\n\n\n");
}
if(displayExtraInfo) {
if(!zeroedStartQuestItems.isEmpty()) {
printWriter.println("START QUEST ITEMS WITH ZERO QUANTITY");
for(Pair<Integer, List<Integer>> iwq : getSortedMapEntries2(zeroedStartQuestItems)) {
printWriter.println(iwq.getLeft() + getExpiredStringLabel(iwq.getLeft()) + ":");
for(Integer i : iwq.getRight()) {
printWriter.println(" " + i);
}
printWriter.println();
}
printWriter.println("\n\n\n\n\n");
}
if(!zeroedCompleteQuestItems.isEmpty()) {
printWriter.println("COMPLETE QUEST ITEMS WITH ZERO QUANTITY");
for(Pair<Integer, List<Integer>> iwq : getSortedMapEntries2(zeroedCompleteQuestItems)) {
printWriter.println(iwq.getLeft() + getExpiredStringLabel(iwq.getLeft()) + ":");
for(Integer i : iwq.getRight()) {
printWriter.println(" " + i);
}
printWriter.println();
}
printWriter.println("\n\n\n\n\n");
}
}
printWriter.close();
System.out.println("Done!");
}
catch(FileNotFoundException ex) {
System.out.println("Unable to open file '" + fileName + "'");
}
catch(IOException ex) {
System.out.println("Error reading file '" + fileName + "'");
}
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) {
System.setProperty("wzpath", wzPath);
ii = MapleItemInformationProvider.getInstance();
ReportQuestItemData();
}
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -1,149 +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.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class ArrayMap<K, V> extends AbstractMap<K, V> {
static class Entry<K, V> implements Map.Entry<K, V> {
protected K key;
protected V value;
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Map.Entry<?, ?>)) {
return false;
}
Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
return (key == null ? e.getKey() == null : key.equals(e.getKey())) && (value == null ? e.getValue() == null : value.equals(e.getValue()));
}
@Override
public int hashCode() {
int keyHash = (key == null ? 0 : key.hashCode());
int valueHash = (value == null ? 0 : value.hashCode());
return keyHash ^ valueHash;
}
@Override
public String toString() {
return key + "=" + value;
}
}
private Set<? extends java.util.Map.Entry<K, V>> entries = null;
private ArrayList<Entry<K, V>> list;
public ArrayMap() {
list = new ArrayList<>();
}
public ArrayMap(Map<K, V> map) {
list = new ArrayList<>();
putAll(map);
}
public ArrayMap(int initialCapacity) {
list = new ArrayList<>(initialCapacity);
}
@Override
@SuppressWarnings ("unchecked")
public Set<java.util.Map.Entry<K, V>> entrySet() {
if (entries == null) {
entries = new AbstractSet<Entry<K, V>>() {
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public Iterator<Entry<K, V>> iterator() {
return list.iterator();
}
@Override
public int size() {
return list.size();
}
};
}
return (Set<java.util.Map.Entry<K, V>>) entries;
}
@Override
public V put(K key, V value) {
int size = list.size();
Entry<K, V> entry = null;
int i;
if (key == null) {
for (i = 0; i < size; i++) {
entry = (list.get(i));
if (entry.getKey() == null) {
break;
}
}
} else {
for (i = 0; i < size; i++) {
entry = (list.get(i));
if (key.equals(entry.getKey())) {
break;
}
}
}
V oldValue = null;
if (i < size) {
oldValue = entry.getValue();
entry.setValue(value);
} else {
list.add(new Entry<>(key, value));
}
return oldValue;
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -1,188 +0,0 @@
package tools;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class FilePrinter {
public static final String
ACCOUNT_STUCK = "accountStuck.txt",
EXCEPTION_CAUGHT = "exceptionCaught.txt",
CLIENT_START = "clientStartError.txt",
ADD_PLAYER = "addPlayer.txt",
MAPLE_MAP = "mapleMap.txt",
ERROR38 = "error38.txt",
PACKET_LOG = "log.txt",
EXCEPTION = "exceptions.txt",
SQL_EXCEPTION = "sqlexceptions.txt",
PACKET_HANDLER = "PacketHandler/",
PORTAL = "portals/",
NPC = "npcs/",
INVOCABLE = "invocable/",
REACTOR = "reactors/",
QUEST = "quests/",
ITEM = "items/",
MOB_MOVEMENT = "mobmovement.txt",
MAP_SCRIPT = "mapscript/",
DIRECTION = "directions/",
SAVE_CHAR = "saveToDB.txt",
INSERT_CHAR = "insertCharacter.txt",
LOAD_CHAR = "loadCharFromDB.txt",
UNHANDLED_EVENT = "doesNotExist.txt",
SESSION = "sessions.txt",
EXPLOITS = "exploits/",
STORAGE = "storage/",
PACKET_LOGS = "packetlogs/",
DELETED_CHARACTERS = "deletedchars/",
FREDRICK = "fredrick/",
NPC_UNCODED = "uncodedNPCs.txt",
QUEST_UNCODED = "uncodedQuests.txt",
AUTOSAVING_CHARACTER = "saveCharAuto.txt",
SAVING_CHARACTER = "saveChar.txt",
USED_COMMANDS = "usedCommands.txt";//more to come (maps)
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //for file system purposes, it's nice to use yyyy-MM-dd
private static final String FILE_PATH = "logs/" + sdf.format(Calendar.getInstance().getTime()) + "/"; // + sdf.format(Calendar.getInstance().getTime()) + "/"
private static final String ERROR = "error/";
public static void printError(final String name, final Throwable t) {
System.out.println("Error thrown: " + name);
System.out.println(getString(t));
FileOutputStream out = null;
final String file = FILE_PATH + ERROR + name;
try {
File outputFile = new File(file);
if (outputFile.getParentFile() != null) {
outputFile.getParentFile().mkdirs();
}
out = new FileOutputStream(file, true);
out.write(getString(t).getBytes());
out.write("\n---------------------------------\r\n".getBytes());
} catch (IOException ess) {
ess.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
}
public static void printError(final String name, final Throwable t, final String info) {
System.out.println("Error thrown: " + name);
System.out.println(getString(t));
FileOutputStream out = null;
final String file = FILE_PATH + ERROR + name;
try {
File outputFile = new File(file);
if (outputFile.getParentFile() != null) {
outputFile.getParentFile().mkdirs();
}
out = new FileOutputStream(file, true);
out.write((info + "\r\n").getBytes());
out.write(getString(t).getBytes());
out.write("\n---------------------------------\r\n".getBytes());
} catch (IOException ess) {
ess.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
}
public static void printError(final String name, final String s) {
System.out.println("Error thrown: " + name);
System.out.println(s);
FileOutputStream out = null;
final String file = FILE_PATH + ERROR + name;
try {
File outputFile = new File(file);
if (outputFile.getParentFile() != null) {
outputFile.getParentFile().mkdirs();
}
out = new FileOutputStream(file, true);
out.write(s.getBytes());
//out.write("\n---------------------------------\n".getBytes());
} catch (IOException ess) {
ess.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
}
public static void print(final String name, final String s) {
print(name, s, true);
}
public static void print(final String name, final String s, boolean line) {
System.out.println("Log: " + name);
System.out.println(s);
FileOutputStream out = null;
String file = FILE_PATH + name;
try {
File outputFile = new File(file);
if (outputFile.getParentFile() != null) {
outputFile.getParentFile().mkdirs();
}
out = new FileOutputStream(file, true);
out.write(s.getBytes());
out.write("\r\n".getBytes());
if (line) {
out.write("---------------------------------\r\n".getBytes());
}
} catch (IOException ess) {
ess.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
}
private static String getString(final Throwable e) {
String retValue = null;
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw);
e.printStackTrace(pw);
retValue = sw.toString();
} finally {
try {
if (pw != null) {
pw.close();
}
if (sw != null) {
sw.close();
}
} catch (IOException ignore) {
ignore.printStackTrace();
}
}
return retValue;
}
}

View File

@@ -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();
}
}

View File

@@ -1,672 +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 provider.*;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
//import server.life.MapleMonsterInformationProvider;
/**
*
* @author Matze
*
*/
public class MapleItemInformationProvider {
private static MapleItemInformationProvider instance = null;
protected MapleDataProvider itemData;
protected MapleDataProvider equipData;
protected MapleDataProvider stringData;
protected MapleData cashStringData;
protected MapleData consumeStringData;
protected MapleData eqpStringData;
protected MapleData etcStringData;
protected MapleData insStringData;
protected MapleData petStringData;
protected Map<Integer, Short> slotMaxCache = new HashMap<>();
protected Map<Integer, Integer> itemEffects = new HashMap<>();
protected Map<Integer, Map<String, Integer>> equipStatsCache = new HashMap<>();
protected Map<Integer, Integer> equipCache = new HashMap<>();
protected Map<Integer, Double> priceCache = new HashMap<>();
protected Map<Integer, Integer> wholePriceCache = new HashMap<>();
protected Map<Integer, Integer> projectileWatkCache = new HashMap<>();
protected Map<Integer, String> nameCache = new HashMap<>();
protected Map<Integer, String> descCache = new HashMap<>();
protected Map<Integer, String> msgCache = new HashMap<>();
protected Map<Integer, Boolean> dropRestrictionCache = new HashMap<>();
protected Map<Integer, Boolean> pickupRestrictionCache = new HashMap<>();
protected Map<Integer, Integer> getMesoCache = new HashMap<>();
protected Map<Integer, Integer> monsterBookID = new HashMap<>();
protected Map<Integer, Boolean> onEquipUntradableCache = new HashMap<>();
protected Map<Integer, Boolean> karmaCache = new HashMap<>();
protected Map<Integer, Integer> triggerItemCache = new HashMap<>();
protected Map<Integer, Integer> expCache = new HashMap<>();
protected Map<Integer, Integer> levelCache = new HashMap<>();
protected List<Pair<Integer, String>> itemNameCache = new ArrayList<>();
protected Map<Integer, Boolean> consumeOnPickupCache = new HashMap<>();
protected Map<Integer, Boolean> isQuestItemCache = new HashMap<>();
protected Map<Integer, String> equipmentSlotCache = new HashMap<>();
protected Map<Integer, Boolean> noCancelMouseCache = new HashMap<>();
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"));
cashStringData = stringData.getData("Cash.img");
consumeStringData = stringData.getData("Consume.img");
eqpStringData = stringData.getData("Eqp.img");
etcStringData = stringData.getData("Etc.img");
insStringData = stringData.getData("Ins.img");
petStringData = stringData.getData("Pet.img");
}
public static MapleItemInformationProvider getInstance() {
if (instance == null) {
instance = new MapleItemInformationProvider();
}
return instance;
}
public List<Pair<Integer, String>> getAllItems() {
if (!itemNameCache.isEmpty()) {
return itemNameCache;
}
List<Pair<Integer, String>> itemPairs = new ArrayList<>();
MapleData itemsData;
itemsData = stringData.getData("Cash.img");
for (MapleData itemFolder : itemsData.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
itemsData = stringData.getData("Consume.img");
for (MapleData itemFolder : itemsData.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
itemsData = stringData.getData("Eqp.img").getChildByPath("Eqp");
for (MapleData eqpType : itemsData.getChildren()) {
for (MapleData itemFolder : eqpType.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
}
itemsData = stringData.getData("Etc.img").getChildByPath("Etc");
for (MapleData itemFolder : itemsData.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
itemsData = stringData.getData("Ins.img");
for (MapleData itemFolder : itemsData.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
itemsData = stringData.getData("Pet.img");
for (MapleData itemFolder : itemsData.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
return itemPairs;
}
public List<Pair<Integer, String>> getAllEtcItems() {
if (!itemNameCache.isEmpty()) {
return itemNameCache;
}
List<Pair<Integer, String>> itemPairs = new ArrayList<>();
MapleData itemsData;
itemsData = stringData.getData("Etc.img").getChildByPath("Etc");
for (MapleData itemFolder : itemsData.getChildren()) {
itemPairs.add(new Pair<>(Integer.parseInt(itemFolder.getName()), MapleDataTool.getString("name", itemFolder, "NO-NAME")));
}
return itemPairs;
}
private MapleData getStringData(int itemId) {
String cat = "null";
MapleData theData;
if (itemId >= 5010000) {
theData = cashStringData;
} else if (itemId >= 2000000 && itemId < 3000000) {
theData = consumeStringData;
} else if ((itemId >= 1010000 && itemId < 1040000) || (itemId >= 1122000 && itemId < 1123000) || (itemId >= 1132000 && itemId < 1133000) || (itemId >= 1142000 && itemId < 1143000)) {
theData = eqpStringData;
cat = "Eqp/Accessory";
} else if (itemId >= 1000000 && itemId < 1010000) {
theData = eqpStringData;
cat = "Eqp/Cap";
} else if (itemId >= 1102000 && itemId < 1103000) {
theData = eqpStringData;
cat = "Eqp/Cape";
} else if (itemId >= 1040000 && itemId < 1050000) {
theData = eqpStringData;
cat = "Eqp/Coat";
} else if (itemId >= 20000 && itemId < 22000) {
theData = eqpStringData;
cat = "Eqp/Face";
} else if (itemId >= 1080000 && itemId < 1090000) {
theData = eqpStringData;
cat = "Eqp/Glove";
} else if (itemId >= 30000 && itemId < 35000) {
theData = eqpStringData;
cat = "Eqp/Hair";
} else if (itemId >= 1050000 && itemId < 1060000) {
theData = eqpStringData;
cat = "Eqp/Longcoat";
} else if (itemId >= 1060000 && itemId < 1070000) {
theData = eqpStringData;
cat = "Eqp/Pants";
} else if (itemId >= 1802000 && itemId < 1842000) {
theData = eqpStringData;
cat = "Eqp/PetEquip";
} else if (itemId >= 1112000 && itemId < 1120000) {
theData = eqpStringData;
cat = "Eqp/Ring";
} else if (itemId >= 1092000 && itemId < 1100000) {
theData = eqpStringData;
cat = "Eqp/Shield";
} else if (itemId >= 1070000 && itemId < 1080000) {
theData = eqpStringData;
cat = "Eqp/Shoes";
} else if (itemId >= 1900000 && itemId < 2000000) {
theData = eqpStringData;
cat = "Eqp/Taming";
} else if (itemId >= 1300000 && itemId < 1800000) {
theData = eqpStringData;
cat = "Eqp/Weapon";
} else if (itemId >= 4000000 && itemId < 5000000) {
theData = etcStringData;
cat = "Etc";
} else if (itemId >= 3000000 && itemId < 4000000) {
theData = insStringData;
} else if (itemId / 1000 == 5000) {
theData = petStringData;
} else {
return null;
}
if (cat.equalsIgnoreCase("null")) {
return theData.getChildByPath(String.valueOf(itemId));
} else {
return theData.getChildByPath(cat + "/" + itemId);
}
}
public boolean noCancelMouse(int itemId) {
if (noCancelMouseCache.containsKey(itemId)) {
return noCancelMouseCache.get(itemId);
}
MapleData item = getItemData(itemId);
if (item == null) {
noCancelMouseCache.put(itemId, false);
return false;
}
boolean blockMouse = MapleDataTool.getIntConvert("info/noCancelMouse", item, 0) == 1;
noCancelMouseCache.put(itemId, blockMouse);
return blockMouse;
}
private MapleData getItemData(int itemId) {
MapleData ret = null;
String idStr = "0" + String.valueOf(itemId);
MapleDataDirectoryEntry root = itemData.getRoot();
for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
for (MapleDataFileEntry iFile : topDir.getFiles()) {
if (iFile.getName().equals(idStr.substring(0, 4) + ".img")) {
ret = itemData.getData(topDir.getName() + "/" + iFile.getName());
if (ret == null) {
return null;
}
ret = ret.getChildByPath(idStr);
return ret;
} else if (iFile.getName().equals(idStr.substring(1) + ".img")) {
return itemData.getData(topDir.getName() + "/" + iFile.getName());
}
}
}
root = equipData.getRoot();
for (MapleDataDirectoryEntry topDir : root.getSubdirectories()) {
for (MapleDataFileEntry iFile : topDir.getFiles()) {
if (iFile.getName().equals(idStr + ".img")) {
return equipData.getData(topDir.getName() + "/" + iFile.getName());
}
}
}
return ret;
}
public List<Integer> getItemIdsInRange(int minId, int maxId, boolean ignoreCashItem) {
List<Integer> list = new ArrayList<>();
if(ignoreCashItem) {
for(int i = minId; i <= maxId; i++) {
if(getItemData(i) != null && !isCash(i)) {
list.add(i);
}
}
}
else {
for(int i = minId; i <= maxId; i++) {
if(getItemData(i) != null) {
list.add(i);
}
}
}
return list;
}
public short getSlotMax(int itemId) {
Short slotMax = slotMaxCache.get(itemId);
if (slotMax != null) {
return slotMax;
}
short ret = 0;
MapleData item = getItemData(itemId);
if (item != null) {
MapleData smEntry = item.getChildByPath("info/slotMax");
if (smEntry == null) {
ret = 100;
} else {
ret = (short) MapleDataTool.getInt(smEntry);
}
}
slotMaxCache.put(itemId, ret);
return ret;
}
public int getMeso(int itemId) {
if (getMesoCache.containsKey(itemId)) {
return getMesoCache.get(itemId);
}
MapleData item = getItemData(itemId);
if (item == null) {
return -1;
}
int pEntry;
MapleData pData = item.getChildByPath("info/meso");
if (pData == null) {
return -1;
}
pEntry = MapleDataTool.getInt(pData);
getMesoCache.put(itemId, pEntry);
return pEntry;
}
public int getWholePrice(int itemId) {
if (wholePriceCache.containsKey(itemId)) {
return wholePriceCache.get(itemId);
}
MapleData item = getItemData(itemId);
if (item == null) {
return -1;
}
int pEntry;
MapleData pData = item.getChildByPath("info/price");
if (pData == null) {
return -1;
}
pEntry = MapleDataTool.getInt(pData);
wholePriceCache.put(itemId, pEntry);
return pEntry;
}
public double getPrice(int itemId) {
if (priceCache.containsKey(itemId)) {
return priceCache.get(itemId);
}
MapleData item = getItemData(itemId);
if (item == null) {
return -1;
}
double pEntry;
MapleData pData = item.getChildByPath("info/unitPrice");
if (pData != null) {
try {
pEntry = MapleDataTool.getDouble(pData);
} catch (Exception e) {
pEntry = MapleDataTool.getInt(pData);
}
} else {
pData = item.getChildByPath("info/price");
if (pData == null) {
return -1;
}
try {
pEntry = MapleDataTool.getInt(pData);
} catch(Exception e) {
priceCache.put(itemId, 0.0);
return 0;
}
}
priceCache.put(itemId, pEntry);
return pEntry;
}
protected String getEquipmentSlot(int itemId) {
if (equipmentSlotCache.containsKey(itemId)) {
return equipmentSlotCache.get(itemId);
}
String ret = "";
MapleData item = getItemData(itemId);
if (item == null) {
return null;
}
MapleData info = item.getChildByPath("info");
if (info == null) {
return null;
}
ret = MapleDataTool.getString("islot", info, "");
equipmentSlotCache.put(itemId, ret);
return ret;
}
public Map<String, Integer> getEquipStats(int itemId) {
if (equipStatsCache.containsKey(itemId)) {
return equipStatsCache.get(itemId);
}
Map<String, Integer> ret = new LinkedHashMap<>();
MapleData item = getItemData(itemId);
if (item == null) {
return null;
}
MapleData info = item.getChildByPath("info");
if (info == null) {
return null;
}
for (MapleData data : info.getChildren()) {
if (data.getName().startsWith("inc")) {
ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data));
}
/*else if (data.getName().startsWith("req"))
ret.put(data.getName(), MapleDataTool.getInt(data.getName(), info, 0));*/
}
ret.put("reqJob", MapleDataTool.getInt("reqJob", info, 0));
ret.put("reqLevel", MapleDataTool.getInt("reqLevel", info, 0));
ret.put("reqDEX", MapleDataTool.getInt("reqDEX", info, 0));
ret.put("reqSTR", MapleDataTool.getInt("reqSTR", info, 0));
ret.put("reqINT", MapleDataTool.getInt("reqINT", info, 0));
ret.put("reqLUK", MapleDataTool.getInt("reqLUK", info, 0));
ret.put("reqPOP", MapleDataTool.getInt("reqPOP", info, 0));
ret.put("cash", MapleDataTool.getInt("cash", info, 0));
ret.put("tuc", MapleDataTool.getInt("tuc", info, 0));
ret.put("cursed", MapleDataTool.getInt("cursed", info, 0));
ret.put("success", MapleDataTool.getInt("success", info, 0));
ret.put("fs", MapleDataTool.getInt("fs", info, 0));
equipStatsCache.put(itemId, ret);
return ret;
}
public List<Integer> getScrollReqs(int itemId) {
List<Integer> ret = new ArrayList<>();
MapleData data = getItemData(itemId);
data = data.getChildByPath("req");
if (data == null) {
return ret;
}
for (MapleData req : data.getChildren()) {
ret.add(MapleDataTool.getInt(req));
}
return ret;
}
public String getName(int itemId) {
if (nameCache.containsKey(itemId)) {
return nameCache.get(itemId);
}
MapleData strings = getStringData(itemId);
if (strings == null) {
return null;
}
String ret = MapleDataTool.getString("name", strings, null);
nameCache.put(itemId, ret);
return ret;
}
public String getMsg(int itemId) {
if (msgCache.containsKey(itemId)) {
return msgCache.get(itemId);
}
MapleData strings = getStringData(itemId);
if (strings == null) {
return null;
}
String ret = MapleDataTool.getString("msg", strings, null);
msgCache.put(itemId, ret);
return ret;
}
public boolean isDropRestricted(int itemId) {
if (dropRestrictionCache.containsKey(itemId)) {
return dropRestrictionCache.get(itemId);
}
MapleData data = getItemData(itemId);
boolean bRestricted = MapleDataTool.getIntConvert("info/tradeBlock", data, 0) == 1;
if (!bRestricted) {
bRestricted = MapleDataTool.getIntConvert("info/accountSharable", data, 0) == 1;
}
if (!bRestricted) {
bRestricted = MapleDataTool.getIntConvert("info/quest", data, 0) == 1;
}
dropRestrictionCache.put(itemId, bRestricted);
return bRestricted;
}
public boolean isPickupRestricted(int itemId) {
if (pickupRestrictionCache.containsKey(itemId)) {
return pickupRestrictionCache.get(itemId);
}
MapleData data = getItemData(itemId);
boolean bRestricted = MapleDataTool.getIntConvert("info/only", data, 0) == 1;
pickupRestrictionCache.put(itemId, bRestricted);
return bRestricted;
}
public Map<String, Integer> getSkillStats(int itemId, double playerJob) {
Map<String, Integer> ret = new LinkedHashMap<>();
MapleData item = getItemData(itemId);
if (item == null) {
return null;
}
MapleData info = item.getChildByPath("info");
if (info == null) {
return null;
}
for (MapleData data : info.getChildren()) {
if (data.getName().startsWith("inc")) {
ret.put(data.getName().substring(3), MapleDataTool.getIntConvert(data));
}
}
ret.put("masterLevel", MapleDataTool.getInt("masterLevel", info, 0));
ret.put("reqSkillLevel", MapleDataTool.getInt("reqSkillLevel", info, 0));
ret.put("success", MapleDataTool.getInt("success", info, 0));
MapleData skill = info.getChildByPath("skill");
int curskill;
for (int i = 0; i < skill.getChildren().size(); i++) {
curskill = MapleDataTool.getInt(Integer.toString(i), skill, 0);
if (curskill == 0) {
break;
}
if (curskill / 10000 == playerJob) {
ret.put("skillid", curskill);
break;
}
}
if (ret.get("skillid") == null) {
ret.put("skillid", 0);
}
return ret;
}
public List<Integer> petsCanConsume(int itemId) {
List<Integer> ret = new ArrayList<>();
MapleData data = getItemData(itemId);
int curPetId;
for (int i = 0; i < data.getChildren().size(); i++) {
curPetId = MapleDataTool.getInt("spec/" + Integer.toString(i), data, 0);
if (curPetId == 0) {
break;
}
ret.add(Integer.valueOf(curPetId));
}
return ret;
}
public boolean isQuestItem(int itemId) {
if (isQuestItemCache.containsKey(itemId)) {
return isQuestItemCache.get(itemId);
}
MapleData data = getItemData(itemId);
boolean questItem = MapleDataTool.getIntConvert("info/quest", data, 0) == 1;
isQuestItemCache.put(itemId, questItem);
return questItem;
}
public int getQuestIdFromItem(int itemId) {
MapleData data = getItemData(itemId);
int questItem = MapleDataTool.getIntConvert("info/quest", data, 0);
return questItem;
}
private void loadCardIdData() {
PreparedStatement ps = null;
ResultSet rs = null;
Connection con = null;
try {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("SELECT cardid, mobid FROM monstercarddata");
rs = ps.executeQuery();
while (rs.next()) {
monsterBookID.put(rs.getInt(1), rs.getInt(2));
}
rs.close();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null && !rs.isClosed()) {
rs.close();
}
if (ps != null && !ps.isClosed()) {
ps.close();
}
if (con != null && !con.isClosed()) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public int getCardMobId(int id) {
return monsterBookID.get(id);
}
public boolean isUntradeableOnEquip(int itemId) {
if (onEquipUntradableCache.containsKey(itemId)) {
return onEquipUntradableCache.get(itemId);
}
boolean untradableOnEquip = MapleDataTool.getIntConvert("info/equipTradeBlock", getItemData(itemId), 0) > 0;
onEquipUntradableCache.put(itemId, untradableOnEquip);
return untradableOnEquip;
}
public boolean isKarmaAble(int itemId) {
if (karmaCache.containsKey(itemId)) {
return karmaCache.get(itemId);
}
boolean bRestricted = MapleDataTool.getIntConvert("info/tradeAvailable", getItemData(itemId), 0) > 0;
karmaCache.put(itemId, bRestricted);
return bRestricted;
}
public int getStateChangeItem(int itemId) {
if (triggerItemCache.containsKey(itemId)) {
return triggerItemCache.get(itemId);
} else {
int triggerItem = MapleDataTool.getIntConvert("info/stateChangeItem", getItemData(itemId), 0);
triggerItemCache.put(itemId, triggerItem);
return triggerItem;
}
}
public int getExpById(int itemId) {
if (expCache.containsKey(itemId)) {
return expCache.get(itemId);
} else {
int exp = MapleDataTool.getIntConvert("spec/exp", getItemData(itemId), 0);
expCache.put(itemId, exp);
return exp;
}
}
public int getMaxLevelById(int itemId) {
if (levelCache.containsKey(itemId)) {
return levelCache.get(itemId);
} else {
int level = MapleDataTool.getIntConvert("info/maxLevel", getItemData(itemId), 256);
levelCache.put(itemId, level);
return level;
}
}
public boolean isConsumeOnPickup(int itemId) {
if (consumeOnPickupCache.containsKey(itemId)) {
return consumeOnPickupCache.get(itemId);
}
MapleData data = getItemData(itemId);
boolean consume = MapleDataTool.getIntConvert("spec/consumeOnPickup", data, 0) == 1 || MapleDataTool.getIntConvert("specEx/consumeOnPickup", data, 0) == 1;
consumeOnPickupCache.put(itemId, consume);
return consume;
}
public boolean isCash(int itemId) {
return itemId / 1000000 == 5 || getEquipStats(itemId).get("cash") == 1;
}
public ArrayList<Pair<Integer, String>> getItemDataByName(String name)
{
ArrayList<Pair<Integer, String>> ret = new ArrayList<>();
for (Pair<Integer, String> itemPair : MapleItemInformationProvider.getInstance().getAllItems()) {
if (itemPair.getRight().toLowerCase().contains(name.toLowerCase())) {
ret.add(itemPair);
}
}
return ret;
}
}

View File

@@ -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;
}
}

View File

@@ -1,128 +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;
public class StringUtil {
/**
* Gets a string padded from the left to <code>length</code> by
* <code>padchar</code>.
*
* @param in The input string to be padded.
* @param padchar The character to pad with.
* @param length The length to pad to.
* @return The padded string.
*/
public static String getLeftPaddedStr(String in, char padchar, int length) {
StringBuilder builder = new StringBuilder(length);
for (int x = in.length(); x < length; x++) {
builder.append(padchar);
}
builder.append(in);
return builder.toString();
}
/**
* Gets a string padded from the right to <code>length</code> by
* <code>padchar</code>.
*
* @param in The input string to be padded.
* @param padchar The character to pad with.
* @param length The length to pad to.
* @return The padded string.
*/
public static String getRightPaddedStr(String in, char padchar, int length) {
StringBuilder builder = new StringBuilder(in);
for (int x = in.length(); x < length; x++) {
builder.append(padchar);
}
return builder.toString();
}
/**
* Joins an array of strings starting from string <code>start</code> with
* a space.
*
* @param arr The array of strings to join.
* @param start Starting from which string.
* @return The joined strings.
*/
public static String joinStringFrom(String arr[], int start) {
return joinStringFrom(arr, start, " ");
}
/**
* Joins an array of strings starting from string <code>start</code> with
* <code>sep</code> as a seperator.
*
* @param arr The array of strings to join.
* @param start Starting from which string.
* @return The joined strings.
*/
public static String joinStringFrom(String arr[], int start, String sep) {
StringBuilder builder = new StringBuilder();
for (int i = start; i < arr.length; i++) {
builder.append(arr[i]);
if (i != arr.length - 1) {
builder.append(sep);
}
}
return builder.toString();
}
/**
* Makes an enum name human readable (fixes spaces, capitalization, etc)
*
* @param enumName The name of the enum to neaten up.
* @return The human-readable enum name.
*/
public static String makeEnumHumanReadable(String enumName) {
StringBuilder builder = new StringBuilder(enumName.length() + 1);
String[] words = enumName.split("_");
for (String word : words) {
if (word.length() <= 2) {
builder.append(word); // assume that it's an abbrevation
} else {
builder.append(word.charAt(0));
builder.append(word.substring(1).toLowerCase());
}
builder.append(' ');
}
return builder.substring(0, enumName.length());
}
/**
* Counts the number of <code>chr</code>'s in <code>str</code>.
*
* @param str The string to check for instances of <code>chr</code>.
* @param chr The character to check for.
* @return The number of times <code>chr</code> occurs in <code>str</code>.
*/
public static int countCharacters(String str, char chr) {
int ret = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == chr) {
ret++;
}
}
return ret;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -1,93 +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 java.io.InputStream;
/**
* Provides an abstract wrapper to a stream of bytes.
*
* @author Frz
* @version 1.0
* @since Revision 323
*/
public class InputStreamByteStream implements ByteInputStream {
private InputStream is;
private long read = 0;
/**
* Class constructor.
* Provide an input stream to wrap this around.
*
* @param is The input stream to wrap this object around.
*/
public InputStreamByteStream(InputStream is) {
this.is = is;
}
/**
* Reads the next byte from the stream.
*
* @return Then next byte in the stream.
*/
@Override
public int readByte() {
int temp;
try {
temp = is.read();
if (temp == -1) {
throw new RuntimeException("EOF");
}
read++;
return temp;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Gets the number of bytes read from the stream.
*
* @return The number of bytes read as a long integer.
*/
@Override
public long getBytesRead() {
return read;
}
/**
* Returns the number of bytes left in the stream.
*
* @return The number of bytes available for reading as a long integer.
*/
@Override
public long available() {
try {
return is.available();
} catch (IOException e) {
e.printStackTrace();
System.out.println("ERROR" + e);
return 0;
}
}
}

View File

@@ -1,45 +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;
/**
* @author Frz
*/
public interface LittleEndianAccessor {
byte readByte();
char readChar();
short readShort();
int readInt();
Point readPos();
long readLong();
void skip(int num);
byte[] read(int num);
float readFloat();
double readDouble();
String readAsciiString(int n);
String readNullTerminatedAsciiString();
String readMapleAsciiString();
long getBytesRead();
long available();
}

View File

@@ -1,84 +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 java.io.RandomAccessFile;
/**
* Provides an abstract layer to a byte stream. This layer can be accessed
* randomly.
*
* @author Frz
* @version 1.0
* @since Revision 323
*/
public class RandomAccessByteStream implements SeekableInputStreamBytestream {
private RandomAccessFile raf;
private long read = 0;
public RandomAccessByteStream(RandomAccessFile raf) {
super();
this.raf = raf;
}
@Override
public int readByte() {
int temp;
try {
temp = raf.read();
if (temp == -1) {
throw new RuntimeException("EOF");
}
read++;
return temp;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void seek(long offset) throws IOException {
raf.seek(offset);
}
@Override
public long getPosition() throws IOException {
return raf.getFilePointer();
}
@Override
public long getBytesRead() {
return read;
}
@Override
public long available() {
try {
return raf.length() - raf.getFilePointer();
} catch (IOException e) {
e.printStackTrace();
System.out.println("ERROR " + e);
return 0;
}
}
}

View File

@@ -1,51 +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 interface to a stream of bytes. This stream can be
* seeked.
*
* @author Frz
* @version 1.0
* @since 299
*/
public interface SeekableInputStreamBytestream extends ByteInputStream {
/**
* Seeks the stream by the specified offset.
*
* @param offset
* Number of bytes to seek.
* @throws IOException
*/
void seek(long offset) throws IOException;
/**
* Gets the current position of the stream.
*
* @return The stream position as a long integer.
* @throws IOException
*/
long getPosition() throws IOException;
}

View File

@@ -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 tools.data.input;
public interface SeekableLittleEndianAccessor extends LittleEndianAccessor {
void seek(long offset);
long getPosition();
}

View File

@@ -1,56 +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.output;
import java.io.ByteArrayOutputStream;
/**
* Uses a byte array to output a stream of bytes.
*
* @author Frz
* @version 1.0
* @since Revision 352
*/
class BAOSByteOutputStream implements ByteOutputStream {
private ByteArrayOutputStream baos;
/**
* Class constructor - Wraps the stream around a Java BAOS.
*
* @param baos <code>The ByteArrayOutputStream</code> to wrap this around.
*/
BAOSByteOutputStream(ByteArrayOutputStream baos) {
super();
this.baos = baos;
}
/**
* Writes a byte to the stream.
*
* @param b The byte to write to the stream.
* @see tools.data.output.ByteOutputStream#writeByte(byte)
*/
@Override
public void writeByte(byte b) {
baos.write(b);
}
}

View File

@@ -1,38 +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.output;
/**
* Provides an interface to an output stream of bytes.
*
* @author Frz
* @since Revision 323
* @version 1.0
*/
interface ByteOutputStream {
/**
* Writes a byte to the stream.
*
* @param b The byte to write.
*/
void writeByte(byte b);
}

View File

@@ -1,183 +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.output;
import java.awt.Point;
import java.nio.charset.Charset;
/**
* Provides a generic writer of a little-endian sequence of bytes.
*
* @author Frz
* @version 1.0
* @since Revision 323
*/
public class GenericLittleEndianWriter implements LittleEndianWriter {
private static Charset ASCII = Charset.forName("US-ASCII");
private ByteOutputStream bos;
/**
* Class constructor - Protected to prevent instantiation with no arguments.
*/
protected GenericLittleEndianWriter() {
// Blah!
}
/**
* Sets the byte-output stream for this instance of the object.
*
* @param bos The new output stream to set.
*/
void setByteOutputStream(ByteOutputStream bos) {
this.bos = bos;
}
/**
* Write an array of bytes to the stream.
*
* @param b The bytes to write.
*/
@Override
public void write(byte[] b) {
for (int x = 0; x < b.length; x++) {
bos.writeByte(b[x]);
}
}
/**
* Write a byte to the stream.
*
* @param b The byte to write.
*/
@Override
public void write(byte b) {
bos.writeByte(b);
}
/**
* Write a byte in integer form to the stream.
*
* @param b The byte as an <code>Integer</code> to write.
*/
@Override
public void write(int b) {
bos.writeByte((byte) b);
}
@Override
public void skip(int b) {
write(new byte[b]);
}
/**
* Write a short integer to the stream.
*
* @param i The short integer to write.
*/
@Override
public void writeShort(int i) {
bos.writeByte((byte) (i & 0xFF));
bos.writeByte((byte) ((i >>> 8) & 0xFF));
}
/**
* Writes an integer to the stream.
*
* @param i The integer to write.
*/
@Override
public void writeInt(int i) {
bos.writeByte((byte) (i & 0xFF));
bos.writeByte((byte) ((i >>> 8) & 0xFF));
bos.writeByte((byte) ((i >>> 16) & 0xFF));
bos.writeByte((byte) ((i >>> 24) & 0xFF));
}
/**
* Writes an ASCII string the the stream.
*
* @param s The ASCII string to write.
*/
@Override
public void writeAsciiString(String s) {
write(s.getBytes(ASCII));
}
/**
* Writes a maple-convention ASCII string to the stream.
*
* @param s The ASCII string to use maple-convention to write.
*/
@Override
public void writeMapleAsciiString(String s) {
writeShort((short) s.length());
writeAsciiString(s);
}
/**
* Writes a null-terminated ASCII string to the stream.
*
* @param s The ASCII string to write.
*/
@Override
public void writeNullTerminatedAsciiString(String s) {
writeAsciiString(s);
write(0);
}
/**
* Write a long integer to the stream.
* @param l The long integer to write.
*/
@Override
public void writeLong(long l) {
bos.writeByte((byte) (l & 0xFF));
bos.writeByte((byte) ((l >>> 8) & 0xFF));
bos.writeByte((byte) ((l >>> 16) & 0xFF));
bos.writeByte((byte) ((l >>> 24) & 0xFF));
bos.writeByte((byte) ((l >>> 32) & 0xFF));
bos.writeByte((byte) ((l >>> 40) & 0xFF));
bos.writeByte((byte) ((l >>> 48) & 0xFF));
bos.writeByte((byte) ((l >>> 56) & 0xFF));
}
/**
* Writes a 2D 4 byte position information
*
* @param s The Point position to write.
*/
@Override
public void writePos(Point s) {
writeShort(s.x);
writeShort(s.y);
}
/**
* Writes a boolean true ? 1 : 0
*
* @param b The boolean to write.
*/
@Override
public void writeBool(final boolean b) {
write(b ? 1 : 0);
}
}

View File

@@ -1,114 +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.output;
import java.awt.Point;
/**
* Provides an interface to a writer class that writes a little-endian sequence
* of bytes.
*
* @author Frz
* @version 1.0
* @since Revision 323
*/
public interface LittleEndianWriter {
/**
* Write an array of bytes to the sequence.
*
* @param b The bytes to write.
*/
public void write(byte b[]);
/**
* Write a byte to the sequence.
*
* @param b The byte to write.
*/
public void write(byte b);
/**
* Write a byte in integer form to the sequence.
*
* @param b The byte as an <code>Integer</code> to write.
*/
public void write(int b);
public void skip(int b);
/**
* Writes an integer to the sequence.
*
* @param i The integer to write.
*/
public void writeInt(int i);
/**
* Write a short integer to the sequence.
*
* @param s The short integer to write.
*/
public void writeShort(int s);
/**
* Write a long integer to the sequence.
*
* @param l The long integer to write.
*/
public void writeLong(long l);
/**
* Writes an ASCII string the the sequence.
*
* @param s The ASCII string to write.
*/
void writeAsciiString(String s);
/**
* Writes a null-terminated ASCII string to the sequence.
*
* @param s The ASCII string to write.
*/
void writeNullTerminatedAsciiString(String s);
/**
* Writes a maple-convention ASCII string to the sequence.
*
* @param s The ASCII string to use maple-convention to write.
*/
void writeMapleAsciiString(String s);
/**
* Writes a 2D 4 byte position information
*
* @param s The Point position to write.
*/
void writePos(Point s);
/**
* Writes a boolean true ? 1 : 0
*
* @param b The boolean to write.
*/
void writeBool(final boolean b);
}

View File

@@ -1,73 +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.output;
import java.io.ByteArrayOutputStream;
import tools.HexTool;
/**
* Writes a maplestory-packet little-endian stream of bytes.
*
* @author Frz
* @version 1.0
* @since Revision 352
*/
public class MaplePacketLittleEndianWriter extends GenericLittleEndianWriter {
private ByteArrayOutputStream baos;
/**
* Constructor - initializes this stream with a default size.
*/
public MaplePacketLittleEndianWriter() {
this(32);
}
/**
* Constructor - initializes this stream with size <code>size</code>.
*
* @param size The size of the underlying stream.
*/
public MaplePacketLittleEndianWriter(int size) {
this.baos = new ByteArrayOutputStream(size);
setByteOutputStream(new BAOSByteOutputStream(baos));
}
/**
* Gets a <code>MaplePacket</code> instance representing this
* sequence of bytes.
*
* @return A <code>MaplePacket</code> with the bytes in this stream.
*/
public byte[] getPacket() {
return baos.toByteArray();
}
/**
* Changes this packet into a human-readable hexadecimal stream of bytes.
*
* @return This packet as hex digits.
*/
@Override
public String toString() {
return HexTool.toString(baos.toByteArray());
}
}