MoparClassic/GameServer/src/org/moparscape/msc/gs/tools/DataConversions.java
Travis Burtrum 57a8bdff9f Removed hex-string lib and scala class, can do it in 1 line of pure java.
Also synchronized around md, since it can be accessed by multiple threads, right?
2012-03-17 23:56:04 -04:00

423 lines
10 KiB
Java

package org.moparscape.msc.gs.tools;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Random;
import org.moparscape.msc.gs.connection.RSCPacket;
import org.moparscape.msc.gs.core.GameEngine;
import org.moparscape.msc.gs.model.Point;
import org.moparscape.msc.gs.util.Logger;
public final class DataConversions {
private static char characters[] = { ' ', 'e', 't', 'a', 'o', 'i', 'h',
'n', 's', 'r', 'd', 'l', 'u', 'm', 'w', 'c', 'y', 'f', 'g', 'p',
'b', 'v', 'k', 'x', 'j', 'q', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', ' ', '!', '?', '.', ',', ':', ';', '(', ')',
'-', '&', '*', '\\', '\'', '@', '#', '+', '=', '\243', '$', '%',
'"', '[', ']' };
private static SimpleDateFormat formatter = new SimpleDateFormat(
"HH:mm:ss dd-MM-yy");
private static final BigInteger key = new BigInteger(
"730546719878348732291497161314617369560443701473303681965331739205703475535302276087891130348991033265134162275669215460061940182844329219743687403068279");
private static MessageDigest md;
private static final BigInteger modulus = new BigInteger(
"1549611057746979844352781944553705273443228154042066840514290174539588436243191882510185738846985723357723362764835928526260868977814405651690121789896823");
private static Random rand = new Random();
/**
* Creates an instance of the message digest used for creating md5 hashes
*/
static {
try {
md = MessageDigest.getInstance("MD5");
} catch (Exception e) {
Logger.error(e);
}
}
/**
* Calculates the average of all values in the array
*/
public static int average(int[] values) {
int total = 0;
for (int value : values) {
total += value;
}
return (int) (total / values.length);
}
/**
* Decodes a byte array back into a string
*/
public static String byteToString(byte[] data, int offset, int length) {
char[] buffer = new char[100];
try {
int k = 0;
int l = -1;
for (int i1 = 0; i1 < length; i1++) {
int j1 = data[offset++] & 0xff;
int k1 = j1 >> 4 & 0xf;
if (l == -1) {
if (k1 < 13) {
buffer[k++] = characters[k1];
} else {
l = k1;
}
} else {
buffer[k++] = characters[((l << 4) + k1) - 195];
l = -1;
}
k1 = j1 & 0xf;
if (l == -1) {
if (k1 < 13) {
buffer[k++] = characters[k1];
} else {
l = k1;
}
} else {
buffer[k++] = characters[((l << 4) + k1) - 195];
l = -1;
}
}
boolean flag = true;
for (int l1 = 0; l1 < k; l1++) {
char c = buffer[l1];
if (l1 > 4 && c == '@') {
buffer[l1] = ' ';
}
if (c == '%') {
buffer[l1] = ' ';
}
if (flag && c >= 'a' && c <= 'z') {
buffer[l1] += '\uFFE0';
flag = false;
}
if (c == '.' || c == '!' || c == ':') {
flag = true;
}
}
return new String(buffer, 0, k);
} catch (Exception e) {
return ".";
}
}
/**
* Decrypts an RSA encrypted packet using our private key
*/
public static RSCPacket decryptRSA(byte[] pData) {
try {
BigInteger bigInteger = new BigInteger(pData);
pData = bigInteger.modPow(key, modulus).toByteArray();
return new RSCPacket(null, 0, pData, true);
} catch (Exception e) {
return null;
}
}
/**
* returns the code used to represent the given character in our byte array
* encoding methods
*/
private static int getCharCode(char c) {
for (int x = 0; x < characters.length; x++) {
if (c == characters[x]) {
return x;
}
}
return 0;
}
private static byte getMobCoordOffset(int coord1, int coord2) {
byte offset = (byte) (coord1 - coord2);
if (offset < 0) {
offset += 32;
}
return offset;
}
public static byte[] getMobPositionOffsets(Point p1, Point p2) {
byte[] rv = new byte[2];
rv[0] = getMobCoordOffset(p1.getX(), p2.getX());
rv[1] = getMobCoordOffset(p1.getY(), p2.getY());
return rv;
}
private static byte getObjectCoordOffset(int coord1, int coord2) {
return (byte) (coord1 - coord2);
}
public static byte[] getObjectPositionOffsets(Point p1, Point p2) {
byte[] rv = new byte[2];
rv[0] = getObjectCoordOffset(p1.getX(), p2.getX());
rv[1] = getObjectCoordOffset(p1.getY(), p2.getY());
return rv;
}
/**
* Returns the random number generator
*/
public static Random getRandom() {
return rand;
}
/**
* Converts a usernames hash back to the username
*/
public static String hashToUsername(long l) {
if (l < 0L)
return "invalid_name";
String s = "";
while (l != 0L) {
int i = (int) (l % 37L);
l /= 37L;
if (i == 0)
s = " " + s;
else if (i < 27) {
if (l % 37L == 0L)
s = (char) ((i + 65) - 1) + s;
else
s = (char) ((i + 97) - 1) + s;
} else {
s = (char) ((i + 48) - 27) + s;
}
}
return s;
}
/**
* Checks if the given int is in the array
*/
public static boolean inArray(int[] haystack, int needle) {
for (int option : haystack) {
if (needle == option) {
return true;
}
}
return false;
}
/**
* Checks if the given point is in the array
*/
public static boolean inPointArray(Point[] haystack, Point needle) {
for (Point option : haystack) {
if (needle.getX() == option.getX()
&& needle.getY() == option.getY()) {
return true;
}
}
return false;
}
public static long IPToLong(String ip) {
String[] octets = ip.split("\\.");
long result = 0L;
for (int x = 0; x < 4; x++) {
result += Integer.parseInt(octets[x]) * Math.pow(256, 3 - x);
}
return result;
}
public static String IPToString(long ip) {
String result = "0.0.0.0";
for (int x = 0; x < 4; x++) {
int octet = (int) (ip / Math.pow(256, 3 - x));
ip -= octet * Math.pow(256, 3 - x);
if (x == 0) {
result = String.valueOf(octet);
} else {
result += ("." + octet);
}
}
return result;
}
public static void main(String[] argv) throws Exception {
if (argv[0].equals("encode"))
Logger.println(usernameToHash(argv[1]));
if (argv[0].equals("decode"))
Logger.println(hashToUsername(Long.parseLong(argv[1])));
}
/**
* returns the max of the 2 values
*/
public static int max(int i1, int i2) {
return i1 > i2 ? i1 : i2;
}
/**
* returns the md5 hash of a string
*/
public static String md5(String s) {
synchronized (md){
md.reset();
md.update(s.getBytes());
return toHex(md.digest());
}
}
public static String toHex(byte[] bytes) {
// change below to lower or uppercase X to control case of output
return String.format("%0" + (bytes.length << 1) + "x", new BigInteger(1, bytes));
}
/**
* Returns true percent% of the time
*/
public static boolean percentChance(int percent) {
return random(1, 100) <= percent;
}
/**
* returns a random number within the given bounds
*/
public static double random(double low, double high) {
return high - (rand.nextDouble() * low);
}
/**
* returns a random number within the given bounds
*/
public static int random(int low, int high) {
return low + rand.nextInt(high - low + 1);
}
/**
* returns a random number within the given bounds, but allows for certain
* values to be weighted
*/
public static int randomWeighted(int low, int dip, int peak, int max) {
int total = 0;
int probability = 100;
int[] probArray = new int[max + 1];
for (int x = 0; x < probArray.length; x++) {
total += probArray[x] = probability;
if (x < dip || x > peak) {
probability -= 3;
} else {
probability += 3;
}
}
int hit = random(0, total);
total = 0;
for (int x = 0; x < probArray.length; x++) {
if (hit >= total && hit < (total + probArray[x])) {
return x;
}
total += probArray[x];
}
return 0;
}
public static double round(double value, int decimalPlace) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return (bd.doubleValue());
}
public static int roundUp(double val) {
return (int) Math.round(val + 0.5D);
}
/**
* Returns a ByteBuffer containing everything available from the given
* InputStream
*/
public static final ByteBuffer streamToBuffer(BufferedInputStream in)
throws IOException {
byte[] buffer = new byte[in.available()];
in.read(buffer, 0, buffer.length);
return ByteBuffer.wrap(buffer);
}
/**
* Encodes a string into a byte array
*/
public static byte[] stringToByteArray(String message) {
byte[] buffer = new byte[100];
if (message.length() > 80) {
message = message.substring(0, 80);
}
message = message.toLowerCase();
int length = 0;
int j = -1;
for (int k = 0; k < message.length(); k++) {
int code = getCharCode(message.charAt(k));
if (code > 12) {
code += 195;
}
if (j == -1) {
if (code < 13)
j = code;
else
buffer[length++] = (byte) code;
} else if (code < 13) {
buffer[length++] = (byte) ((j << 4) + code);
j = -1;
} else {
buffer[length++] = (byte) ((j << 4) + (code >> 4));
j = code & 0xf;
}
}
if (j != -1) {
buffer[length++] = (byte) (j << 4);
}
byte[] string = new byte[length];
System.arraycopy(buffer, 0, string, 0, length);
return string;
}
public static String timeFormat(long l) {
return formatter.format(l);
}
public static String timeSince(long time) {
int seconds = (int) ((GameEngine.getTime() - time) / 1000);
int minutes = (int) (seconds / 60);
int hours = (int) (minutes / 60);
int days = (int) (hours / 24);
return days + " days " + (hours % 24) + " hours " + (minutes % 60)
+ " mins";
}
/**
* Converts a username to a unique hash
*/
public static long usernameToHash(String s) {
s = s.toLowerCase();
String s1 = "";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 'a' && c <= 'z')
s1 = s1 + c;
else if (c >= '0' && c <= '9')
s1 = s1 + c;
else
s1 = s1 + ' ';
}
s1 = s1.trim();
if (s1.length() > 12)
s1 = s1.substring(0, 12);
long l = 0L;
for (int j = 0; j < s1.length(); j++) {
char c1 = s1.charAt(j);
l *= 37L;
if (c1 >= 'a' && c1 <= 'z')
l += (1 + c1) - 97;
else if (c1 >= '0' && c1 <= '9')
l += (27 + c1) - 48;
}
return l;
}
}