This commit is contained in:
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.lang.management.LockInfo;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MonitorInfo;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.Shutdown;
|
||||
import com.l2jmobius.gameserver.util.Broadcast;
|
||||
|
||||
/**
|
||||
* Thread to check for deadlocked threads.
|
||||
* @author -Nemesiss- L2M
|
||||
*/
|
||||
public class DeadLockDetector extends Thread
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(DeadLockDetector.class.getName());
|
||||
|
||||
/** Interval to check for deadlocked threads */
|
||||
private static final int _sleepTime = Config.DEADLOCK_CHECK_INTERVAL * 1000;
|
||||
|
||||
private final ThreadMXBean tmx;
|
||||
|
||||
public DeadLockDetector()
|
||||
{
|
||||
super("DeadLockDetector");
|
||||
tmx = ManagementFactory.getThreadMXBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run()
|
||||
{
|
||||
boolean deadlock = false;
|
||||
while (!deadlock)
|
||||
{
|
||||
try
|
||||
{
|
||||
final long[] ids = tmx.findDeadlockedThreads();
|
||||
|
||||
if (ids != null)
|
||||
{
|
||||
deadlock = true;
|
||||
final ThreadInfo[] tis = tmx.getThreadInfo(ids, true, true);
|
||||
final StringBuilder info = new StringBuilder();
|
||||
info.append("DeadLock Found!");
|
||||
info.append(Config.EOL);
|
||||
for (ThreadInfo ti : tis)
|
||||
{
|
||||
info.append(ti.toString());
|
||||
}
|
||||
|
||||
for (ThreadInfo ti : tis)
|
||||
{
|
||||
final LockInfo[] locks = ti.getLockedSynchronizers();
|
||||
final MonitorInfo[] monitors = ti.getLockedMonitors();
|
||||
if ((locks.length == 0) && (monitors.length == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ThreadInfo dl = ti;
|
||||
info.append("Java-level deadlock:");
|
||||
info.append(Config.EOL);
|
||||
info.append('\t');
|
||||
info.append(dl.getThreadName());
|
||||
info.append(" is waiting to lock ");
|
||||
info.append(dl.getLockInfo().toString());
|
||||
info.append(" which is held by ");
|
||||
info.append(dl.getLockOwnerName());
|
||||
info.append(Config.EOL);
|
||||
while ((dl = tmx.getThreadInfo(new long[]
|
||||
{
|
||||
dl.getLockOwnerId()
|
||||
}, true, true)[0]).getThreadId() != ti.getThreadId())
|
||||
{
|
||||
info.append('\t');
|
||||
info.append(dl.getThreadName());
|
||||
info.append(" is waiting to lock ");
|
||||
info.append(dl.getLockInfo().toString());
|
||||
info.append(" which is held by ");
|
||||
info.append(dl.getLockOwnerName());
|
||||
info.append(Config.EOL);
|
||||
}
|
||||
}
|
||||
_log.warning(info.toString());
|
||||
|
||||
if (Config.RESTART_ON_DEADLOCK)
|
||||
{
|
||||
Broadcast.toAllOnlinePlayers("Server has stability issues - restarting now.");
|
||||
Shutdown.getInstance().startTelnetShutdown("DeadLockDetector - Auto Restart", 60, true);
|
||||
}
|
||||
}
|
||||
Thread.sleep(_sleepTime);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.log(Level.WARNING, "DeadLockDetector: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
145
L2J_Mobius_HighFive/java/com/l2jmobius/util/EmptyQueue.java
Normal file
145
L2J_Mobius_HighFive/java/com/l2jmobius/util/EmptyQueue.java
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* @author UnAfraid
|
||||
* @param <E>
|
||||
*/
|
||||
public final class EmptyQueue<E> implements Queue<E>
|
||||
{
|
||||
private static final Queue<Object> EMPTY_QUEUE = new EmptyQueue<>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> Queue<E> emptyQueue()
|
||||
{
|
||||
return (Queue<E>) EMPTY_QUEUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator()
|
||||
{
|
||||
return Collections.<E> emptyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray()
|
||||
{
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E element()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E peek()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
155
L2J_Mobius_HighFive/java/com/l2jmobius/util/EnumIntBitmask.java
Normal file
155
L2J_Mobius_HighFive/java/com/l2jmobius/util/EnumIntBitmask.java
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
/**
|
||||
* @author HorridoJoho
|
||||
* @param <E> The enum type
|
||||
*/
|
||||
public final class EnumIntBitmask<E extends Enum<E>> implements Cloneable
|
||||
{
|
||||
public static <E extends Enum<E>> int getAllBitmask(Class<E> enumClass)
|
||||
{
|
||||
int allBitmask = 0;
|
||||
final E[] values = enumClass.getEnumConstants();
|
||||
if (values.length > 32)
|
||||
{
|
||||
throw new IllegalArgumentException("Enum too big for an integer bitmask.");
|
||||
}
|
||||
for (E value : values)
|
||||
{
|
||||
allBitmask |= 1 << value.ordinal();
|
||||
}
|
||||
return allBitmask;
|
||||
}
|
||||
|
||||
private final Class<E> _enumClass;
|
||||
private int _bitmask;
|
||||
|
||||
public EnumIntBitmask(Class<E> enumClass, boolean all)
|
||||
{
|
||||
_enumClass = enumClass;
|
||||
|
||||
final E[] values = _enumClass.getEnumConstants();
|
||||
if (values.length > 32)
|
||||
{
|
||||
throw new IllegalArgumentException("Enum too big for an integer bitmask.");
|
||||
}
|
||||
|
||||
if (all)
|
||||
{
|
||||
setAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
public EnumIntBitmask(Class<E> enumClass, int bitmask)
|
||||
{
|
||||
_enumClass = enumClass;
|
||||
_bitmask = bitmask;
|
||||
}
|
||||
|
||||
public void setAll()
|
||||
{
|
||||
set(_enumClass.getEnumConstants());
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
_bitmask = 0;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void set(E... many)
|
||||
{
|
||||
clear();
|
||||
for (E one : many)
|
||||
{
|
||||
_bitmask |= 1 << one.ordinal();
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void set(E first, E... more)
|
||||
{
|
||||
clear();
|
||||
add(first, more);
|
||||
}
|
||||
|
||||
public void setBitmask(int bitmask)
|
||||
{
|
||||
_bitmask = bitmask;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void add(E first, E... more)
|
||||
{
|
||||
_bitmask |= 1 << first.ordinal();
|
||||
if (more != null)
|
||||
{
|
||||
for (E one : more)
|
||||
{
|
||||
_bitmask |= 1 << one.ordinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void remove(E first, E... more)
|
||||
{
|
||||
_bitmask &= ~(1 << first.ordinal());
|
||||
if (more != null)
|
||||
{
|
||||
for (E one : more)
|
||||
{
|
||||
_bitmask &= ~(1 << one.ordinal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final boolean has(E first, E... more)
|
||||
{
|
||||
if ((_bitmask & (1 << first.ordinal())) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (E one : more)
|
||||
{
|
||||
if ((_bitmask & (1 << one.ordinal())) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumIntBitmask<E> clone()
|
||||
{
|
||||
return new EnumIntBitmask<>(_enumClass, _bitmask);
|
||||
}
|
||||
|
||||
public int getBitmask()
|
||||
{
|
||||
return _bitmask;
|
||||
}
|
||||
}
|
251
L2J_Mobius_HighFive/java/com/l2jmobius/util/HexUtils.java
Normal file
251
L2J_Mobius_HighFive/java/com/l2jmobius/util/HexUtils.java
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author HorridoJoho
|
||||
*/
|
||||
public class HexUtils
|
||||
{
|
||||
// lookup table for hex characters
|
||||
private static final char[] _NIBBLE_CHAR_LOOKUP =
|
||||
{
|
||||
'0',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F'
|
||||
};
|
||||
private static final char[] _NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray();
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character presentation of a byte<br>
|
||||
* This call is equivalent to {@link HexUtils#b2HexChars(byte, char[], int)} with parameters (data, null, 0)
|
||||
* @param data byte to generate the hexadecimal character presentation from
|
||||
* @return a new char array with exactly 2 elements
|
||||
*/
|
||||
public static char[] b2HexChars(byte data)
|
||||
{
|
||||
return b2HexChars(data, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character presentation of a byte
|
||||
* @param data byte to generate the hexadecimal character presentation from
|
||||
* @param dstHexChars the char array the hexadecimal character presentation should be copied to, if this is null, dstOffset is ignored and a new char array with 2 elements is created
|
||||
* @param dstOffset offset at which the hexadecimal character presentation is copied to dstHexChars
|
||||
* @return the char array the hexadecimal character presentation was copied to
|
||||
*/
|
||||
public static char[] b2HexChars(byte data, char[] dstHexChars, int dstOffset)
|
||||
{
|
||||
if (dstHexChars == null)
|
||||
{
|
||||
dstHexChars = new char[2];
|
||||
dstOffset = 0;
|
||||
}
|
||||
|
||||
// /////////////////////////////
|
||||
// NIBBLE LOOKUP
|
||||
dstHexChars[dstOffset] = _NIBBLE_CHAR_LOOKUP[(data & 0xF0) >> 4];
|
||||
dstHexChars[dstOffset + 1] = _NIBBLE_CHAR_LOOKUP[data & 0x0F];
|
||||
|
||||
return dstHexChars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character presentation of an integer This call is equivalent to {@link HexUtils#int2HexChars(int, char[], int)} with parameters (data, null, 0)
|
||||
* @param data integer to generate the hexadecimal character presentation from
|
||||
* @return new char array with 8 elements
|
||||
*/
|
||||
public static char[] int2HexChars(int data)
|
||||
{
|
||||
return int2HexChars(data, new char[8], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character presentation of an integer
|
||||
* @param data integer to generate the hexadecimal character presentation from
|
||||
* @param dstHexChars the char array the hexadecimal character presentation should be copied to, if this is null, dstOffset is ignored and a new char array with 8 elements is created
|
||||
* @param dstOffset offset at which the hexadecimal character presentation is copied to dstHexChars
|
||||
* @return the char array the hexadecimal character presentation was copied to
|
||||
*/
|
||||
public static char[] int2HexChars(int data, char[] dstHexChars, int dstOffset)
|
||||
{
|
||||
if (dstHexChars == null)
|
||||
{
|
||||
dstHexChars = new char[8];
|
||||
dstOffset = 0;
|
||||
}
|
||||
|
||||
b2HexChars((byte) ((data & 0xFF000000) >> 24), dstHexChars, dstOffset);
|
||||
b2HexChars((byte) ((data & 0x00FF0000) >> 16), dstHexChars, dstOffset + 2);
|
||||
b2HexChars((byte) ((data & 0x0000FF00) >> 8), dstHexChars, dstOffset + 4);
|
||||
b2HexChars((byte) (data & 0x000000FF), dstHexChars, dstOffset + 6);
|
||||
return dstHexChars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character presentation of a byte array<br>
|
||||
* This call is equivalent to {@link HexUtils#bArr2HexChars(byte[], int, int, char[], int)} with parameters (data, offset, len, null, 0)
|
||||
* @param data byte array to generate the hexadecimal character presentation from
|
||||
* @param offset offset where to start in data array
|
||||
* @param len number of bytes to generate the hexadecimal character presentation from
|
||||
* @return a new char array with len*2 elements
|
||||
*/
|
||||
public static char[] bArr2HexChars(byte[] data, int offset, int len)
|
||||
{
|
||||
return bArr2HexChars(data, offset, len, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character presentation of a byte array
|
||||
* @param data byte array to generate the hexadecimal character presentation from
|
||||
* @param offset offset where to start in data array
|
||||
* @param len number of bytes to generate the hexadecimal character presentation from
|
||||
* @param dstHexChars the char array the hexadecimal character presentation should be copied to, if this is null, dstOffset is ignored and a new char array with len*2 elements is created
|
||||
* @param dstOffset offset at which the hexadecimal character presentation is copied to dstHexChars
|
||||
* @return the char array the hexadecimal character presentation was copied to
|
||||
*/
|
||||
public static char[] bArr2HexChars(byte[] data, int offset, int len, char[] dstHexChars, int dstOffset)
|
||||
{
|
||||
if (dstHexChars == null)
|
||||
{
|
||||
dstHexChars = new char[len * 2];
|
||||
dstOffset = 0;
|
||||
}
|
||||
|
||||
for (int dataIdx = offset, charsIdx = dstOffset; dataIdx < (len + offset); ++dataIdx, ++charsIdx)
|
||||
{
|
||||
// /////////////////////////////
|
||||
// NIBBLE LOOKUP, we duplicate the code from b2HexChars here, we want to save a few cycles(for charsIdx increment)
|
||||
dstHexChars[charsIdx] = _NIBBLE_CHAR_LOOKUP[(data[dataIdx] & 0xF0) >> 4];
|
||||
dstHexChars[++charsIdx] = _NIBBLE_CHAR_LOOKUP[data[dataIdx] & 0x0F];
|
||||
}
|
||||
|
||||
return dstHexChars;
|
||||
}
|
||||
|
||||
public static char[] bArr2AsciiChars(byte[] data, int offset, int len)
|
||||
{
|
||||
return bArr2AsciiChars(data, offset, len, new char[len], 0);
|
||||
}
|
||||
|
||||
public static char[] bArr2AsciiChars(byte[] data, int offset, int len, char[] dstAsciiChars, int dstOffset)
|
||||
{
|
||||
if (dstAsciiChars == null)
|
||||
{
|
||||
dstAsciiChars = new char[len];
|
||||
dstOffset = 0;
|
||||
}
|
||||
|
||||
for (int dataIdx = offset, charsIdx = dstOffset; dataIdx < (len + offset); ++dataIdx, ++charsIdx)
|
||||
{
|
||||
dstAsciiChars[charsIdx] = (data[dataIdx] > 0x1f) && (data[dataIdx] < 0x80) ? (char) data[dataIdx] : '.';
|
||||
}
|
||||
|
||||
return dstAsciiChars;
|
||||
}
|
||||
|
||||
private static final int _HEX_ED_BPL = 16;
|
||||
private static final int _HEX_ED_CPB = 2;
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal character representation of a byte array like in a hex editor<br>
|
||||
* Line Format: {OFFSET} {HEXADECIMAL} {ASCII}({NEWLINE})<br>
|
||||
* {OFFSET} = offset of the first byte in line(8 chars)<br>
|
||||
* {HEXADECIMAL} = hexadecimal character representation({@link #_HEX_ED_BPL}*2 chars)<br>
|
||||
* {ASCII} = ascii character presentation({@link #_HEX_ED_BPL} chars)
|
||||
* @param data byte array to generate the hexadecimal character representation
|
||||
* @param len the number of bytes to generate the hexadecimal character representation from
|
||||
* @return byte array which contains the hexadecimal character representation of the given byte array
|
||||
*/
|
||||
public static char[] bArr2HexEdChars(byte[] data, int len)
|
||||
{
|
||||
// {OFFSET} {HEXADECIMAL} {ASCII}{NEWLINE}
|
||||
final int lineLength = 9 + (_HEX_ED_BPL * _HEX_ED_CPB) + 1 + _HEX_ED_BPL + _NEW_LINE_CHARS.length;
|
||||
final int lenBplMod = len % _HEX_ED_BPL;
|
||||
// create text buffer
|
||||
// 1. don't allocate a full last line if not _HEX_ED_BPL bytes are shown in last line
|
||||
// 2. no new line at end of buffer
|
||||
// BUG: when the length is multiple of _HEX_ED_BPL we erase the whole ascii space with this
|
||||
// char[] textData = new char[lineLength * numLines - (_HEX_ED_BPL - (len % _HEX_ED_BPL)) - _NEW_LINE_CHARS.length];
|
||||
// FIXED HERE
|
||||
int numLines;
|
||||
char[] textData;
|
||||
if (lenBplMod == 0)
|
||||
{
|
||||
numLines = len / _HEX_ED_BPL;
|
||||
textData = new char[(lineLength * numLines) - _NEW_LINE_CHARS.length];
|
||||
}
|
||||
else
|
||||
{
|
||||
numLines = (len / _HEX_ED_BPL) + 1;
|
||||
textData = new char[(lineLength * numLines) - (_HEX_ED_BPL - lenBplMod) - _NEW_LINE_CHARS.length];
|
||||
}
|
||||
|
||||
// performance penalty, only doing space filling in the loop is faster
|
||||
// Arrays.fill(textData, ' ');
|
||||
|
||||
int dataOffset;
|
||||
int dataLen;
|
||||
int lineStart;
|
||||
int lineHexDataStart;
|
||||
int lineAsciiDataStart;
|
||||
for (int i = 0; i < numLines; ++i)
|
||||
{
|
||||
dataOffset = i * _HEX_ED_BPL;
|
||||
dataLen = Math.min(len - dataOffset, _HEX_ED_BPL);
|
||||
lineStart = i * lineLength;
|
||||
lineHexDataStart = lineStart + 9;
|
||||
lineAsciiDataStart = lineHexDataStart + (_HEX_ED_BPL * _HEX_ED_CPB) + 1;
|
||||
|
||||
int2HexChars(dataOffset, textData, lineStart); // the offset of this line
|
||||
textData[lineHexDataStart - 1] = ' '; // separate
|
||||
bArr2HexChars(data, dataOffset, dataLen, textData, lineHexDataStart); // the data in hex
|
||||
bArr2AsciiChars(data, dataOffset, dataLen, textData, lineAsciiDataStart); // the data in ascii
|
||||
|
||||
if (i < (numLines - 1))
|
||||
{
|
||||
textData[lineAsciiDataStart - 1] = ' '; // separate
|
||||
System.arraycopy(_NEW_LINE_CHARS, 0, textData, lineAsciiDataStart + _HEX_ED_BPL, _NEW_LINE_CHARS.length); // the new line
|
||||
}
|
||||
else if (dataLen < _HEX_ED_BPL)
|
||||
{
|
||||
Arrays.fill(textData, lineHexDataStart + (dataLen * _HEX_ED_CPB), lineHexDataStart + (dataLen * _HEX_ED_CPB) + ((_HEX_ED_BPL - dataLen) * _HEX_ED_CPB) + 1, ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
// last line which shows _HEX_ED_BPL bytes
|
||||
textData[lineAsciiDataStart - 1] = ' '; // separate
|
||||
}
|
||||
}
|
||||
return textData;
|
||||
}
|
||||
}
|
159
L2J_Mobius_HighFive/java/com/l2jmobius/util/IPSubnet.java
Normal file
159
L2J_Mobius_HighFive/java/com/l2jmobius/util/IPSubnet.java
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class IPSubnet
|
||||
{
|
||||
final byte[] _addr;
|
||||
final byte[] _mask;
|
||||
final boolean _isIPv4;
|
||||
|
||||
public IPSubnet(String input) throws UnknownHostException, NumberFormatException, ArrayIndexOutOfBoundsException
|
||||
{
|
||||
final int idx = input.indexOf("/");
|
||||
if (idx > 0)
|
||||
{
|
||||
_addr = InetAddress.getByName(input.substring(0, idx)).getAddress();
|
||||
_mask = getMask(Integer.parseInt(input.substring(idx + 1)), _addr.length);
|
||||
_isIPv4 = _addr.length == 4;
|
||||
|
||||
if (!applyMask(_addr))
|
||||
{
|
||||
throw new UnknownHostException(input);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_addr = InetAddress.getByName(input).getAddress();
|
||||
_mask = getMask(_addr.length * 8, _addr.length); // host, no need to check mask
|
||||
_isIPv4 = _addr.length == 4;
|
||||
}
|
||||
}
|
||||
|
||||
public IPSubnet(InetAddress addr, int mask) throws UnknownHostException
|
||||
{
|
||||
_addr = addr.getAddress();
|
||||
_isIPv4 = _addr.length == 4;
|
||||
_mask = getMask(mask, _addr.length);
|
||||
if (!applyMask(_addr))
|
||||
{
|
||||
throw new UnknownHostException(addr.toString() + "/" + mask);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getAddress()
|
||||
{
|
||||
return _addr;
|
||||
}
|
||||
|
||||
public boolean applyMask(byte[] addr)
|
||||
{
|
||||
// V4 vs V4 or V6 vs V6 checks
|
||||
if (_isIPv4 == (addr.length == 4))
|
||||
{
|
||||
for (int i = 0; i < _addr.length; i++)
|
||||
{
|
||||
if ((addr[i] & _mask[i]) != _addr[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check for embedded v4 in v6 addr (not done !)
|
||||
else if (_isIPv4)
|
||||
{
|
||||
// my V4 vs V6
|
||||
for (int i = 0; i < _addr.length; i++)
|
||||
{
|
||||
if ((addr[i + 12] & _mask[i]) != _addr[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// my V6 vs V4
|
||||
for (int i = 0; i < _addr.length; i++)
|
||||
{
|
||||
if ((addr[i] & _mask[i + 12]) != _addr[i + 12])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
int size = 0;
|
||||
for (byte element : _mask)
|
||||
{
|
||||
size += Integer.bitCount(element & 0xFF);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return InetAddress.getByAddress(_addr).toString() + "/" + size;
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o instanceof IPSubnet)
|
||||
{
|
||||
return applyMask(((IPSubnet) o).getAddress());
|
||||
}
|
||||
return (o instanceof InetAddress) && applyMask(((InetAddress) o).getAddress());
|
||||
}
|
||||
|
||||
private static byte[] getMask(int n, int maxLength) throws UnknownHostException
|
||||
{
|
||||
if ((n > (maxLength << 3)) || (n < 0))
|
||||
{
|
||||
throw new UnknownHostException("Invalid netmask: " + n);
|
||||
}
|
||||
|
||||
final byte[] result = new byte[maxLength];
|
||||
for (int i = 0; i < maxLength; i++)
|
||||
{
|
||||
result[i] = (byte) 0xFF;
|
||||
}
|
||||
|
||||
for (int i = (maxLength << 3) - 1; i >= n; i--)
|
||||
{
|
||||
result[i >> 3] = (byte) (result[i >> 3] << 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
143
L2J_Mobius_HighFive/java/com/l2jmobius/util/IPv4Filter.java
Normal file
143
L2J_Mobius_HighFive/java/com/l2jmobius/util/IPv4Filter.java
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.commons.mmocore.IAcceptFilter;
|
||||
|
||||
/**
|
||||
* IPv4 filter.
|
||||
* @author Forsaiken, Zoey76
|
||||
*/
|
||||
public class IPv4Filter implements IAcceptFilter, Runnable
|
||||
{
|
||||
private static final Logger LOG = Logger.getLogger(IPv4Filter.class.getName());
|
||||
private final HashMap<Integer, Flood> _ipFloodMap;
|
||||
private static final long SLEEP_TIME = 5000;
|
||||
|
||||
public IPv4Filter()
|
||||
{
|
||||
_ipFloodMap = new HashMap<>();
|
||||
final Thread t = new Thread(this, getClass().getSimpleName());
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
private static int hash(byte[] ip)
|
||||
{
|
||||
return (ip[0] & 0xFF) | ((ip[1] << 8) & 0xFF00) | ((ip[2] << 16) & 0xFF0000) | ((ip[3] << 24) & 0xFF000000);
|
||||
}
|
||||
|
||||
protected static final class Flood
|
||||
{
|
||||
long lastAccess;
|
||||
int trys;
|
||||
|
||||
Flood()
|
||||
{
|
||||
lastAccess = System.currentTimeMillis();
|
||||
trys = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SocketChannel sc)
|
||||
{
|
||||
final InetAddress addr = sc.socket().getInetAddress();
|
||||
if (!(addr instanceof Inet4Address))
|
||||
{
|
||||
LOG.info(IPv4Filter.class.getSimpleName() + ": Someone tried to connect from something other than IPv4: " + addr.getHostAddress());
|
||||
return false;
|
||||
}
|
||||
|
||||
final int h = hash(addr.getAddress());
|
||||
final long current = System.currentTimeMillis();
|
||||
Flood f;
|
||||
synchronized (_ipFloodMap)
|
||||
{
|
||||
f = _ipFloodMap.get(h);
|
||||
}
|
||||
if (f != null)
|
||||
{
|
||||
if (f.trys == -1)
|
||||
{
|
||||
f.lastAccess = current;
|
||||
return false;
|
||||
}
|
||||
|
||||
f.lastAccess = current;
|
||||
if ((f.lastAccess + 1000) > current)
|
||||
{
|
||||
if (f.trys >= 3)
|
||||
{
|
||||
f.trys = -1;
|
||||
return false;
|
||||
}
|
||||
f.trys++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
synchronized (_ipFloodMap)
|
||||
{
|
||||
_ipFloodMap.put(h, new Flood());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
final long reference = System.currentTimeMillis() - (1000 * 300);
|
||||
synchronized (_ipFloodMap)
|
||||
{
|
||||
final Iterator<Entry<Integer, Flood>> it = _ipFloodMap.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
if (it.next().getValue().lastAccess < reference)
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
/**
|
||||
* Specialized {@link LogManager} class.<br>
|
||||
* Prevents log devices to close before shutdown sequence so the shutdown sequence can make logging.
|
||||
*/
|
||||
public class L2LogManager extends LogManager
|
||||
{
|
||||
public L2LogManager()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void doReset()
|
||||
{
|
||||
super.reset();
|
||||
}
|
||||
}
|
353
L2J_Mobius_HighFive/java/com/l2jmobius/util/PrimeFinder.java
Normal file
353
L2J_Mobius_HighFive/java/com/l2jmobius/util/PrimeFinder.java
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (c) 1999 CERN - European Organization for Nuclear Research.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear in
|
||||
* supporting documentation. CERN makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without expressed or implied warranty.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* <b>Modified for Trove to use the java.util.Arrays sort/search<br>
|
||||
* algorithms instead of those provided with colt.</b><br>
|
||||
* Used to keep hash table capacities prime numbers.<br>
|
||||
* Not of interest for users; only for implementors of hashtables.<br>
|
||||
* <p>
|
||||
* Choosing prime numbers as hash table capacities is a good idea<br>
|
||||
* to keep them working fast, particularly under hash table expansions.<br>
|
||||
* <p>
|
||||
* However, JDK 1.2, JGL 3.1 and many other toolkits do nothing to keep capacities prime.<br>
|
||||
* This class provides efficient means to choose prime capacities.
|
||||
* <p>
|
||||
* Choosing a prime is <tt>O(log 300)</tt> (binary search in a list of 300 ints).<br>
|
||||
* Memory requirements: 1 KB static memory.<br>
|
||||
* @author wolfgang.hoschek@cern.ch
|
||||
* @version 1.0, 09/24/99
|
||||
*/
|
||||
public final class PrimeFinder
|
||||
{
|
||||
/**
|
||||
* The largest prime this class can generate; currently equal to <tt>Integer.MAX_VALUE</tt>.
|
||||
*/
|
||||
public static final int LARGEST_PRIME = Integer.MAX_VALUE; // yes, it is prime.
|
||||
|
||||
/**
|
||||
* The prime number list consists of 11 chunks.<br>
|
||||
* Each chunk contains prime numbers.<br>
|
||||
* A chunk starts with a prime P1.<br>
|
||||
* The next element is a prime P2.<br>
|
||||
* P2 is the smallest prime for which holds: P2 >= 2*P1.<br>
|
||||
* The next element is P3, for which the same holds with respect to P2, and so on. Chunks are chosen such that for any desired capacity >= 1000<br>
|
||||
* the list includes a prime number <= desired capacity * 1.11.<br>
|
||||
* Therefore, primes can be retrieved which are quite close to any<br>
|
||||
* desired capacity, which in turn avoids wasting memory.<br>
|
||||
* For example, the list includes<br>
|
||||
* 1039,1117,1201,1277,1361,1439,1523,1597,1759,1907,2081.<br>
|
||||
* So if you need a prime >= 1040, you will find a prime <= 1040*1.11=1154.<br> Chunks are chosen such that they are optimized for a hashtable growthfactor of 2.0;<br>
|
||||
* If your hashtable has such a growthfactor then, after initially<br>
|
||||
* "rounding to a prime" upon hashtable construction, it will<br>
|
||||
* later expand to prime capacities such that there exist no better primes.<br>
|
||||
* In total these are about 32*10=320 numbers -> 1 KB of static memory needed.<br>
|
||||
* If you are stingy, then delete every second or fourth chunk.
|
||||
*/
|
||||
|
||||
private static final int[] PRIME_CAPACITIES =
|
||||
{
|
||||
// chunk #0
|
||||
LARGEST_PRIME,
|
||||
|
||||
// chunk #1
|
||||
5,
|
||||
11,
|
||||
23,
|
||||
47,
|
||||
97,
|
||||
197,
|
||||
397,
|
||||
797,
|
||||
1597,
|
||||
3203,
|
||||
6421,
|
||||
12853,
|
||||
25717,
|
||||
51437,
|
||||
102877,
|
||||
205759,
|
||||
411527,
|
||||
823117,
|
||||
1646237,
|
||||
3292489,
|
||||
6584983,
|
||||
13169977,
|
||||
26339969,
|
||||
52679969,
|
||||
105359939,
|
||||
210719881,
|
||||
421439783,
|
||||
842879579,
|
||||
1685759167,
|
||||
|
||||
// chunk #2
|
||||
433,
|
||||
877,
|
||||
1759,
|
||||
3527,
|
||||
7057,
|
||||
14143,
|
||||
28289,
|
||||
56591,
|
||||
113189,
|
||||
226379,
|
||||
452759,
|
||||
905551,
|
||||
1811107,
|
||||
3622219,
|
||||
7244441,
|
||||
14488931,
|
||||
28977863,
|
||||
57955739,
|
||||
115911563,
|
||||
231823147,
|
||||
463646329,
|
||||
927292699,
|
||||
1854585413,
|
||||
|
||||
// chunk #3
|
||||
953,
|
||||
1907,
|
||||
3821,
|
||||
7643,
|
||||
15287,
|
||||
30577,
|
||||
61169,
|
||||
122347,
|
||||
244703,
|
||||
489407,
|
||||
978821,
|
||||
1957651,
|
||||
3915341,
|
||||
7830701,
|
||||
15661423,
|
||||
31322867,
|
||||
62645741,
|
||||
125291483,
|
||||
250582987,
|
||||
501165979,
|
||||
1002331963,
|
||||
2004663929,
|
||||
|
||||
// chunk #4
|
||||
1039,
|
||||
2081,
|
||||
4177,
|
||||
8363,
|
||||
16729,
|
||||
33461,
|
||||
66923,
|
||||
133853,
|
||||
267713,
|
||||
535481,
|
||||
1070981,
|
||||
2141977,
|
||||
4283963,
|
||||
8567929,
|
||||
17135863,
|
||||
34271747,
|
||||
68543509,
|
||||
137087021,
|
||||
274174111,
|
||||
548348231,
|
||||
1096696463,
|
||||
|
||||
// chunk #5
|
||||
31,
|
||||
67,
|
||||
137,
|
||||
277,
|
||||
557,
|
||||
1117,
|
||||
2237,
|
||||
4481,
|
||||
8963,
|
||||
17929,
|
||||
35863,
|
||||
71741,
|
||||
143483,
|
||||
286973,
|
||||
573953,
|
||||
1147921,
|
||||
2295859,
|
||||
4591721,
|
||||
9183457,
|
||||
18366923,
|
||||
36733847,
|
||||
73467739,
|
||||
146935499,
|
||||
293871013,
|
||||
587742049,
|
||||
1175484103,
|
||||
|
||||
// chunk #6
|
||||
599,
|
||||
1201,
|
||||
2411,
|
||||
4831,
|
||||
9677,
|
||||
19373,
|
||||
38747,
|
||||
77509,
|
||||
155027,
|
||||
310081,
|
||||
620171,
|
||||
1240361,
|
||||
2480729,
|
||||
4961459,
|
||||
9922933,
|
||||
19845871,
|
||||
39691759,
|
||||
79383533,
|
||||
158767069,
|
||||
317534141,
|
||||
635068283,
|
||||
1270136683,
|
||||
|
||||
// chunk #7
|
||||
311,
|
||||
631,
|
||||
1277,
|
||||
2557,
|
||||
5119,
|
||||
10243,
|
||||
20507,
|
||||
41017,
|
||||
82037,
|
||||
164089,
|
||||
328213,
|
||||
656429,
|
||||
1312867,
|
||||
2625761,
|
||||
5251529,
|
||||
10503061,
|
||||
21006137,
|
||||
42012281,
|
||||
84024581,
|
||||
168049163,
|
||||
336098327,
|
||||
672196673,
|
||||
1344393353,
|
||||
|
||||
// chunk #8
|
||||
3,
|
||||
7,
|
||||
17,
|
||||
37,
|
||||
79,
|
||||
163,
|
||||
331,
|
||||
673,
|
||||
1361,
|
||||
2729,
|
||||
5471,
|
||||
10949,
|
||||
21911,
|
||||
43853,
|
||||
87719,
|
||||
175447,
|
||||
350899,
|
||||
701819,
|
||||
1403641,
|
||||
2807303,
|
||||
5614657,
|
||||
11229331,
|
||||
22458671,
|
||||
44917381,
|
||||
89834777,
|
||||
179669557,
|
||||
359339171,
|
||||
718678369,
|
||||
1437356741,
|
||||
|
||||
// chunk #9
|
||||
43,
|
||||
89,
|
||||
179,
|
||||
359,
|
||||
719,
|
||||
1439,
|
||||
2879,
|
||||
5779,
|
||||
11579,
|
||||
23159,
|
||||
46327,
|
||||
92657,
|
||||
185323,
|
||||
370661,
|
||||
741337,
|
||||
1482707,
|
||||
2965421,
|
||||
5930887,
|
||||
11861791,
|
||||
23723597,
|
||||
47447201,
|
||||
94894427,
|
||||
189788857,
|
||||
379577741,
|
||||
759155483,
|
||||
1518310967,
|
||||
|
||||
// chunk #10
|
||||
379,
|
||||
761,
|
||||
1523,
|
||||
3049,
|
||||
6101,
|
||||
12203,
|
||||
24407,
|
||||
48817,
|
||||
97649,
|
||||
195311,
|
||||
390647,
|
||||
781301,
|
||||
1562611,
|
||||
3125257,
|
||||
6250537,
|
||||
12501169,
|
||||
25002389,
|
||||
50004791,
|
||||
100009607,
|
||||
200019221,
|
||||
400038451,
|
||||
800076929,
|
||||
1600153859
|
||||
};
|
||||
static
|
||||
{ // initializer
|
||||
// The above prime numbers are formatted for human readability.
|
||||
// To find numbers fast, we sort them once and for all.
|
||||
|
||||
Arrays.sort(PRIME_CAPACITIES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a prime number which is <code>>= desiredCapacity</code> and very close to <code>desiredCapacity</code> (within 11% if <code>desiredCapacity >= 1000</code>).
|
||||
* @param desiredCapacity the capacity desired by the user.
|
||||
* @return the capacity which should be used for a hashtable.
|
||||
*/
|
||||
public static int nextPrime(int desiredCapacity)
|
||||
{
|
||||
int i = Arrays.binarySearch(PRIME_CAPACITIES, desiredCapacity);
|
||||
if (i < 0)
|
||||
{
|
||||
// desired capacity not found, choose next prime greater
|
||||
// than desired capacity
|
||||
i = -i - 1; // remember the semantics of binarySearch...
|
||||
}
|
||||
return PRIME_CAPACITIES[i];
|
||||
}
|
||||
}
|
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Simplifies loading of property files and adds logging if a non existing property is requested.
|
||||
* @author NosBit
|
||||
*/
|
||||
public final class PropertiesParser
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(PropertiesParser.class.getName());
|
||||
|
||||
private final Properties _properties = new Properties();
|
||||
private final File _file;
|
||||
|
||||
public PropertiesParser(String name)
|
||||
{
|
||||
this(new File(name));
|
||||
}
|
||||
|
||||
public PropertiesParser(File file)
|
||||
{
|
||||
_file = file;
|
||||
try (FileInputStream fileInputStream = new FileInputStream(file))
|
||||
{
|
||||
try (InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, Charset.defaultCharset()))
|
||||
{
|
||||
_properties.load(inputStreamReader);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] There was an error loading config reason: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containskey(String key)
|
||||
{
|
||||
return _properties.containsKey(key);
|
||||
}
|
||||
|
||||
private String getValue(String key)
|
||||
{
|
||||
final String value = _properties.getProperty(key);
|
||||
return value != null ? value.trim() : null;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key, boolean defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (value.equalsIgnoreCase("true"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (value.equalsIgnoreCase("false"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"boolean\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public byte getByte(String key, byte defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Byte.parseByte(value);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"byte\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public short getShort(String key, short defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Short.parseShort(value);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"short\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public int getInt(String key, int defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"int\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public long getLong(String key, long defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"long\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public float getFloat(String key, float defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Float.parseFloat(value);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"float\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public double getDouble(String key, double defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be \"double\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public String getString(String key, String defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value != null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public <T extends Enum<T>> T getEnum(String key, Class<T> clazz, T defaultValue)
|
||||
{
|
||||
final String value = getValue(key);
|
||||
if (value == null)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] missing property for key: " + key + " using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Enum.valueOf(clazz, value);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
_log.warning("[" + _file.getName() + "] Invalid value specified for key: " + key + " specified value: " + value + " should be enum value of \"" + clazz.getSimpleName() + "\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
457
L2J_Mobius_HighFive/java/com/l2jmobius/util/Rnd.java
Normal file
457
L2J_Mobius_HighFive/java/com/l2jmobius/util/Rnd.java
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @author Forsaiken
|
||||
*/
|
||||
public final class Rnd
|
||||
{
|
||||
/**
|
||||
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
|
||||
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
|
||||
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
|
||||
* @author Forsaiken
|
||||
* @see java.util.Random
|
||||
*/
|
||||
public static final class NonAtomicRandom extends Random
|
||||
{
|
||||
private volatile long _seed;
|
||||
|
||||
public NonAtomicRandom()
|
||||
{
|
||||
this(++SEED_UNIQUIFIER + System.nanoTime());
|
||||
}
|
||||
|
||||
public NonAtomicRandom(long seed)
|
||||
{
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int next(int bits)
|
||||
{
|
||||
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setSeed(long seed)
|
||||
{
|
||||
_seed = (seed ^ MULTIPLIER) & MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Forsaiken
|
||||
*/
|
||||
protected static final class RandomContainer
|
||||
{
|
||||
private final Random _random;
|
||||
|
||||
protected RandomContainer(Random random)
|
||||
{
|
||||
_random = random;
|
||||
}
|
||||
|
||||
public final Random directRandom()
|
||||
{
|
||||
return _random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random double number from 0 to 1
|
||||
* @return A random double number from 0 to 1
|
||||
* @see com.l2jmobius.util.Rnd#nextDouble()
|
||||
*/
|
||||
public final double get()
|
||||
{
|
||||
return _random.nextDouble();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random integer number from 0(inclusive) to n(exclusive)
|
||||
* @param n The superior limit (exclusive)
|
||||
* @return A random integer number from 0 to n-1
|
||||
*/
|
||||
public final int get(int n)
|
||||
{
|
||||
return (int) (_random.nextDouble() * n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random integer number from min(inclusive) to max(inclusive)
|
||||
* @param min The minimum value
|
||||
* @param max The maximum value
|
||||
* @return A random integer number from min to max
|
||||
*/
|
||||
public final int get(int min, int max)
|
||||
{
|
||||
return min + (int) (_random.nextDouble() * ((max - min) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random long number from min(inclusive) to max(inclusive)
|
||||
* @param min The minimum value
|
||||
* @param max The maximum value
|
||||
* @return A random long number from min to max
|
||||
*/
|
||||
public final long get(long min, long max)
|
||||
{
|
||||
return min + (long) (_random.nextDouble() * ((max - min) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random boolean state (true or false)
|
||||
* @return A random boolean state (true or false)
|
||||
* @see java.util.Random#nextBoolean()
|
||||
*/
|
||||
public final boolean nextBoolean()
|
||||
{
|
||||
return _random.nextBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
|
||||
* @param array The array to be filled with random byte numbers
|
||||
* @see java.util.Random#nextBytes(byte[] bytes)
|
||||
*/
|
||||
public final void nextBytes(byte[] array)
|
||||
{
|
||||
_random.nextBytes(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random double number from 0 to 1
|
||||
* @return A random double number from 0 to 1
|
||||
* @see java.util.Random#nextDouble()
|
||||
*/
|
||||
public final double nextDouble()
|
||||
{
|
||||
return _random.nextDouble();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random float number from 0 to 1
|
||||
* @return A random integer number from 0 to 1
|
||||
* @see java.util.Random#nextFloat()
|
||||
*/
|
||||
public final float nextFloat()
|
||||
{
|
||||
return _random.nextFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random gaussian double number from 0 to 1
|
||||
* @return A random gaussian double number from 0 to 1
|
||||
* @see java.util.Random#nextGaussian()
|
||||
*/
|
||||
public final double nextGaussian()
|
||||
{
|
||||
return _random.nextGaussian();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
|
||||
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
|
||||
* @see java.util.Random#nextInt()
|
||||
*/
|
||||
public final int nextInt()
|
||||
{
|
||||
return _random.nextInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
|
||||
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
|
||||
* @see java.util.Random#nextLong()
|
||||
*/
|
||||
public final long nextLong()
|
||||
{
|
||||
return _random.nextLong();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Forsaiken
|
||||
*/
|
||||
public static enum RandomType
|
||||
{
|
||||
/**
|
||||
* For best random quality.
|
||||
* @see java.security.SecureRandom
|
||||
*/
|
||||
SECURE,
|
||||
|
||||
/**
|
||||
* For average random quality.
|
||||
* @see java.util.Random
|
||||
*/
|
||||
UNSECURE_ATOMIC,
|
||||
|
||||
/**
|
||||
* Like {@link com.l2jmobius.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
|
||||
* Each thread has it`s own random instance.<br>
|
||||
* Provides best parallel access speed.
|
||||
* @see com.l2jmobius.util.Rnd.ThreadLocalRandom
|
||||
*/
|
||||
UNSECURE_THREAD_LOCAL,
|
||||
|
||||
/**
|
||||
* Like {@link com.l2jmobius.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
|
||||
* Provides much faster parallel access speed.
|
||||
* @see com.l2jmobius.util.Rnd.NonAtomicRandom
|
||||
*/
|
||||
UNSECURE_VOLATILE
|
||||
}
|
||||
|
||||
/**
|
||||
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
|
||||
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
|
||||
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
|
||||
* Each thread has it`s own random instance.
|
||||
* @author Forsaiken
|
||||
* @see java.util.Random
|
||||
*/
|
||||
public static final class ThreadLocalRandom extends Random
|
||||
{
|
||||
private static final class Seed
|
||||
{
|
||||
long _seed;
|
||||
|
||||
Seed(long seed)
|
||||
{
|
||||
setSeed(seed);
|
||||
}
|
||||
|
||||
final int next(int bits)
|
||||
{
|
||||
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
|
||||
}
|
||||
|
||||
final void setSeed(long seed)
|
||||
{
|
||||
_seed = (seed ^ MULTIPLIER) & MASK;
|
||||
}
|
||||
}
|
||||
|
||||
private final ThreadLocal<Seed> _seedLocal;
|
||||
|
||||
public ThreadLocalRandom()
|
||||
{
|
||||
_seedLocal = new ThreadLocal<Seed>()
|
||||
{
|
||||
@Override
|
||||
public final Seed initialValue()
|
||||
{
|
||||
return new Seed(++SEED_UNIQUIFIER + System.nanoTime());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ThreadLocalRandom(long seed)
|
||||
{
|
||||
_seedLocal = new ThreadLocal<Seed>()
|
||||
{
|
||||
@Override
|
||||
public final Seed initialValue()
|
||||
{
|
||||
return new Seed(seed);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int next(int bits)
|
||||
{
|
||||
return _seedLocal.get().next(bits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setSeed(long seed)
|
||||
{
|
||||
if (_seedLocal != null)
|
||||
{
|
||||
_seedLocal.get().setSeed(seed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final long ADDEND = 0xBL;
|
||||
|
||||
private static final long MASK = (1L << 48) - 1;
|
||||
|
||||
private static final long MULTIPLIER = 0x5DEECE66DL;
|
||||
|
||||
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
|
||||
|
||||
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
|
||||
|
||||
public static Random directRandom()
|
||||
{
|
||||
return rnd.directRandom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random double number from 0 to 1
|
||||
* @return A random double number from 0 to 1
|
||||
* @see com.l2jmobius.util.Rnd#nextDouble()
|
||||
*/
|
||||
public static double get()
|
||||
{
|
||||
return rnd.nextDouble();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random integer number from 0(inclusive) to n(exclusive)
|
||||
* @param n The superior limit (exclusive)
|
||||
* @return A random integer number from 0 to n-1
|
||||
*/
|
||||
public static int get(int n)
|
||||
{
|
||||
return rnd.get(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random integer number from min(inclusive) to max(inclusive)
|
||||
* @param min The minimum value
|
||||
* @param max The maximum value
|
||||
* @return A random integer number from min to max
|
||||
*/
|
||||
public static int get(int min, int max)
|
||||
{
|
||||
return rnd.get(min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random long number from min(inclusive) to max(inclusive)
|
||||
* @param min The minimum value
|
||||
* @param max The maximum value
|
||||
* @return A random long number from min to max
|
||||
*/
|
||||
public static long get(long min, long max)
|
||||
{
|
||||
return rnd.get(min, max);
|
||||
}
|
||||
|
||||
public static RandomContainer newInstance(RandomType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case UNSECURE_ATOMIC:
|
||||
{
|
||||
return new RandomContainer(new Random());
|
||||
}
|
||||
case UNSECURE_VOLATILE:
|
||||
{
|
||||
return new RandomContainer(new NonAtomicRandom());
|
||||
}
|
||||
case UNSECURE_THREAD_LOCAL:
|
||||
{
|
||||
return new RandomContainer(new ThreadLocalRandom());
|
||||
}
|
||||
case SECURE:
|
||||
{
|
||||
return new RandomContainer(new SecureRandom());
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random boolean state (true or false)
|
||||
* @return A random boolean state (true or false)
|
||||
* @see java.util.Random#nextBoolean()
|
||||
*/
|
||||
public static boolean nextBoolean()
|
||||
{
|
||||
return rnd.nextBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the given array with random byte numbers from Byte.MIN_VALUE(inclusive) to Byte.MAX_VALUE(inclusive)
|
||||
* @param array The array to be filled with random byte numbers
|
||||
* @see java.util.Random#nextBytes(byte[] bytes)
|
||||
*/
|
||||
public static void nextBytes(byte[] array)
|
||||
{
|
||||
rnd.nextBytes(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random double number from 0 to 1
|
||||
* @return A random double number from 0 to 1
|
||||
* @see java.util.Random#nextDouble()
|
||||
*/
|
||||
public static double nextDouble()
|
||||
{
|
||||
return rnd.nextDouble();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random float number from 0 to 1
|
||||
* @return A random integer number from 0 to 1
|
||||
* @see java.util.Random#nextFloat()
|
||||
*/
|
||||
public static float nextFloat()
|
||||
{
|
||||
return rnd.nextFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random gaussian double number from 0 to 1
|
||||
* @return A random gaussian double number from 0 to 1
|
||||
* @see java.util.Random#nextGaussian()
|
||||
*/
|
||||
public static double nextGaussian()
|
||||
{
|
||||
return rnd.nextGaussian();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random integer number from Integer.MIN_VALUE(inclusive) to Integer.MAX_VALUE(inclusive)
|
||||
* @return A random integer number from Integer.MIN_VALUE to Integer.MAX_VALUE
|
||||
* @see java.util.Random#nextInt()
|
||||
*/
|
||||
public static int nextInt()
|
||||
{
|
||||
return rnd.nextInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n
|
||||
* @return
|
||||
* @see com.l2jmobius.util.Rnd#get(int n)
|
||||
*/
|
||||
public static int nextInt(int n)
|
||||
{
|
||||
return get(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random long number from Long.MIN_VALUE(inclusive) to Long.MAX_VALUE(inclusive)
|
||||
* @return A random integer number from Long.MIN_VALUE to Long.MAX_VALUE
|
||||
* @see java.util.Random#nextLong()
|
||||
*/
|
||||
public static long nextLong()
|
||||
{
|
||||
return rnd.nextLong();
|
||||
}
|
||||
}
|
276
L2J_Mobius_HighFive/java/com/l2jmobius/util/StringUtil.java
Normal file
276
L2J_Mobius_HighFive/java/com/l2jmobius/util/StringUtil.java
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
|
||||
/**
|
||||
* String utilities optimized for the best performance.<br>
|
||||
* <h1>How to Use It</h1>
|
||||
* <h2>concat() or append()</h2> If concatenating strings<br>
|
||||
* in single call, use StringUtil.concat(), otherwise use StringUtil.append()<br>
|
||||
* and its variants.<br>
|
||||
* <br>
|
||||
* <h2>Minimum Calls</h2><br>
|
||||
* Bad:
|
||||
*
|
||||
* <pre>
|
||||
* final StringBuilder sbString = new StringBuilder();
|
||||
* StringUtil.append(sbString, "text 1", String.valueOf(npcId));
|
||||
* StringUtil.append("text 2");
|
||||
* </pre>
|
||||
*
|
||||
* Good:
|
||||
*
|
||||
* <pre>
|
||||
* final StringBuilder sbString = new StringBuilder();
|
||||
* StringUtil.append(sbString, "text 1", String.valueOf(npcId), "text 2");
|
||||
* </pre>
|
||||
*
|
||||
* Why?<br/>
|
||||
* Because the less calls you do, the less memory re-allocations have to be done<br>
|
||||
* so the whole text fits into the memory and less array copy tasks has to be<br>
|
||||
* performed. So if using less calls, less memory is used and string concatenation is faster.<br>
|
||||
* <br>
|
||||
* <h2>Size Hints for Loops</h2><br>
|
||||
* Bad:
|
||||
*
|
||||
* <pre>
|
||||
* final StringBuilder sbString = new StringBuilder();
|
||||
* StringUtil.append(sbString, "header start", someText, "header end");
|
||||
* for (int i = 0; i < 50; i++)
|
||||
* {
|
||||
* StringUtil.append(sbString, "text 1", stringArray[i], "text 2");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Good:
|
||||
*
|
||||
* <pre>
|
||||
* final StringBuilder sbString = StringUtil.startAppend(1300, "header start", someText, "header end");
|
||||
* for (int i = 0; i < 50; i++)
|
||||
* {
|
||||
* StringUtil.append(sbString, "text 1", stringArray[i], "text 2");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Why?<br/>
|
||||
* When using StringUtil.append(), memory is only allocated to fit in the strings in method argument. So on each loop new memory for the string has to be allocated and old string has to be copied to the new string. With size hint, even if the size hint is above the needed memory, memory is saved
|
||||
* because new memory has not to be allocated on each cycle. Also it is much faster if no string copy tasks has to be performed. So if concatenating strings in a loop, count approximately the size and set it as the hint for the string builder size. It's better to make the size hint little bit larger
|
||||
* rather than smaller.<br/>
|
||||
* In case there is no text appended before the cycle, just use <code>new
|
||||
* StringBuilder(1300)</code>.<br>
|
||||
* <br>
|
||||
* <h2>Concatenation and Constants</h2><br>
|
||||
* Bad:
|
||||
*
|
||||
* <pre>
|
||||
* StringUtil.concat("text 1 ", "text 2", String.valueOf(npcId));
|
||||
* </pre>
|
||||
*
|
||||
* Good:
|
||||
*
|
||||
* <pre>
|
||||
* StringUtil.concat("text 1 " + "text 2", String.valueOf(npcId));
|
||||
* </pre>
|
||||
*
|
||||
* or
|
||||
*
|
||||
* <pre>
|
||||
* StringUtil.concat("text 1 text 2", String.valueOf(npcId));
|
||||
* </pre>
|
||||
*
|
||||
* Why?<br/>
|
||||
* It saves some cycles when determining size of memory that needs to be allocated because less strings are passed to concat() method. But do not use + for concatenation of non-constant strings, that degrades performance and makes extra memory allocations needed.<br>
|
||||
* <h2>Concatenation and Constant Variables</h2> Bad:
|
||||
*
|
||||
* <pre>
|
||||
* String glue = "some glue";
|
||||
* StringUtil.concat("text 1", glue, "text 2", glue, String.valueOf(npcId));
|
||||
* </pre>
|
||||
*
|
||||
* Good:
|
||||
*
|
||||
* <pre>
|
||||
* final String glue = "some glue";
|
||||
* StringUtil.concat("text 1" + glue + "text2" + glue, String.valueOf(npcId));
|
||||
* </pre>
|
||||
*
|
||||
* Why? Because when using <code>final</code> keyword, the <code>glue</code> is marked as constant string and compiler treats it as a constant string so it is able to create string "text1some gluetext2some glue" during the compilation. But this only works in case the value is known at compilation
|
||||
* time, so this cannot be used for cases like <code>final String objectIdString =
|
||||
* String.valueOf(getObjectId)</code>.<br>
|
||||
* <br>
|
||||
* <h2>StringBuilder Reuse</h2><br>
|
||||
* Bad:
|
||||
*
|
||||
* <pre>
|
||||
* final StringBuilder sbString1 = new StringBuilder();
|
||||
* StringUtil.append(sbString1, "text 1", String.valueOf(npcId), "text 2");
|
||||
* ... // output of sbString1, it is no more needed
|
||||
* final StringBuilder sbString2 = new StringBuilder();
|
||||
* StringUtil.append(sbString2, "text 3", String.valueOf(npcId), "text 4");
|
||||
* </pre>
|
||||
*
|
||||
* Good:
|
||||
*
|
||||
* <pre>
|
||||
* final StringBuilder sbString = new StringBuilder();
|
||||
* StringUtil.append(sbString, "text 1", String.valueOf(npcId), "text 2");
|
||||
* ... // output of sbString, it is no more needed
|
||||
* sbString.setLength(0);
|
||||
* StringUtil.append(sbString, "text 3", String.valueOf(npcId), "text 4");
|
||||
* </pre>
|
||||
*
|
||||
* Why?</br>
|
||||
* In first case, new memory has to be allocated for the second string. In second case already allocated memory is reused, but only in case the new string is not longer than the previously allocated string. Anyway, the second way is better because the string either fits in the memory and some memory
|
||||
* is saved, or it does not fit in the memory, and in that case it works as in the first case.
|
||||
* <h2>Primitives to Strings</h2> To convert primitives to string, use String.valueOf().<br>
|
||||
* <br>
|
||||
* <h2>How much faster is it?</h2><br>
|
||||
* Here are some results of my tests. Count is number of strings concatenated. Don't take the numbers as 100% true as the numbers are affected by other programs running on my computer at the same time. Anyway, from the results it is obvious that using StringBuilder with predefined size is the
|
||||
* fastest (and also most memory efficient) solution. It is about 5 times faster when concatenating 7 strings, compared to TextBuilder. Also, with more strings concatenated, the difference between StringBuilder and TextBuilder gets larger. In code, there are many cases, where there are concatenated
|
||||
* 50+ strings so the time saving is even greater.<br>
|
||||
*
|
||||
* <pre>
|
||||
* Count: 2
|
||||
* TextBuilder: 1893
|
||||
* TextBuilder with size: 1703
|
||||
* String: 1033
|
||||
* StringBuilder: 993
|
||||
* StringBuilder with size: 1024
|
||||
* Count: 3
|
||||
* TextBuilder: 1973
|
||||
* TextBuilder with size: 1872
|
||||
* String: 2583
|
||||
* StringBuilder: 1633
|
||||
* StringBuilder with size: 1156
|
||||
* Count: 4
|
||||
* TextBuilder: 2188
|
||||
* TextBuilder with size: 2229
|
||||
* String: 4207
|
||||
* StringBuilder: 1816
|
||||
* StringBuilder with size: 1444
|
||||
* Count: 5
|
||||
* TextBuilder: 9185
|
||||
* TextBuilder with size: 9464
|
||||
* String: 6937
|
||||
* StringBuilder: 2745
|
||||
* StringBuilder with size: 1882
|
||||
* Count: 6
|
||||
* TextBuilder: 9785
|
||||
* TextBuilder with size: 10082
|
||||
* String: 9471
|
||||
* StringBuilder: 2889
|
||||
* StringBuilder with size: 1857
|
||||
* Count: 7
|
||||
* TextBuilder: 10169
|
||||
* TextBuilder with size: 10528
|
||||
* String: 12746
|
||||
* StringBuilder: 3081
|
||||
* StringBuilder with size: 2139
|
||||
* </pre>
|
||||
*
|
||||
* @author fordfrog
|
||||
*/
|
||||
public final class StringUtil
|
||||
{
|
||||
private StringUtil()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates strings.
|
||||
* @param strings strings to be concatenated
|
||||
* @return concatenated string
|
||||
*/
|
||||
public static String concat(String... strings)
|
||||
{
|
||||
final StringBuilder sbString = new StringBuilder();
|
||||
for (String string : strings)
|
||||
{
|
||||
sbString.append(string);
|
||||
}
|
||||
return sbString.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new string builder with size initializated to <code>sizeHint</code>, unless total length of strings is greater than <code>sizeHint</code>.
|
||||
* @param sizeHint hint for string builder size allocation
|
||||
* @param strings strings to be appended
|
||||
* @return created string builder
|
||||
*/
|
||||
public static StringBuilder startAppend(int sizeHint, String... strings)
|
||||
{
|
||||
final int length = getLength(strings);
|
||||
final StringBuilder sbString = new StringBuilder(sizeHint > length ? sizeHint : length);
|
||||
for (String string : strings)
|
||||
{
|
||||
sbString.append(string);
|
||||
}
|
||||
return sbString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends strings to existing string builder.
|
||||
* @param sbString string builder
|
||||
* @param strings strings to be appended
|
||||
*/
|
||||
public static void append(StringBuilder sbString, String... strings)
|
||||
{
|
||||
sbString.ensureCapacity(sbString.length() + getLength(strings));
|
||||
|
||||
for (String string : strings)
|
||||
{
|
||||
sbString.append(string);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getLength(Iterable<String> strings)
|
||||
{
|
||||
int length = 0;
|
||||
for (String string : strings)
|
||||
{
|
||||
length += (string == null) ? 4 : string.length();
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts total length of all the strings.
|
||||
* @param strings array of strings
|
||||
* @return total length of all the strings
|
||||
*/
|
||||
public static int getLength(String[] strings)
|
||||
{
|
||||
int length = 0;
|
||||
for (String string : strings)
|
||||
{
|
||||
length += (string == null) ? 4 : string.length();
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public static String getTraceString(StackTraceElement[] trace)
|
||||
{
|
||||
final StringBuilder sbString = new StringBuilder();
|
||||
for (StackTraceElement element : trace)
|
||||
{
|
||||
sbString.append(element.toString()).append(Config.EOL);
|
||||
}
|
||||
return sbString.toString();
|
||||
}
|
||||
}
|
224
L2J_Mobius_HighFive/java/com/l2jmobius/util/Util.java
Normal file
224
L2J_Mobius_HighFive/java/com/l2jmobius/util/Util.java
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Useful utilities common to L2J Server.
|
||||
*/
|
||||
public final class Util
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(Util.class.getName());
|
||||
|
||||
private static final char[] ILLEGAL_CHARACTERS =
|
||||
{
|
||||
'/',
|
||||
'\n',
|
||||
'\r',
|
||||
'\t',
|
||||
'\0',
|
||||
'\f',
|
||||
'`',
|
||||
'?',
|
||||
'*',
|
||||
'\\',
|
||||
'<',
|
||||
'>',
|
||||
'|',
|
||||
'\"',
|
||||
':'
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a host name is internal
|
||||
* @param host the host name to check
|
||||
* @return true: host name is internal<br>
|
||||
* false: host name is external
|
||||
*/
|
||||
public static boolean isInternalHostname(String host)
|
||||
{
|
||||
try
|
||||
{
|
||||
final InetAddress addr = InetAddress.getByName(host);
|
||||
return addr.isSiteLocalAddress() || addr.isLoopbackAddress();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
_log.warning("Util: " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate the hexadecimal representation of a byte array.<br>
|
||||
* 16 bytes per row, while ascii chars or "." is shown at the end of the line.
|
||||
* @param data the byte array to be represented in hexadecimal representation
|
||||
* @param len the number of bytes to represent in hexadecimal representation
|
||||
* @return byte array represented in hexadecimal format
|
||||
*/
|
||||
public static String printData(byte[] data, int len)
|
||||
{
|
||||
return new String(HexUtils.bArr2HexEdChars(data, len));
|
||||
}
|
||||
|
||||
/**
|
||||
* This call is equivalent to Util.printData(data, data.length)
|
||||
* @see Util#printData(byte[],int)
|
||||
* @param data data to represent in hexadecimal
|
||||
* @return byte array represented in hexadecimal format
|
||||
*/
|
||||
public static String printData(byte[] data)
|
||||
{
|
||||
return printData(data, data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to represent the remaining bytes of a ByteBuffer as hexadecimal
|
||||
* @param buf ByteBuffer to represent the remaining bytes of as hexadecimal
|
||||
* @return hexadecimal representation of remaining bytes of the ByteBuffer
|
||||
*/
|
||||
public static String printData(ByteBuffer buf)
|
||||
{
|
||||
final byte[] data = new byte[buf.remaining()];
|
||||
buf.get(data);
|
||||
final String hex = Util.printData(data, data.length);
|
||||
buf.position(buf.position() - data.length);
|
||||
return hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate a random sequence of bytes returned as byte array
|
||||
* @param size number of random bytes to generate
|
||||
* @return byte array with sequence of random bytes
|
||||
*/
|
||||
public static byte[] generateHex(int size)
|
||||
{
|
||||
final byte[] array = new byte[size];
|
||||
Rnd.nextBytes(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the stack trace of a Throwable into a String
|
||||
* @param t Throwable to get the stacktrace from
|
||||
* @return stack trace from Throwable as String
|
||||
*/
|
||||
public static String getStackTrace(Throwable t)
|
||||
{
|
||||
final StringWriter sw = new StringWriter();
|
||||
t.printStackTrace(new PrintWriter(sw));
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces most invalid characters for the given string with an underscore.
|
||||
* @param str the string that may contain invalid characters
|
||||
* @return the string with invalid character replaced by underscores
|
||||
*/
|
||||
public static String replaceIllegalCharacters(String str)
|
||||
{
|
||||
String valid = str;
|
||||
for (char c : ILLEGAL_CHARACTERS)
|
||||
{
|
||||
valid = valid.replace(c, '_');
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if a file name is valid.
|
||||
* @param name the name of the file
|
||||
* @return {@code true} if the file name is valid, {@code false} otherwise
|
||||
*/
|
||||
public static boolean isValidFileName(String name)
|
||||
{
|
||||
final File f = new File(name);
|
||||
try
|
||||
{
|
||||
f.getCanonicalPath();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split words with a space.
|
||||
* @param input the string to split
|
||||
* @return the split string
|
||||
*/
|
||||
public static String splitWords(String input)
|
||||
{
|
||||
return input.replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next or same closest date from the specified days in {@code daysOfWeek Array} at specified {@code hour} and {@code min}.
|
||||
* @param daysOfWeek the days of week
|
||||
* @param hour the hour
|
||||
* @param min the min
|
||||
* @return the next or same date from the days of week at specified time
|
||||
* @throws IllegalArgumentException if the {@code daysOfWeek Array} is empty.
|
||||
*/
|
||||
public static LocalDateTime getNextClosestDateTime(DayOfWeek[] daysOfWeek, int hour, int min) throws IllegalArgumentException
|
||||
{
|
||||
return getNextClosestDateTime(Arrays.asList(daysOfWeek), hour, min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next or same closest date from the specified days in {@code daysOfWeek List} at specified {@code hour} and {@code min}.
|
||||
* @param daysOfWeek the days of week
|
||||
* @param hour the hour
|
||||
* @param min the min
|
||||
* @return the next or same date from the days of week at specified time
|
||||
* @throws IllegalArgumentException if the {@code daysOfWeek List} is empty.
|
||||
*/
|
||||
public static LocalDateTime getNextClosestDateTime(List<DayOfWeek> daysOfWeek, int hour, int min) throws IllegalArgumentException
|
||||
{
|
||||
if (daysOfWeek.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("daysOfWeek should not be empty.");
|
||||
}
|
||||
|
||||
final LocalDateTime dateNow = LocalDateTime.now();
|
||||
final LocalDateTime dateNowWithDifferentTime = dateNow.withHour(hour).withMinute(min).withSecond(0);
|
||||
|
||||
// @formatter:off
|
||||
return daysOfWeek.stream()
|
||||
.map(d -> dateNowWithDifferentTime.with(TemporalAdjusters.nextOrSame(d)))
|
||||
.filter(d -> d.isAfter(dateNow))
|
||||
.min(Comparator.naturalOrder())
|
||||
.orElse(dateNowWithDifferentTime.with(TemporalAdjusters.next(daysOfWeek.get(0))));
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.crypt;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
/**
|
||||
* @author KenM
|
||||
*/
|
||||
public class LoginCrypt
|
||||
{
|
||||
private static final byte[] STATIC_BLOWFISH_KEY =
|
||||
{
|
||||
(byte) 0x6b,
|
||||
(byte) 0x60,
|
||||
(byte) 0xcb,
|
||||
(byte) 0x5b,
|
||||
(byte) 0x82,
|
||||
(byte) 0xce,
|
||||
(byte) 0x90,
|
||||
(byte) 0xb1,
|
||||
(byte) 0xcc,
|
||||
(byte) 0x2b,
|
||||
(byte) 0x6c,
|
||||
(byte) 0x55,
|
||||
(byte) 0x6c,
|
||||
(byte) 0x6c,
|
||||
(byte) 0x6c,
|
||||
(byte) 0x6c
|
||||
};
|
||||
|
||||
private static final NewCrypt _STATIC_CRYPT = new NewCrypt(STATIC_BLOWFISH_KEY);
|
||||
private NewCrypt _crypt = null;
|
||||
private boolean _static = true;
|
||||
|
||||
/**
|
||||
* Method to initialize the the blowfish cipher with dynamic key.
|
||||
* @param key the blowfish key to initialize the dynamic blowfish cipher with
|
||||
*/
|
||||
public void setKey(byte[] key)
|
||||
{
|
||||
_crypt = new NewCrypt(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to decrypt an incoming login client packet.
|
||||
* @param raw array with encrypted data
|
||||
* @param offset offset where the encrypted data is located
|
||||
* @param size number of bytes of encrypted data
|
||||
* @return true when checksum could be verified, false otherwise
|
||||
* @throws IOException the size is not multiple of blowfishs block size or the raw array can't hold size bytes starting at offset due to it's size
|
||||
*/
|
||||
public boolean decrypt(byte[] raw, int offset, int size) throws IOException
|
||||
{
|
||||
if ((size % 8) != 0)
|
||||
{
|
||||
throw new IOException("size have to be multiple of 8");
|
||||
}
|
||||
if ((offset + size) > raw.length)
|
||||
{
|
||||
throw new IOException("raw array too short for size starting from offset");
|
||||
}
|
||||
|
||||
_crypt.decrypt(raw, offset, size);
|
||||
return NewCrypt.verifyChecksum(raw, offset, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to encrypt an outgoing packet to login client.<br>
|
||||
* Performs padding and resizing of data array.
|
||||
* @param raw array with plain data
|
||||
* @param offset offset where the plain data is located
|
||||
* @param size number of bytes of plain data
|
||||
* @return the new array size
|
||||
* @throws IOException packet is too long to make padding and add verification data
|
||||
*/
|
||||
public int encrypt(byte[] raw, int offset, int size) throws IOException
|
||||
{
|
||||
// reserve checksum
|
||||
size += 4;
|
||||
|
||||
if (_static)
|
||||
{
|
||||
// reserve for XOR "key"
|
||||
size += 4;
|
||||
|
||||
// padding
|
||||
size += 8 - (size % 8);
|
||||
if ((offset + size) > raw.length)
|
||||
{
|
||||
throw new IOException("packet too long");
|
||||
}
|
||||
NewCrypt.encXORPass(raw, offset, size, Rnd.nextInt());
|
||||
_STATIC_CRYPT.crypt(raw, offset, size);
|
||||
_static = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// padding
|
||||
size += 8 - (size % 8);
|
||||
if ((offset + size) > raw.length)
|
||||
{
|
||||
throw new IOException("packet too long");
|
||||
}
|
||||
NewCrypt.appendChecksum(raw, offset, size);
|
||||
_crypt.crypt(raw, offset, size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
218
L2J_Mobius_HighFive/java/com/l2jmobius/util/crypt/NewCrypt.java
Normal file
218
L2J_Mobius_HighFive/java/com/l2jmobius/util/crypt/NewCrypt.java
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.crypt;
|
||||
|
||||
/**
|
||||
* Class to use a blowfish cipher with ECB processing.<br>
|
||||
* Static methods are present to append/check the checksum of<br>
|
||||
* packets exchanged between the following partners:<br>
|
||||
* Login Server <-> Game Client<br>
|
||||
* Login Server <-> Game Server<br>
|
||||
* Also a static method is provided for the initial xor encryption between Login Server <-> Game Client.
|
||||
*/
|
||||
public final class NewCrypt
|
||||
{
|
||||
private final BlowfishEngine _cipher;
|
||||
|
||||
/**
|
||||
* @param blowfishKey
|
||||
*/
|
||||
public NewCrypt(byte[] blowfishKey)
|
||||
{
|
||||
_cipher = new BlowfishEngine();
|
||||
_cipher.init(blowfishKey);
|
||||
}
|
||||
|
||||
public NewCrypt(String key)
|
||||
{
|
||||
this(key.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to calling {@link #verifyChecksum(byte[], int, int)} with parameters (raw, 0, raw.length)
|
||||
* @param raw data array to be verified
|
||||
* @return true when the checksum of the data is valid, false otherwise
|
||||
*/
|
||||
public static boolean verifyChecksum(byte[] raw)
|
||||
{
|
||||
return NewCrypt.verifyChecksum(raw, 0, raw.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to verify the checksum of a packet received by login server from game client.<br>
|
||||
* This is also used for game server <-> login server communication.
|
||||
* @param raw data array to be verified
|
||||
* @param offset at which offset to start verifying
|
||||
* @param size number of bytes to verify
|
||||
* @return true if the checksum of the data is valid, false otherwise
|
||||
*/
|
||||
public static boolean verifyChecksum(byte[] raw, int offset, int size)
|
||||
{
|
||||
// check if size is multiple of 4 and if there is more then only the checksum
|
||||
if (((size & 3) != 0) || (size <= 4))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
long chksum = 0;
|
||||
final int count = size - 4;
|
||||
long check = -1;
|
||||
int i;
|
||||
|
||||
for (i = offset; i < count; i += 4)
|
||||
{
|
||||
check = raw[i] & 0xff;
|
||||
check |= (raw[i + 1] << 8) & 0xff00;
|
||||
check |= (raw[i + 2] << 0x10) & 0xff0000;
|
||||
check |= (raw[i + 3] << 0x18) & 0xff000000;
|
||||
|
||||
chksum ^= check;
|
||||
}
|
||||
|
||||
check = raw[i] & 0xff;
|
||||
check |= (raw[i + 1] << 8) & 0xff00;
|
||||
check |= (raw[i + 2] << 0x10) & 0xff0000;
|
||||
check |= (raw[i + 3] << 0x18) & 0xff000000;
|
||||
|
||||
return check == chksum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to calling {@link #appendChecksum(byte[], int, int)} with parameters (raw, 0, raw.length)
|
||||
* @param raw data array to compute the checksum from
|
||||
*/
|
||||
public static void appendChecksum(byte[] raw)
|
||||
{
|
||||
NewCrypt.appendChecksum(raw, 0, raw.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to append packet checksum at the end of the packet.
|
||||
* @param raw data array to compute the checksum from
|
||||
* @param offset offset where to start in the data array
|
||||
* @param size number of bytes to compute the checksum from
|
||||
*/
|
||||
public static void appendChecksum(byte[] raw, int offset, int size)
|
||||
{
|
||||
long chksum = 0;
|
||||
final int count = size - 4;
|
||||
long ecx;
|
||||
int i;
|
||||
|
||||
for (i = offset; i < count; i += 4)
|
||||
{
|
||||
ecx = raw[i] & 0xff;
|
||||
ecx |= (raw[i + 1] << 8) & 0xff00;
|
||||
ecx |= (raw[i + 2] << 0x10) & 0xff0000;
|
||||
ecx |= (raw[i + 3] << 0x18) & 0xff000000;
|
||||
|
||||
chksum ^= ecx;
|
||||
}
|
||||
|
||||
ecx = raw[i] & 0xff;
|
||||
ecx |= (raw[i + 1] << 8) & 0xff00;
|
||||
ecx |= (raw[i + 2] << 0x10) & 0xff0000;
|
||||
ecx |= (raw[i + 3] << 0x18) & 0xff000000;
|
||||
|
||||
raw[i] = (byte) (chksum & 0xff);
|
||||
raw[i + 1] = (byte) ((chksum >> 0x08) & 0xff);
|
||||
raw[i + 2] = (byte) ((chksum >> 0x10) & 0xff);
|
||||
raw[i + 3] = (byte) ((chksum >> 0x18) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet is first XOR encoded with <code>key</code> then, the last 4 bytes are overwritten with the the XOR "key".<br>
|
||||
* Thus this assume that there is enough room for the key to fit without overwriting data.
|
||||
* @param raw The raw bytes to be encrypted
|
||||
* @param key The 4 bytes (int) XOR key
|
||||
*/
|
||||
public static void encXORPass(byte[] raw, int key)
|
||||
{
|
||||
NewCrypt.encXORPass(raw, 0, raw.length, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet is first XOR encoded with <code>key</code> then, the last 4 bytes are overwritten with the the XOR "key".<br>
|
||||
* Thus this assume that there is enough room for the key to fit without overwriting data.
|
||||
* @param raw The raw bytes to be encrypted
|
||||
* @param offset The beginning of the data to be encrypted
|
||||
* @param size Length of the data to be encrypted
|
||||
* @param key The 4 bytes (int) XOR key
|
||||
*/
|
||||
static void encXORPass(byte[] raw, int offset, int size, int key)
|
||||
{
|
||||
final int stop = size - 8;
|
||||
int pos = 4 + offset;
|
||||
int edx;
|
||||
int ecx = key; // Initial xor key
|
||||
|
||||
while (pos < stop)
|
||||
{
|
||||
edx = raw[pos] & 0xFF;
|
||||
edx |= (raw[pos + 1] & 0xFF) << 8;
|
||||
edx |= (raw[pos + 2] & 0xFF) << 16;
|
||||
edx |= (raw[pos + 3] & 0xFF) << 24;
|
||||
|
||||
ecx += edx;
|
||||
|
||||
edx ^= ecx;
|
||||
|
||||
raw[pos++] = (byte) (edx & 0xFF);
|
||||
raw[pos++] = (byte) ((edx >> 8) & 0xFF);
|
||||
raw[pos++] = (byte) ((edx >> 16) & 0xFF);
|
||||
raw[pos++] = (byte) ((edx >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
raw[pos++] = (byte) (ecx & 0xFF);
|
||||
raw[pos++] = (byte) ((ecx >> 8) & 0xFF);
|
||||
raw[pos++] = (byte) ((ecx >> 16) & 0xFF);
|
||||
raw[pos++] = (byte) ((ecx >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to decrypt using Blowfish-Blockcipher in ECB mode.<br>
|
||||
* The results will be directly placed inside {@code raw} array.<br>
|
||||
* This method does not do any error checking, since the calling code<br>
|
||||
* should ensure sizes.
|
||||
* @param raw the data array to be decrypted
|
||||
* @param offset the offset at which to start decrypting
|
||||
* @param size the number of bytes to be decrypted
|
||||
*/
|
||||
public void decrypt(byte[] raw, int offset, int size)
|
||||
{
|
||||
for (int i = offset; i < (offset + size); i += 8)
|
||||
{
|
||||
_cipher.decryptBlock(raw, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to encrypt using Blowfish-Blockcipher in ECB mode.<br>
|
||||
* The results will be directly placed inside {@code raw} array.<br>
|
||||
* This method does not do any error checking, since the calling code should ensure sizes.
|
||||
* @param raw the data array to be decrypted
|
||||
* @param offset the offset at which to start decrypting
|
||||
* @param size the number of bytes to be decrypted
|
||||
*/
|
||||
public void crypt(byte[] raw, int offset, int size)
|
||||
{
|
||||
for (int i = offset; i < (offset + size); i += 8)
|
||||
{
|
||||
_cipher.encryptBlock(raw, i);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.crypt;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyPair;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ScrambledKeyPair
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(ScrambledKeyPair.class.getName());
|
||||
public KeyPair _pair;
|
||||
public byte[] _scrambledModulus;
|
||||
|
||||
public ScrambledKeyPair(KeyPair pPair)
|
||||
{
|
||||
_pair = pPair;
|
||||
_scrambledModulus = scrambleModulus(((RSAPublicKey) _pair.getPublic()).getModulus());
|
||||
}
|
||||
|
||||
private byte[] scrambleModulus(BigInteger modulus)
|
||||
{
|
||||
byte[] scrambledMod = modulus.toByteArray();
|
||||
|
||||
if ((scrambledMod.length == 0x81) && (scrambledMod[0] == 0x00))
|
||||
{
|
||||
final byte[] temp = new byte[0x80];
|
||||
System.arraycopy(scrambledMod, 1, temp, 0, 0x80);
|
||||
scrambledMod = temp;
|
||||
}
|
||||
// step 1 : 0x4d-0x50 <-> 0x00-0x04
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
final byte temp = scrambledMod[0x00 + i];
|
||||
scrambledMod[0x00 + i] = scrambledMod[0x4d + i];
|
||||
scrambledMod[0x4d + i] = temp;
|
||||
}
|
||||
// step 2 : xor first 0x40 bytes with last 0x40 bytes
|
||||
for (int i = 0; i < 0x40; i++)
|
||||
{
|
||||
scrambledMod[i] = (byte) (scrambledMod[i] ^ scrambledMod[0x40 + i]);
|
||||
}
|
||||
// step 3 : xor bytes 0x0d-0x10 with bytes 0x34-0x38
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
scrambledMod[0x0d + i] = (byte) (scrambledMod[0x0d + i] ^ scrambledMod[0x34 + i]);
|
||||
}
|
||||
// step 4 : xor last 0x40 bytes with first 0x40 bytes
|
||||
for (int i = 0; i < 0x40; i++)
|
||||
{
|
||||
scrambledMod[0x40 + i] = (byte) (scrambledMod[0x40 + i] ^ scrambledMod[i]);
|
||||
}
|
||||
_log.fine("Modulus was scrambled");
|
||||
|
||||
return scrambledMod;
|
||||
}
|
||||
}
|
@ -0,0 +1,665 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.data.xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.util.file.filter.XMLFilter;
|
||||
|
||||
/**
|
||||
* Interface for XML parsers.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public interface IXmlReader
|
||||
{
|
||||
Logger LOGGER = Logger.getLogger(IXmlReader.class.getName());
|
||||
String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
|
||||
String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
|
||||
/** The default file filter, ".xml" files only. */
|
||||
XMLFilter XML_FILTER = new XMLFilter();
|
||||
|
||||
/**
|
||||
* This method can be used to load/reload the data.<br>
|
||||
* It's highly recommended to clear the data storage, either the list or map.
|
||||
*/
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Wrapper for {@link #parseFile(File)} method.
|
||||
* @param path the relative path to the datapack root of the XML file to parse.
|
||||
*/
|
||||
default void parseDatapackFile(String path)
|
||||
{
|
||||
parseFile(new File(Config.DATAPACK_ROOT, path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a single XML file.<br>
|
||||
* If the file was successfully parsed, call {@link #parseDocument(Document, File)} for the parsed document.<br>
|
||||
* <b>Validation is enforced.</b>
|
||||
* @param f the XML file to parse.
|
||||
*/
|
||||
default void parseFile(File f)
|
||||
{
|
||||
if (!getCurrentFileFilter().accept(f))
|
||||
{
|
||||
LOGGER.warning(getClass().getSimpleName() + ": Could not parse " + f.getName() + " is not a file or it doesn't exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setValidating(true);
|
||||
dbf.setIgnoringComments(true);
|
||||
try
|
||||
{
|
||||
dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
|
||||
final DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(new XMLErrorHandler());
|
||||
parseDocument(db.parse(f), f);
|
||||
}
|
||||
catch (SAXParseException e)
|
||||
{
|
||||
LOGGER.warning(getClass().getSimpleName() + ": Could not parse file " + f.getName() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber() + ": " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warning(getClass().getSimpleName() + ": Could not parse file " + f.getName() + ": " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for {@link #parseDirectory(File, boolean)}.
|
||||
* @param file the path to the directory where the XML files are.
|
||||
* @return {@code false} if it fails to find the directory, {@code true} otherwise.
|
||||
*/
|
||||
default boolean parseDirectory(File file)
|
||||
{
|
||||
return parseDirectory(file, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for {@link #parseDirectory(File, boolean)}.
|
||||
* @param path the path to the directory where the XML files are.
|
||||
* @return {@code false} if it fails to find the directory, {@code true} otherwise.
|
||||
*/
|
||||
default boolean parseDirectory(String path)
|
||||
{
|
||||
return parseDirectory(new File(path), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for {@link #parseDirectory(File, boolean)}.
|
||||
* @param path the path to the directory where the XML files are.
|
||||
* @param recursive parses all sub folders if there is.
|
||||
* @return {@code false} if it fails to find the directory, {@code true} otherwise.
|
||||
*/
|
||||
default boolean parseDirectory(String path, boolean recursive)
|
||||
{
|
||||
return parseDirectory(new File(path), recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all XML files from {@code path} and calls {@link #parseFile(File)} for each one of them.
|
||||
* @param dir the directory object to scan.
|
||||
* @param recursive parses all sub folders if there is.
|
||||
* @return {@code false} if it fails to find the directory, {@code true} otherwise.
|
||||
*/
|
||||
default boolean parseDirectory(File dir, boolean recursive)
|
||||
{
|
||||
if (!dir.exists())
|
||||
{
|
||||
LOGGER.warning(getClass().getSimpleName() + ": Folder " + dir.getAbsolutePath() + " doesn't exist!");
|
||||
return false;
|
||||
}
|
||||
|
||||
final File[] files = dir.listFiles();
|
||||
if (files != null)
|
||||
{
|
||||
for (File f : files)
|
||||
{
|
||||
if (recursive && f.isDirectory())
|
||||
{
|
||||
parseDirectory(f, recursive);
|
||||
}
|
||||
else if (getCurrentFileFilter().accept(f))
|
||||
{
|
||||
parseFile(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for {@link #parseDirectory(File, boolean)}.
|
||||
* @param path the path to the directory where the XML files are
|
||||
* @param recursive parses all sub folders if there is
|
||||
* @return {@code false} if it fails to find the directory, {@code true} otherwise
|
||||
*/
|
||||
default boolean parseDatapackDirectory(String path, boolean recursive)
|
||||
{
|
||||
return parseDirectory(new File(Config.DATAPACK_ROOT, path), recursive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method that when implemented will parse the current document.<br>
|
||||
* Is expected to be call from {@link #parseFile(File)}.
|
||||
* @param doc the current document to parse
|
||||
* @param f the current file
|
||||
*/
|
||||
default void parseDocument(Document doc, File f)
|
||||
{
|
||||
parseDocument(doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method that when implemented will parse the current document.<br>
|
||||
* Is expected to be call from {@link #parseFile(File)}.
|
||||
* @param doc the current document to parse
|
||||
*/
|
||||
default void parseDocument(Document doc)
|
||||
{
|
||||
LOGGER.severe("Parser not implemented!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a boolean value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Boolean parseBoolean(Node node, Boolean defaultValue)
|
||||
{
|
||||
return node != null ? Boolean.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a boolean value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Boolean parseBoolean(Node node)
|
||||
{
|
||||
return parseBoolean(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a boolean value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Boolean parseBoolean(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseBoolean(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a boolean value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Boolean parseBoolean(NamedNodeMap attrs, String name, Boolean defaultValue)
|
||||
{
|
||||
return parseBoolean(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a byte value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Byte parseByte(Node node, Byte defaultValue)
|
||||
{
|
||||
return node != null ? Byte.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a byte value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Byte parseByte(Node node)
|
||||
{
|
||||
return parseByte(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a byte value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Byte parseByte(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseByte(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a byte value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Byte parseByte(NamedNodeMap attrs, String name, Byte defaultValue)
|
||||
{
|
||||
return parseByte(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Short parseShort(Node node, Short defaultValue)
|
||||
{
|
||||
return node != null ? Short.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Short parseShort(Node node)
|
||||
{
|
||||
return parseShort(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Short parseShort(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseShort(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Short parseShort(NamedNodeMap attrs, String name, Short defaultValue)
|
||||
{
|
||||
return parseShort(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an int value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default int parseInt(Node node, Integer defaultValue)
|
||||
{
|
||||
return node != null ? Integer.parseInt(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an int value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default int parseInt(Node node)
|
||||
{
|
||||
return parseInt(node, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an integer value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Integer parseInteger(Node node, Integer defaultValue)
|
||||
{
|
||||
return node != null ? Integer.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an integer value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Integer parseInteger(Node node)
|
||||
{
|
||||
return parseInteger(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an integer value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Integer parseInteger(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseInteger(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an integer value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Integer parseInteger(NamedNodeMap attrs, String name, Integer defaultValue)
|
||||
{
|
||||
return parseInteger(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a long value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Long parseLong(Node node, Long defaultValue)
|
||||
{
|
||||
return node != null ? Long.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a long value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Long parseLong(Node node)
|
||||
{
|
||||
return parseLong(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a long value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Long parseLong(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseLong(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a long value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Long parseLong(NamedNodeMap attrs, String name, Long defaultValue)
|
||||
{
|
||||
return parseLong(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a float value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Float parseFloat(Node node, Float defaultValue)
|
||||
{
|
||||
return node != null ? Float.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a float value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Float parseFloat(Node node)
|
||||
{
|
||||
return parseFloat(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a float value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Float parseFloat(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseFloat(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a float value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Float parseFloat(NamedNodeMap attrs, String name, Float defaultValue)
|
||||
{
|
||||
return parseFloat(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a double value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Double parseDouble(Node node, Double defaultValue)
|
||||
{
|
||||
return node != null ? Double.valueOf(node.getNodeValue()) : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a double value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Double parseDouble(Node node)
|
||||
{
|
||||
return parseDouble(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a double value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default Double parseDouble(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseDouble(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a double value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default Double parseDouble(NamedNodeMap attrs, String name, Double defaultValue)
|
||||
{
|
||||
return parseDouble(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string value.
|
||||
* @param node the node to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default String parseString(Node node, String defaultValue)
|
||||
{
|
||||
return node != null ? node.getNodeValue() : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string value.
|
||||
* @param node the node to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default String parseString(Node node)
|
||||
{
|
||||
return parseString(node, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null, the value of the parsed node, otherwise null
|
||||
*/
|
||||
default String parseString(NamedNodeMap attrs, String name)
|
||||
{
|
||||
return parseString(attrs.getNamedItem(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string value.
|
||||
* @param attrs the attributes
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null, the value of the parsed node, otherwise the default value
|
||||
*/
|
||||
default String parseString(NamedNodeMap attrs, String name, String defaultValue)
|
||||
{
|
||||
return parseString(attrs.getNamedItem(name), defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an enumerated value.
|
||||
* @param <T> the enumerated type
|
||||
* @param node the node to parse
|
||||
* @param clazz the class of the enumerated
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null and the node value is valid the parsed value, otherwise the default value
|
||||
*/
|
||||
default <T extends Enum<T>> T parseEnum(Node node, Class<T> clazz, T defaultValue)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Enum.valueOf(clazz, node.getNodeValue());
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
LOGGER.warning("Invalid value specified for node: " + node.getNodeName() + " specified value: " + node.getNodeValue() + " should be enum value of \"" + clazz.getSimpleName() + "\" using default value: " + defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an enumerated value.
|
||||
* @param <T> the enumerated type
|
||||
* @param node the node to parse
|
||||
* @param clazz the class of the enumerated
|
||||
* @return if the node is not null and the node value is valid the parsed value, otherwise null
|
||||
*/
|
||||
default <T extends Enum<T>> T parseEnum(Node node, Class<T> clazz)
|
||||
{
|
||||
return parseEnum(node, clazz, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an enumerated value.
|
||||
* @param <T> the enumerated type
|
||||
* @param attrs the attributes
|
||||
* @param clazz the class of the enumerated
|
||||
* @param name the name of the attribute to parse
|
||||
* @return if the node is not null and the node value is valid the parsed value, otherwise null
|
||||
*/
|
||||
default <T extends Enum<T>> T parseEnum(NamedNodeMap attrs, Class<T> clazz, String name)
|
||||
{
|
||||
return parseEnum(attrs.getNamedItem(name), clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an enumerated value.
|
||||
* @param <T> the enumerated type
|
||||
* @param attrs the attributes
|
||||
* @param clazz the class of the enumerated
|
||||
* @param name the name of the attribute to parse
|
||||
* @param defaultValue the default value
|
||||
* @return if the node is not null and the node value is valid the parsed value, otherwise the default value
|
||||
*/
|
||||
default <T extends Enum<T>> T parseEnum(NamedNodeMap attrs, Class<T> clazz, String name, T defaultValue)
|
||||
{
|
||||
return parseEnum(attrs.getNamedItem(name), clazz, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current file filter.
|
||||
* @return the current file filter
|
||||
*/
|
||||
default FileFilter getCurrentFileFilter()
|
||||
{
|
||||
return XML_FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple XML error handler.
|
||||
* @author Zoey76
|
||||
*/
|
||||
static class XMLErrorHandler implements ErrorHandler
|
||||
{
|
||||
@Override
|
||||
public void warning(SAXParseException e) throws SAXParseException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(SAXParseException e) throws SAXParseException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException e) throws SAXParseException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.file.filter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* @author lasarus
|
||||
*/
|
||||
public class ExtFilter implements FileFilter
|
||||
{
|
||||
private final String _ext;
|
||||
|
||||
public ExtFilter(String ext)
|
||||
{
|
||||
_ext = ext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
return f.getName().toLowerCase().endsWith(_ext);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.file.filter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Specialized {@link FileFilter} class.<br>
|
||||
* Accepts <b>files</b> ending with ".htm" and ".html" only.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public class HTMLFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
if ((f == null) || !f.isFile())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final String name = f.getName().toLowerCase();
|
||||
return name.endsWith(".htm") || name.endsWith(".html");
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.file.filter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Specialized {@link FileFilter} class.<br>
|
||||
* Accepts <b>files</b> matching "numbers".xml only.
|
||||
* @author UnAfraid
|
||||
*/
|
||||
public class NumericNameFilter extends XMLFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
return super.accept(f) && f.getName().matches("\\d+\\.xml");
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.file.filter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Specialized {@link FileFilter} class.<br>
|
||||
* Accepts <b>files</b> starting with "Pledge_" only.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public class OldPledgeFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
return (f != null) && f.isFile() && f.getName().startsWith("Pledge_");
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.file.filter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Specialized {@link FileFilter} class.<br>
|
||||
* Accepts <b>files</b> ending with ".sql" only.
|
||||
* @author Zoey76
|
||||
*/
|
||||
public class SQLFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
return (f != null) && f.isFile() && f.getName().toLowerCase().endsWith(".sql");
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.file.filter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Specialized {@link FileFilter} class.<br>
|
||||
* Accepts files ending with ".xml" only.
|
||||
* @author mrTJO
|
||||
*/
|
||||
public class XMLFilter implements FileFilter
|
||||
{
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
return (f != null) && f.isFile() && f.getName().toLowerCase().endsWith(".xml");
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.network;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:12 $
|
||||
*/
|
||||
public abstract class BaseRecievePacket
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(BaseRecievePacket.class.getName());
|
||||
|
||||
private final byte[] _decrypt;
|
||||
private int _off;
|
||||
|
||||
public BaseRecievePacket(byte[] decrypt)
|
||||
{
|
||||
_decrypt = decrypt;
|
||||
_off = 1; // skip packet type id
|
||||
}
|
||||
|
||||
public int readD()
|
||||
{
|
||||
int result = _decrypt[_off++] & 0xff;
|
||||
result |= (_decrypt[_off++] << 8) & 0xff00;
|
||||
result |= (_decrypt[_off++] << 0x10) & 0xff0000;
|
||||
result |= (_decrypt[_off++] << 0x18) & 0xff000000;
|
||||
return result;
|
||||
}
|
||||
|
||||
public int readC()
|
||||
{
|
||||
return _decrypt[_off++] & 0xff;
|
||||
}
|
||||
|
||||
public int readH()
|
||||
{
|
||||
return (_decrypt[_off++] & 0xff) | ((_decrypt[_off++] << 8) & 0xff00);
|
||||
}
|
||||
|
||||
public double readF()
|
||||
{
|
||||
long result = _decrypt[_off++] & 0xff;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 8L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 16L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 24L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 32L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 40L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 48L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 56L;
|
||||
return Double.longBitsToDouble(result);
|
||||
}
|
||||
|
||||
public String readS()
|
||||
{
|
||||
String result = null;
|
||||
try
|
||||
{
|
||||
result = new String(_decrypt, _off, _decrypt.length - _off, "UTF-16LE");
|
||||
result = result.substring(0, result.indexOf(0x00));
|
||||
_off += (result.length() * 2) + 2;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public final byte[] readB(int length)
|
||||
{
|
||||
final byte[] result = new byte[length];
|
||||
System.arraycopy(_decrypt, _off, result, 0, length);
|
||||
_off += length;
|
||||
return result;
|
||||
}
|
||||
|
||||
public long readQ()
|
||||
{
|
||||
long result = _decrypt[_off++] & 0xff;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 8L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 16L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 24L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 32L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 40L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 48L;
|
||||
result |= (_decrypt[_off++] & 0xffL) << 56L;
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.util.network;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:11 $
|
||||
*/
|
||||
public abstract class BaseSendablePacket
|
||||
{
|
||||
private static final Logger _log = Logger.getLogger(BaseSendablePacket.class.getName());
|
||||
|
||||
private final ByteArrayOutputStream _bao;
|
||||
|
||||
protected BaseSendablePacket()
|
||||
{
|
||||
_bao = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
protected void writeD(int value)
|
||||
{
|
||||
_bao.write(value & 0xff);
|
||||
_bao.write((value >> 8) & 0xff);
|
||||
_bao.write((value >> 16) & 0xff);
|
||||
_bao.write((value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
protected void writeH(int value)
|
||||
{
|
||||
_bao.write(value & 0xff);
|
||||
_bao.write((value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
protected void writeC(int value)
|
||||
{
|
||||
_bao.write(value & 0xff);
|
||||
}
|
||||
|
||||
protected void writeF(double org)
|
||||
{
|
||||
final long value = Double.doubleToRawLongBits(org);
|
||||
_bao.write((int) (value & 0xff));
|
||||
_bao.write((int) ((value >> 8) & 0xff));
|
||||
_bao.write((int) ((value >> 16) & 0xff));
|
||||
_bao.write((int) ((value >> 24) & 0xff));
|
||||
_bao.write((int) ((value >> 32) & 0xff));
|
||||
_bao.write((int) ((value >> 40) & 0xff));
|
||||
_bao.write((int) ((value >> 48) & 0xff));
|
||||
_bao.write((int) ((value >> 56) & 0xff));
|
||||
}
|
||||
|
||||
protected void writeS(String text)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (text != null)
|
||||
{
|
||||
_bao.write(text.getBytes("UTF-16LE"));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
_bao.write(0);
|
||||
_bao.write(0);
|
||||
}
|
||||
|
||||
protected void writeB(byte[] array)
|
||||
{
|
||||
try
|
||||
{
|
||||
_bao.write(array);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_log.warning(getClass().getSimpleName() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeQ(long value)
|
||||
{
|
||||
_bao.write((int) (value & 0xff));
|
||||
_bao.write((int) ((value >> 8) & 0xff));
|
||||
_bao.write((int) ((value >> 16) & 0xff));
|
||||
_bao.write((int) ((value >> 24) & 0xff));
|
||||
_bao.write((int) ((value >> 32) & 0xff));
|
||||
_bao.write((int) ((value >> 40) & 0xff));
|
||||
_bao.write((int) ((value >> 48) & 0xff));
|
||||
_bao.write((int) ((value >> 56) & 0xff));
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return _bao.size() + 2;
|
||||
}
|
||||
|
||||
public byte[] getBytes()
|
||||
{
|
||||
// if (this instanceof Init)
|
||||
// writeD(0x00); // reserve for XOR initial key
|
||||
|
||||
writeD(0x00); // reserve for checksum
|
||||
|
||||
final int padding = _bao.size() % 8;
|
||||
if (padding != 0)
|
||||
{
|
||||
for (int i = padding; i < 8; i++)
|
||||
{
|
||||
writeC(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
return _bao.toByteArray();
|
||||
}
|
||||
|
||||
public abstract byte[] getContent() throws IOException;
|
||||
}
|
Reference in New Issue
Block a user