actual freya branch

This commit is contained in:
2026-09-12 15:41:31 +00:00
parent 8049e0a882
commit 68c1cd27d4
3510 changed files with 336689 additions and 302906 deletions
@@ -0,0 +1,104 @@
/* 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.l2jserver.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.l2jserver.Config;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.Shutdown;
/**
* @author -Nemesiss- L2M
*/
public class DeadLockDetector extends Thread
{
private static Logger _log = Logger.getLogger(DeadLockDetector.class.getName());
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
{
long[] ids = tmx.findDeadlockedThreads();
if (ids != null)
{
deadlock = true;
ThreadInfo[] tis = tmx.getThreadInfo(ids, true, true);
String info = "DeadLock Found!\n";
for (ThreadInfo ti : tis)
{
info += ti.toString();
}
for (ThreadInfo ti : tis)
{
LockInfo[] locks = ti.getLockedSynchronizers();
MonitorInfo[] monitors = ti.getLockedMonitors();
if ((locks.length == 0) && (monitors.length == 0))
{
continue;
}
ThreadInfo dl = ti;
info += "Java-level deadlock:\n";
info += "\t" + dl.getThreadName() + " is waiting to lock " + dl.getLockInfo().toString() + " which is held by " + dl.getLockOwnerName() + "\n";
while ((dl = tmx.getThreadInfo(new long[]
{
dl.getLockOwnerId()
}, true, true)[0]).getThreadId() != ti.getThreadId())
{
info += "\t" + dl.getThreadName() + " is waiting to lock " + dl.getLockInfo().toString() + " which is held by " + dl.getLockOwnerName() + "\n";
}
}
_log.warning(info);
if (Config.RESTART_ON_DEADLOCK)
{
Announcements an = Announcements.getInstance();
an.announceToAll("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);
}
}
}
}
@@ -0,0 +1,50 @@
/*
* $Header: EventData.java
*
* $Author: SarEvoK
* Added copyright notice
*
*
* 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.l2jserver.util;
import java.util.LinkedList;
public class EventData
{
public int eventX;
public int eventY;
public int eventZ;
public int eventKarma;
public int eventPvpKills;
public int eventPkKills;
public String eventTitle;
public LinkedList<String> kills = new LinkedList<>();
public boolean eventSitForced = false;
public EventData(int pEventX, int pEventY, int pEventZ, int pEventkarma, int pEventpvpkills, int pEventpkkills, String pEventTitle, LinkedList<String> pKills, boolean pEventSitForced)
{
eventX = pEventX;
eventY = pEventY;
eventZ = pEventZ;
eventKarma = pEventkarma;
eventPvpKills = pEventpvpkills;
eventPkKills = pEventpkkills;
eventTitle = pEventTitle;
kills = pKills;
eventSitForced = pEventSitForced;
}
}
@@ -0,0 +1,161 @@
/*
* 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.l2jserver.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
{
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;
}
}
}
else
{
// check for embedded v4 in v6 addr (not done !)
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 (o instanceof IPSubnet)
{
return applyMask(((IPSubnet) o).getAddress());
}
else if (o instanceof InetAddress)
{
return applyMask(((InetAddress) o).getAddress());
}
return false;
}
private static final 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;
}
}
@@ -0,0 +1,143 @@
/*
* 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.l2jserver.util;
import java.net.InetAddress;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import org.mmocore.network.IAcceptFilter;
/**
* Formatted Forsaiken's IPv4 filter [DrHouse]
* @author Forsaiken
*/
public class IPv4Filter implements IAcceptFilter, Runnable
{
private final HashMap<Integer, Flood> _ipFloodMap;
private static final long SLEEP_TIME = 5000;
public IPv4Filter()
{
_ipFloodMap = new HashMap<>();
Thread t = new Thread(this);
t.setName(getClass().getSimpleName());
t.setDaemon(true);
t.start();
}
/**
* @param ip
* @return
*/
private static final 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)
{
InetAddress addr = sc.socket().getInetAddress();
int h = hash(addr.getAddress());
long current = System.currentTimeMillis();
Flood f;
synchronized (_ipFloodMap)
{
f = _ipFloodMap.get(h);
}
if (f != null)
{
if (f.trys == -1)
{
f.lastAccess = current;
return false;
}
if ((f.lastAccess + 1000) > current)
{
f.lastAccess = current;
if (f.trys >= 3)
{
f.trys = -1;
return false;
}
f.trys++;
}
else
{
f.lastAccess = current;
}
}
else
{
synchronized (_ipFloodMap)
{
_ipFloodMap.put(h, new Flood());
}
}
return true;
}
@Override
public void run()
{
while (true)
{
long reference = System.currentTimeMillis() - (1000 * 300);
synchronized (_ipFloodMap)
{
Iterator<Entry<Integer, Flood>> it = _ipFloodMap.entrySet().iterator();
while (it.hasNext())
{
Flood f = it.next().getValue();
if (f.lastAccess < reference)
{
it.remove();
}
}
}
try
{
Thread.sleep(SLEEP_TIME);
}
catch (InterruptedException e)
{
return;
}
}
}
}
@@ -0,0 +1,71 @@
/*
* 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.l2jserver.util;
import java.util.List;
import javolution.util.FastList;
/**
* A custom version of LinkedList with extension for iterating without using temporary collection<br>
* It`s provide synchronization lock when iterating if needed<br>
* <br>
* @author Julian Version 1.0.1 (2008-02-07)<br>
* Changes:<br>
* 1.0.0 - Initial version.<br>
* 1.0.1 - Made forEachP() final.<br>
*/
public class L2FastList<T extends Object> extends FastList<T>
{
static final long serialVersionUID = 1L;
/**
* Public inner interface used by ForEach iterations<br>
* @author Julian
*/
public interface I2ForEach<T>
{
public boolean ForEach(T obj);
}
public L2FastList()
{
super();
}
public L2FastList(List<? extends T> list)
{
super(list);
}
/**
* Public method that iterate entire collection.<br>
* <br>
* @param func - a class method that must be executed on every element of collection.<br>
* @return - returns true if entire collection is iterated, false if it`s been interrupted by<br>
* check method (I2ForEach.forEach())<br>
*/
public boolean forEach(I2ForEach<T> func)
{
for (T e : this)
{
if (!func.ForEach(e))
{
return false;
}
}
return true;
}
}
@@ -0,0 +1,94 @@
/*
* 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.l2jserver.util;
import java.util.HashMap;
import java.util.Map;
/**
* A custom version of HashMap with extension for iterating without using temporary collection<br>
* <br>
* @author Julian Version 1.0.1 (2008-02-07)<br>
* Changes:<br>
* 1.0.0 - Initial version.<br>
* 1.0.1 - Made forEachP() final.<br>
*/
public class L2FastMap<K extends Object, V extends Object> extends HashMap<K, V>
{
static final long serialVersionUID = 1L;
/**
* Public inner interface used by ForEach iterations<br>
* @author Julian
*/
public interface I2ForEach<K, V>
{
public boolean forEach(K key, V val);
}
public interface I2ForEachKey<K>
{
public boolean forEach(K key);
}
public interface I2ForEachValue<V>
{
public boolean forEach(V val);
}
/**
* Public method that iterate entire collection.<br>
* <br>
* @param func - a class method that must be executed on every element of collection.<br>
* @return - returns true if entire collection is iterated, false if it`s been interrupted by<br>
* check method (I2ForEach.forEach())<br>
*/
public boolean ForEach(I2ForEach<K, V> func)
{
for (Map.Entry<K, V> e : entrySet())
{
if (!func.forEach(e.getKey(), e.getValue()))
{
return false;
}
}
return true;
}
public boolean ForEachKey(I2ForEachKey<K> func)
{
for (K k : keySet())
{
if (!func.forEach(k))
{
return false;
}
}
return true;
}
public boolean ForEachValue(I2ForEachValue<V> func)
{
for (V v : values())
{
if (!func.forEach(v))
{
return false;
}
}
return true;
}
}
@@ -0,0 +1,26 @@
package com.l2jserver.util;
import java.util.logging.LogManager;
/**
* Dummy class to enable logs while shutting down
*/
public class L2LogManager extends LogManager
{
public L2LogManager()
{
super();
}
@Override
public void reset()
{
// do nothing
}
public void doReset()
{
super.reset();
}
}
@@ -0,0 +1,512 @@
/*
* 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.l2jserver.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.l2jserver.gameserver.model.L2Object;
/**
* This class is a highly optimized hashtable, where keys are integers. The main goal of this class is to allow concurent read/iterate and write access to this table, plus minimal used memory. This class uses plain array as the table of values, and keys are used to get position in the table. If the
* position is already busy, we iterate to the next position, unil we find the needed element or null. To iterate over the table (read access) we may simply iterate throgh table array. In case we remove an element from the table, we check - if the next position is null, we reset table's slot to
* null, otherwice we assign it to a dummy value
* @author mkizub
* @param <T> type of values stored in this hashtable
*/
public final class L2ObjectHashMap<T extends L2Object> extends L2ObjectMap<T>
{
private static final boolean TRACE = false;
private static final boolean DEBUG = false;
private final static int[] PRIMES =
{
5,
7,
11,
17,
23,
29,
37,
47,
59,
71,
89,
107,
131,
163,
197,
239,
293,
353,
431,
521,
631,
761,
919,
1103,
1327,
1597,
1931,
2333,
2801,
3371,
4049,
4861,
5839,
7013,
8419,
10103,
12143,
14591,
17519,
21023,
25229,
30293,
36353,
43627,
52361,
62851,
75431,
90523,
108631,
130363,
156437,
187751,
225307,
270371,
324449,
389357,
467237,
560689,
672827,
807403,
968897,
1162687,
1395263,
1674319,
2009191,
2411033,
2893249,
3471899,
4166287,
4999559,
5999471,
7199369
};
private T[] _table;
private int[] _keys;
private int _count;
private static int getPrime(int min)
{
for (int element : PRIMES)
{
if (element >= min)
{
return element;
}
}
throw new OutOfMemoryError();
}
@SuppressWarnings("unchecked")
public L2ObjectHashMap()
{
int size = PRIMES[0];
_table = (T[]) new L2Object[size];
_keys = new int[size];
if (DEBUG)
{
check();
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#size()
*/
@Override
public int size()
{
return _count;
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#isEmpty()
*/
@Override
public boolean isEmpty()
{
return _count == 0;
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#clear()
*/
@Override
@SuppressWarnings("unchecked")
public synchronized void clear()
{
int size = PRIMES[0];
_table = (T[]) new L2Object[size];
_keys = new int[size];
_count = 0;
if (DEBUG)
{
check();
}
}
private void check()
{
if (DEBUG)
{
int cnt = 0;
for (int i = 0; i < _table.length; i++)
{
L2Object obj = _table[i];
if (obj == null)
{
assert (_keys[i] == 0) || (_keys[i] == 0x80000000);
}
else
{
cnt++;
assert obj.getObjectId() == (_keys[i] & 0x7FFFFFFF);
}
}
assert cnt == _count;
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#put(T)
*/
@Override
public synchronized void put(T obj)
{
if (_count >= (_table.length / 2))
{
expand();
}
final int hashcode = obj.getObjectId();
assert hashcode > 0;
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
int ntry = 0;
int slot = -1; // keep last found slot
do
{
int pos = (seed % _table.length) & 0x7FFFFFFF;
if (_table[pos] == null)
{
if (slot < 0)
{
slot = pos;
}
if (_keys[pos] >= 0)
{
// found an empty slot without previous collisions,
// but use previously found slot
_keys[slot] = hashcode;
_table[slot] = obj;
_count++;
if (TRACE)
{
System.err.println("ht: put obj id=" + hashcode + " at slot=" + slot);
}
if (DEBUG)
{
check();
}
return;
}
}
else
{
// check if we are adding the same object
if (_table[pos] == obj)
{
return;
}
// this should never happen
assert obj.getObjectId() != _table[pos].getObjectId();
// if there was no collisions at this slot, and we found a free
// slot previously - use found slot
if ((slot >= 0) && (_keys[pos] > 0))
{
_keys[slot] |= hashcode; // preserve collision bit
_table[slot] = obj;
_count++;
if (TRACE)
{
System.err.println("ht: put obj id=" + hashcode + " at slot=" + slot);
}
if (DEBUG)
{
check();
}
return;
}
}
// set collision bit
_keys[pos] |= 0x80000000;
// calculate next slot
seed += incr;
}
while (++ntry < _table.length);
if (DEBUG)
{
check();
}
throw new IllegalStateException();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#remove(T)
*/
@Override
public synchronized void remove(T obj)
{
int hashcode = obj.getObjectId();
assert hashcode > 0;
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
int ntry = 0;
do
{
int pos = (seed % _table.length) & 0x7FFFFFFF;
if (_table[pos] == obj)
{
// found the object
_keys[pos] &= 0x80000000; // preserve collision bit
_table[pos] = null;
_count--;
if (TRACE)
{
System.err.println("ht: remove obj id=" + hashcode + " from slot=" + pos);
}
if (DEBUG)
{
check();
}
return;
}
// check for collision (if we previously deleted element)
if ((_table[pos] == null) && (_keys[pos] >= 0))
{
if (DEBUG)
{
check();
}
return; // throw new IllegalArgumentException();
}
// calculate next slot
seed += incr;
}
while (++ntry < _table.length);
if (DEBUG)
{
check();
}
throw new IllegalStateException();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#get(int)
*/
@Override
public T get(int id)
{
final int size = _table.length;
if (id <= 0)
{
return null;
}
if (size <= 11)
{
// for small tables linear check is fast
for (int i = 0; i < size; i++)
{
if ((_keys[i] & 0x7FFFFFFF) == id)
{
return _table[i];
}
}
return null;
}
int seed = id;
int incr = 1 + (((seed >> 5) + 1) % (size - 1));
int ntry = 0;
do
{
int pos = (seed % size) & 0x7FFFFFFF;
if ((_keys[pos] & 0x7FFFFFFF) == id)
{
return _table[pos];
}
// check for collision (if we previously deleted element)
if ((_table[pos] == null) && (_keys[pos] >= 0))
{
return null;
}
// calculate next slot
seed += incr;
}
while (++ntry < size);
return null;
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#contains(T)
*/
@Override
public boolean contains(T obj)
{
return get(obj.getObjectId()) != null;
}
@SuppressWarnings("unchecked")
private/* already synchronized in put() */void expand()
{
int newSize = getPrime(_table.length + 1);
L2Object[] newTable = new L2Object[newSize];
int[] newKeys = new int[newSize];
// over all old entries
next_entry: for (int i = 0; i < _table.length; i++)
{
L2Object obj = _table[i];
if (obj == null)
{
continue;
}
final int hashcode = _keys[i] & 0x7FFFFFFF;
assert hashcode == obj.getObjectId();
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (newSize - 1));
int ntry = 0;
do
{
int pos = (seed % newSize) & 0x7FFFFFFF;
if (newTable[pos] == null)
{
assert (newKeys[pos] == 0) && (hashcode != 0);
// found an empty slot without previous collisions,
// but use previously found slot
newKeys[pos] = hashcode;
newTable[pos] = obj;
if (TRACE)
{
System.err.println("ht: move obj id=" + hashcode + " from slot=" + i + " to slot=" + pos);
}
continue next_entry;
}
// set collision bit
newKeys[pos] |= 0x80000000;
// calculate next slot
seed += incr;
}
while (++ntry < newSize);
throw new IllegalStateException();
}
_table = (T[]) newTable;
_keys = newKeys;
if (DEBUG)
{
check();
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#iterator()
*/
@Override
public Iterator<T> iterator()
{
return new Itr(_table);
}
class Itr implements Iterator<T>
{
private final T[] _array;
private int _nextIdx;
private T _nextObj;
private T _lastRet;
Itr(T[] pArray)
{
this._array = pArray;
for (; _nextIdx < _array.length; _nextIdx++)
{
_nextObj = _array[_nextIdx];
if (_nextObj != null)
{
return;
}
}
}
@Override
public boolean hasNext()
{
return _nextObj != null;
}
@Override
public T next()
{
if (_nextObj == null)
{
throw new NoSuchElementException();
}
_lastRet = _nextObj;
for (_nextIdx++; _nextIdx < _array.length; _nextIdx++)
{
_nextObj = _array[_nextIdx];
if (_nextObj != null)
{
break;
}
}
if (_nextIdx >= _array.length)
{
_nextObj = null;
}
return _lastRet;
}
@Override
public void remove()
{
if (_lastRet == null)
{
throw new IllegalStateException();
}
L2ObjectHashMap.this.remove(_lastRet);
}
}
}
@@ -0,0 +1,505 @@
/*
* 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.l2jserver.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.l2jserver.gameserver.model.L2Object;
/**
* This class is a highly optimized hashtable, where keys are integers. The main goal of this class is to allow concurent read/iterate and write access to this table, plus minimal used memory. This class uses plain array as the table of values, and keys are used to get position in the table. If the
* position is already busy, we iterate to the next position, unil we find the needed element or null. To iterate over the table (read access) we may simply iterate throgh table array. In case we remove an element from the table, we check - if the next position is null, we reset table's slot to
* null, otherwice we assign it to a dummy value
* @author mkizub
* @param <T> type of values stored in this hashtable
*/
public final class L2ObjectHashSet<T extends L2Object> extends L2ObjectSet<T>
{
private static final boolean TRACE = false;
private static final boolean DEBUG = false;
private final static int[] PRIMES =
{
5,
7,
11,
17,
23,
29,
37,
47,
59,
71,
89,
107,
131,
163,
197,
239,
293,
353,
431,
521,
631,
761,
919,
1103,
1327,
1597,
1931,
2333,
2801,
3371,
4049,
4861,
5839,
7013,
8419,
10103,
12143,
14591,
17519,
21023,
25229,
30293,
36353,
43627,
52361,
62851,
75431,
90523,
108631,
130363,
156437,
187751,
225307,
270371,
324449,
389357,
467237,
560689,
672827,
807403,
968897,
1162687,
1395263,
1674319,
2009191,
2411033,
2893249,
3471899,
4166287,
4999559,
5999471,
7199369
};
private T[] _table;
private int[] _collisions;
private int _count;
private static int getPrime(int min)
{
for (int element : PRIMES)
{
if (element >= min)
{
return element;
}
}
throw new OutOfMemoryError();
}
@SuppressWarnings("unchecked")
public L2ObjectHashSet()
{
int size = PRIMES[0];
_table = (T[]) new L2Object[size];
_collisions = new int[(size + 31) >> 5];
if (DEBUG)
{
check();
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#size()
*/
@Override
public int size()
{
return _count;
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#isEmpty()
*/
@Override
public boolean isEmpty()
{
return _count == 0;
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#clear()
*/
@Override
@SuppressWarnings("unchecked")
public synchronized void clear()
{
int size = PRIMES[0];
_table = (T[]) new L2Object[size];
_collisions = new int[(size + 31) >> 5];
_count = 0;
if (DEBUG)
{
check();
}
}
private void check()
{
if (DEBUG)
{
int cnt = 0;
assert _collisions.length == ((_table.length + 31) >> 5);
for (T obj : _table)
{
if (obj != null)
{
cnt++;
}
}
assert cnt == _count;
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#put(T)
*/
@Override
public synchronized void put(T obj)
{
if (obj == null)
{
return;
}
if (contains(obj))
{
return;
}
if (_count >= (_table.length / 2))
{
expand();
}
final int hashcode = obj.getObjectId();
assert hashcode > 0;
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
int ntry = 0;
int slot = -1; // keep last found slot
do
{
int pos = (seed % _table.length) & 0x7FFFFFFF;
if (_table[pos] == null)
{
if (slot < 0)
{
slot = pos;
}
if ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0)
{
// found an empty slot without previous collisions,
// but use previously found slot
_table[slot] = obj;
_count++;
if (TRACE)
{
System.err.println("ht: put obj id=" + hashcode + " at slot=" + slot);
}
if (DEBUG)
{
check();
}
return;
}
}
else
{
// check if we are adding the same object
if (_table[pos] == obj)
{
return;
}
// this should never happen
assert obj.getObjectId() != _table[pos].getObjectId();
// if there was no collisions at this slot, and we found a free
// slot previously - use found slot
if ((slot >= 0) && ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0))
{
_table[slot] = obj;
_count++;
if (TRACE)
{
System.err.println("ht: put obj id=" + hashcode + " at slot=" + slot);
}
if (DEBUG)
{
check();
}
return;
}
}
// set collision bit
_collisions[pos >> 5] |= 1 << (pos & 31);
// calculate next slot
seed += incr;
}
while (++ntry < _table.length);
if (DEBUG)
{
check();
}
throw new IllegalStateException();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#remove(T)
*/
@Override
public synchronized void remove(T obj)
{
if (obj == null)
{
return;
}
if (!contains(obj))
{
return;
}
int hashcode = obj.getObjectId();
assert hashcode > 0;
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (_table.length - 1));
int ntry = 0;
do
{
int pos = (seed % _table.length) & 0x7FFFFFFF;
if (_table[pos] == obj)
{
// found the object
_table[pos] = null;
_count--;
if (TRACE)
{
System.err.println("ht: remove obj id=" + hashcode + " from slot=" + pos);
}
if (DEBUG)
{
check();
}
return;
}
// check for collision (if we previously deleted element)
if ((_table[pos] == null) && ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0))
{
if (DEBUG)
{
check();
}
return; // throw new IllegalArgumentException();
}
// calculate next slot
seed += incr;
}
while (++ntry < _table.length);
if (DEBUG)
{
check();
}
throw new IllegalStateException();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#contains(T)
*/
@Override
public boolean contains(T obj)
{
final int size = _table.length;
if (size <= 11)
{
// for small tables linear check is fast
for (int i = 0; i < size; i++)
{
if (_table[i] == obj)
{
return true;
}
}
return false;
}
int hashcode = obj.getObjectId();
assert hashcode > 0;
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (size - 1));
int ntry = 0;
do
{
int pos = (seed % size) & 0x7FFFFFFF;
if (_table[pos] == obj)
{
return true;
}
// check for collision (if we previously deleted element)
if ((_table[pos] == null) && ((_collisions[pos >> 5] & (1 << (pos & 31))) == 0))
{
return false;
}
// calculate next slot
seed += incr;
}
while (++ntry < size);
return false;
}
@SuppressWarnings("unchecked")
private/* already synchronized in put() */void expand()
{
int newSize = getPrime(_table.length + 1);
L2Object[] newTable = new L2Object[newSize];
int[] newCollisions = new int[(newSize + 31) >> 5];
// over all old entries
next_entry: for (int i = 0; i < _table.length; i++)
{
L2Object obj = _table[i];
if (obj == null)
{
continue;
}
final int hashcode = obj.getObjectId();
int seed = hashcode;
int incr = 1 + (((seed >> 5) + 1) % (newSize - 1));
int ntry = 0;
do
{
int pos = (seed % newSize) & 0x7FFFFFFF;
if (newTable[pos] == null)
{
// found an empty slot without previous collisions,
// but use previously found slot
newTable[pos] = obj;
if (TRACE)
{
System.err.println("ht: move obj id=" + hashcode + " from slot=" + i + " to slot=" + pos);
}
continue next_entry;
}
// set collision bit
newCollisions[pos >> 5] |= 1 << (pos & 31);
// calculate next slot
seed += incr;
}
while (++ntry < newSize);
throw new IllegalStateException();
}
_table = (T[]) newTable;
_collisions = newCollisions;
if (DEBUG)
{
check();
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#iterator()
*/
@Override
public Iterator<T> iterator()
{
return new Itr(_table);
}
class Itr implements Iterator<T>
{
private final T[] _array;
private int _nextIdx;
private T _nextObj;
private T _lastRet;
Itr(T[] pArray)
{
this._array = pArray;
for (; _nextIdx < _array.length; _nextIdx++)
{
_nextObj = _array[_nextIdx];
if (_nextObj != null)
{
return;
}
}
}
@Override
public boolean hasNext()
{
return _nextObj != null;
}
@Override
public T next()
{
if (_nextObj == null)
{
throw new NoSuchElementException();
}
_lastRet = _nextObj;
for (_nextIdx++; _nextIdx < _array.length; _nextIdx++)
{
_nextObj = _array[_nextIdx];
if (_nextObj != null)
{
break;
}
}
if (_nextIdx >= _array.length)
{
_nextObj = null;
}
return _lastRet;
}
@Override
public void remove()
{
if (_lastRet == null)
{
throw new IllegalStateException();
}
L2ObjectHashSet.this.remove(_lastRet);
}
}
}
@@ -0,0 +1,67 @@
/*
* $Header: L2ObjectMap.java, 22/07/2005 13:17:51 luisantonioa Exp $
*
* $Author: luisantonioa $
* $Date: 22/07/2005 13:17:51 $
* $Revision: 1 $
* $Log: L2ObjectMap.java,v $
* Revision 1 22/07/2005 13:17:51 luisantonioa
* Added copyright notice
*
*
* 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.l2jserver.util;
import java.util.Iterator;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.L2Object;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
public abstract class L2ObjectMap<T extends L2Object> implements Iterable<T>
{
public abstract int size();
public abstract boolean isEmpty();
public abstract void clear();
public abstract void put(T obj);
public abstract void remove(T obj);
public abstract T get(int id);
public abstract boolean contains(T obj);
@Override
public abstract Iterator<T> iterator();
public static L2ObjectMap<L2Object> createL2ObjectMap()
{
switch (Config.MAP_TYPE)
{
case WorldObjectMap:
return new WorldObjectMap<>();
default:
return new WorldObjectTree<>();
}
}
}
@@ -0,0 +1,77 @@
/*
* $Header: L2ObjectSet.java, 22/07/2005 13:22:46 luisantonioa Exp $
*
* $Author: luisantonioa $
* $Date: 22/07/2005 13:22:46 $
* $Revision: 1 $
* $Log: L2ObjectSet.java,v $
* Revision 1 22/07/2005 13:22:46 luisantonioa
* Added copyright notice
*
*
* 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.l2jserver.util;
import java.util.Iterator;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Playable;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
public abstract class L2ObjectSet<T extends L2Object> implements Iterable<T>
{
public static L2ObjectSet<L2Object> createL2ObjectSet()
{
switch (Config.SET_TYPE)
{
case WorldObjectSet:
return new WorldObjectSet<>();
default:
return new L2ObjectHashSet<>();
}
}
public static L2ObjectSet<L2Playable> createL2PlayerSet()
{
switch (Config.SET_TYPE)
{
case WorldObjectSet:
return new WorldObjectSet<>();
default:
return new L2ObjectHashSet<>();
}
}
public abstract int size();
public abstract boolean isEmpty();
public abstract void clear();
public abstract void put(T obj);
public abstract void remove(T obj);
public abstract boolean contains(T obj);
@Override
public abstract Iterator<T> iterator();
}
@@ -0,0 +1,132 @@
/*
* 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.l2jserver.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Properties;
import java.util.logging.Logger;
/**
* @author Noctarius
*/
public final class L2Properties extends Properties
{
private static final long serialVersionUID = 1L;
private static Logger _log = Logger.getLogger(L2Properties.class.getName());
public L2Properties()
{
}
public L2Properties(String name) throws IOException
{
load(new FileInputStream(name));
}
public L2Properties(File file) throws IOException
{
load(new FileInputStream(file));
}
public L2Properties(InputStream inStream) throws IOException
{
load(inStream);
}
public L2Properties(Reader reader) throws IOException
{
load(reader);
}
public void load(String name) throws IOException
{
load(new FileInputStream(name));
}
public void load(File file) throws IOException
{
load(new FileInputStream(file));
}
@Override
public void load(InputStream inStream) throws IOException
{
InputStreamReader reader = null;
try
{
reader = new InputStreamReader(inStream, Charset.defaultCharset());
super.load(reader);
}
finally
{
inStream.close();
if (reader != null)
{
reader.close();
}
}
}
@Override
public void load(Reader reader) throws IOException
{
try
{
super.load(reader);
}
finally
{
reader.close();
}
}
@Override
public String getProperty(String key)
{
String property = super.getProperty(key);
if (property == null)
{
_log.info("L2Properties: Missing property for key - " + key);
return null;
}
return property.trim();
}
@Override
public String getProperty(String key, String defaultValue)
{
String property = super.getProperty(key, defaultValue);
if (property == null)
{
_log.warning("L2Properties: Missing defaultValue for key - " + key);
return null;
}
return property.trim();
}
}
@@ -0,0 +1,438 @@
/*
* 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.l2jserver.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
/**
* Highly concurrent List wrapping class, thread-safe<br>
* The default constructor sets a wrapped class to ArrayList<T> to minimize code line when wrapped class type is not that importent.<br>
* <br>
* Note: Iterator returned does not support element removal!
* @author Julian
*/
public class L2SyncList<T extends Object> implements List<T>
{
private final List<T> _list;
private final ReentrantReadWriteLock _rw = new ReentrantReadWriteLock();
private final ReadLock _rl = _rw.readLock();
private final WriteLock _wl = _rw.writeLock();
/**
* Default constructor use ArrayList as it internal
*/
public L2SyncList()
{
_list = new ArrayList<>();
}
public L2SyncList(List<T> list)
{
_list = list;
}
@Override
public T get(int index)
{
_rl.lock();
try
{
return _list.get(index);
}
finally
{
_rl.unlock();
}
}
@Override
public boolean equals(Object o)
{
_rl.lock();
try
{
return _list.equals(o);
}
finally
{
_rl.unlock();
}
}
@Override
public int hashCode()
{
_rl.lock();
try
{
return _list.hashCode();
}
finally
{
_rl.unlock();
}
}
@Override
public T set(int index, T element)
{
_wl.lock();
try
{
return _list.set(index, element);
}
finally
{
_wl.unlock();
}
}
@Override
public void add(int index, T element)
{
_wl.lock();
try
{
_list.add(index, element);
}
finally
{
_wl.unlock();
}
}
@Override
public boolean add(T element)
{
_wl.lock();
try
{
return _list.add(element);
}
finally
{
_wl.unlock();
}
}
@Override
public T remove(int index)
{
_wl.lock();
try
{
return _list.remove(index);
}
finally
{
_wl.unlock();
}
}
@Override
public boolean remove(Object value)
{
_wl.lock();
try
{
return _list.remove(value);
}
finally
{
_wl.unlock();
}
}
@Override
public boolean removeAll(Collection<?> list)
{
_wl.lock();
try
{
return _list.removeAll(list);
}
finally
{
_wl.unlock();
}
}
@Override
public boolean retainAll(Collection<?> list)
{
_wl.lock();
try
{
return _list.retainAll(list);
}
finally
{
_wl.unlock();
}
}
@Override
public int indexOf(Object o)
{
_rl.lock();
try
{
return _list.indexOf(o);
}
finally
{
_rl.unlock();
}
}
@Override
public boolean contains(Object o)
{
_rl.lock();
try
{
return _list.contains(o);
}
finally
{
_rl.unlock();
}
}
@Override
public boolean containsAll(Collection<?> list)
{
_rl.lock();
try
{
return _list.containsAll(list);
}
finally
{
_rl.unlock();
}
}
@Override
public int lastIndexOf(Object o)
{
_rl.lock();
try
{
return _list.lastIndexOf(o);
}
finally
{
_rl.unlock();
}
}
@Override
public boolean addAll(Collection<? extends T> list)
{
_wl.lock();
try
{
return _list.addAll(list);
}
finally
{
_wl.unlock();
}
}
@Override
public boolean addAll(int index, Collection<? extends T> c)
{
_wl.lock();
try
{
return _list.addAll(index, c);
}
finally
{
_wl.unlock();
}
}
@Override
public List<T> subList(int fromIndex, int toIndex)
{
_rl.lock();
try
{
return new L2SyncList<>(_list.subList(fromIndex, toIndex));
}
finally
{
_rl.unlock();
}
}
@Override
public void clear()
{
_wl.lock();
try
{
_list.clear();
}
finally
{
_wl.unlock();
}
}
@Override
public int size()
{
_rl.lock();
try
{
return _list.size();
}
finally
{
_rl.unlock();
}
}
@Override
public boolean isEmpty()
{
_rl.lock();
try
{
return _list.isEmpty();
}
finally
{
_rl.unlock();
}
}
/**
* <FONT color="#FF0000">WARNING: Unsupported</FONT>
*/
@Override
public ListIterator<T> listIterator()
{
throw new UnsupportedOperationException();
}
/**
* <FONT color="#FF0000">WARNING: Unsupported</FONT>
* @see java.util.List#listIterator(int)
*/
@Override
public ListIterator<T> listIterator(int index)
{
throw new UnsupportedOperationException();
}
/**
* <FONT color="#FF0000">WARNING: Returned iterator use cloned List</FONT>
* @see java.util.List#iterator()
*/
@Override
@SuppressWarnings("unchecked")
public Iterator<T> iterator()
{
return new Itr((T[]) _list.toArray());
}
private class Itr implements Iterator<T>
{
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int size;
T[] elementData;
public Itr(T[] data)
{
elementData = data;
if (data != null)
{
size = data.length;
}
else
{
size = 0;
}
}
@Override
public boolean hasNext()
{
return cursor != size;
}
@Override
public T next()
{
int i = cursor;
if (i >= size)
{
throw new NoSuchElementException();
}
cursor = i + 1;
lastRet = i;
return elementData[lastRet];
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
@Override
public Object[] toArray()
{
_rl.lock();
try
{
return _list.toArray();
}
finally
{
_rl.unlock();
}
}
@Override
@SuppressWarnings("hiding")
public <T> T[] toArray(T[] a)
{
_rl.lock();
try
{
return _list.toArray(a);
}
finally
{
_rl.unlock();
}
}
}
@@ -0,0 +1,195 @@
/*
* 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.l2jserver.util;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import com.l2jserver.util.L2FastMap.I2ForEach;
import com.l2jserver.util.L2FastMap.I2ForEachKey;
import com.l2jserver.util.L2FastMap.I2ForEachValue;
/**
* Fully synchronized version of L2FastMap class.<br>
* In addition it`s provide ForEach methods and interfaces that can be used for iterating collection<br>
* without using iterators. As addition its provide full lock on entire class if needed<br>
* <font color="red">WARNING!!! methods: keySet(), values() and entrySet() are removed!</font> <br>
* @author Julian Version: 1.0.0 <2008-02-07> - Original release
* @author Julian Varsion: 1.0.1 <2008-06-17> - Changed underlayng map to L2FastMap
*/
public class L2SyncMap<K extends Object, V extends Object> implements Map<K, V>
{
static final long serialVersionUID = 1L;
private final L2FastMap<K, V> _map = new L2FastMap<>();
@Override
public synchronized V put(K key, V value)
{
return _map.put(key, value);
}
@Override
public synchronized V get(Object key)
{
return _map.get(key);
}
@Override
public synchronized V remove(Object key)
{
return _map.remove(key);
}
@Override
public synchronized boolean containsKey(Object key)
{
return _map.containsKey(key);
}
@Override
public synchronized int size()
{
return _map.size();
}
@Override
public synchronized boolean isEmpty()
{
return _map.isEmpty();
}
@Override
public synchronized void clear()
{
_map.clear();
}
/**
* This method use specific locking strategy: map which have lowest hashCode() will be locked first
* @see java.util.Map#putAll(java.util.Map)
*/
@Override
public void putAll(Map<? extends K, ? extends V> map)
{
if ((map == null) || (this == map))
{
return;
}
if (this.hashCode() <= map.hashCode())
{
synchronized (this)
{
synchronized (map)
{
_map.putAll(map);
}
}
}
else
{
synchronized (map)
{
synchronized (this)
{
_map.putAll(map);
}
}
}
}
@Override
public synchronized boolean containsValue(Object value)
{
return _map.containsValue(value);
}
@Override
public synchronized boolean equals(Object o)
{
return _map.equals(o);
}
@Override
public synchronized int hashCode()
{
return _map.hashCode();
}
@Override
public synchronized String toString()
{
return _map.toString();
}
/**
* Public method that iterate entire collection.<br>
* <br>
* @param func - a class method that must be executed on every element of collection.<br>
* @return - returns true if entire collection is iterated, false if it`s been interrupted by check method (I2ForEach.forEach())<br>
*/
public synchronized final boolean ForEach(I2ForEach<K, V> func)
{
return _map.ForEach(func);
}
public synchronized final boolean ForEachValue(I2ForEachValue<V> func)
{
return _map.ForEachValue(func);
}
public synchronized final boolean ForEachKey(I2ForEachKey<K> func)
{
return _map.ForEachKey(func);
}
/**
* <font color="red">Unsupported operation!!!</font>
* @deprecated
* @throws UnsupportedOperationException
* @see java.util.Map#values()
*/
@Deprecated
@Override
public Collection<V> values()
{
throw new UnsupportedOperationException();
}
/**
* <font color="red">Unsupported operation!!!</font>
* @deprecated
* @throws UnsupportedOperationException
*/
@Deprecated
@Override
public Set<K> keySet()
{
throw new UnsupportedOperationException();
}
/**
* <font color="red">Unsupported operation!!!</font>
* @deprecated
* @throws UnsupportedOperationException
* @see java.util.Map#entrySet()
*/
@Deprecated
@Override
public Set<Map.Entry<K, V>> entrySet()
{
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,178 @@
/*
* $Header: Point3D.java, 19/07/2005 21:33:07 luisantonioa Exp $
*
* $Author: luisantonioa $
* $Date: 19/07/2005 21:33:07 $
* $Revision: 1 $
* $Log: Point3D.java,v $
* Revision 1 19/07/2005 21:33:07 luisantonioa
* Added copyright notice
*
*
* 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.l2jserver.util;
import java.io.Serializable;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
public class Point3D implements Serializable
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 4638345252031872576L;
private volatile int _x, _y, _z;
public Point3D(int pX, int pY, int pZ)
{
_x = pX;
_y = pY;
_z = pZ;
}
public Point3D(int pX, int pY)
{
_x = pX;
_y = pY;
_z = 0;
}
/**
* @param worldPosition
*/
public Point3D(Point3D worldPosition)
{
synchronized (worldPosition)
{
_x = worldPosition._x;
_y = worldPosition._y;
_z = worldPosition._z;
}
}
public synchronized void setTo(Point3D point)
{
synchronized (point)
{
_x = point._x;
_y = point._y;
_z = point._z;
}
}
@Override
public String toString()
{
return "(" + _x + ", " + _y + ", " + _z + ")";
}
@Override
public int hashCode()
{
return _x ^ _y ^ _z;
}
@Override
public synchronized boolean equals(Object o)
{
if (o instanceof Point3D)
{
Point3D point3D = (Point3D) o;
boolean ret;
synchronized (point3D)
{
ret = (point3D._x == _x) && (point3D._y == _y) && (point3D._z == _z);
}
return ret;
}
return false;
}
public synchronized boolean equals(int pX, int pY, int pZ)
{
return (_x == pX) && (_y == pY) && (_z == pZ);
}
public synchronized long distanceSquaredTo(Point3D point)
{
long dx, dy;
synchronized (point)
{
dx = _x - point._x;
dy = _y - point._y;
}
return (dx * dx) + (dy * dy);
}
public static long distanceSquared(Point3D point1, Point3D point2)
{
long dx, dy;
synchronized (point1)
{
synchronized (point2)
{
dx = point1._x - point2._x;
dy = point1._y - point2._y;
}
}
return (dx * dx) + (dy * dy);
}
public static boolean distanceLessThan(Point3D point1, Point3D point2, double distance)
{
return distanceSquared(point1, point2) < (distance * distance);
}
public int getX()
{
return _x;
}
public synchronized void setX(int pX)
{
_x = pX;
}
public int getY()
{
return _y;
}
public synchronized void setY(int pY)
{
_y = pY;
}
public int getZ()
{
return _z;
}
public synchronized void setZ(int pZ)
{
_z = pZ;
}
public synchronized void setXYZ(int pX, int pY, int pZ)
{
_x = pX;
_y = pY;
_z = pZ;
}
}
@@ -0,0 +1,338 @@
// 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.l2jserver.util;
import java.util.Arrays;
/*
* Modified for Trove to use the java.util.Arrays sort/search
* algorithms instead of those provided with colt.
*/
/**
* Used to keep hash table capacities prime numbers. Not of interest for users; only for implementors of hashtables.
* <p>
* Choosing prime numbers as hash table capacities is a good idea to keep them working fast, particularly under hash table expansions.
* <p>
* However, JDK 1.2, JGL 3.1 and many other toolkits do nothing to keep capacities prime. 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). Memory requirements: 1 KB static memory.
* @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. Each chunk contains prime numbers. A chunk starts with a prime P1. The next element is a prime P2. P2 is the smallest prime for which holds: P2 >= 2*P1. 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 the list includes a prime number <= desired capacity * 1.11. Therefore, primes can be retrieved which are quite close to any desired capacity, which in turn avoids wasting memory. For example, the list includes
* 1039,1117,1201,1277,1361,1439,1523,1597,1759,1907,2081. So if you need a prime >= 1040, you will find a prime <= 1040*1.11=1154. Chunks are chosen such that they are optimized for a hashtable growthfactor of 2.0; If your hashtable has such a growthfactor then, after initially
* "rounding to a prime" upon hashtable construction, it will later expand to prime capacities such that there exist no better primes. In total these are about 32*10=320 numbers -> 1 KB of static memory needed. 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>&gt;= desiredCapacity</code> and very close to <code>desiredCapacity</code> (within 11% if <code>desiredCapacity &gt;= 1000</code>).
* @param desiredCapacity the capacity desired by the user.
* @return the capacity which should be used for a hashtable.
*/
public static final 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];
}
}
+449
View File
@@ -0,0 +1,449 @@
/* 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.l2jserver.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 static final long serialVersionUID = 1L;
private volatile long _seed;
public NonAtomicRandom()
{
this(++SEED_UNIQUIFIER + System.nanoTime());
}
public NonAtomicRandom(final long seed)
{
setSeed(seed);
}
@Override
public final int next(final int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
@Override
public final void setSeed(final long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
/**
* @author Forsaiken
*/
public static final class RandomContainer
{
private final Random _random;
protected RandomContainer(final 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.l2jserver.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(final 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(final int min, final 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(final long min, final 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(final 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.l2jserver.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jserver.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jserver.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jserver.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(final long seed)
{
setSeed(seed);
}
final int next(final int bits)
{
return (int) ((_seed = ((_seed * MULTIPLIER) + ADDEND) & MASK) >>> (48 - bits));
}
final void setSeed(final long seed)
{
_seed = (seed ^ MULTIPLIER) & MASK;
}
}
private static final long serialVersionUID = 1L;
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(final long seed)
{
_seedLocal = new ThreadLocal<Seed>()
{
@Override
public final Seed initialValue()
{
return new Seed(seed);
}
};
}
@Override
public final int next(final int bits)
{
return _seedLocal.get().next(bits);
}
@Override
public final void setSeed(final long seed)
{
if (_seedLocal != null)
{
_seedLocal.get().setSeed(seed);
}
}
}
private final static long ADDEND = 0xBL;
private final static long MASK = (1L << 48) - 1;
private final static long MULTIPLIER = 0x5DEECE66DL;
private static final RandomContainer rnd = newInstance(RandomType.UNSECURE_THREAD_LOCAL);
protected static volatile long SEED_UNIQUIFIER = 8682522807148012L;
public static final 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.l2jserver.util.Rnd#nextDouble()
*/
public static final 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 final int get(final 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 final int get(final int min, final 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 final long get(final long min, final long max)
{
return rnd.get(min, max);
}
public static final RandomContainer newInstance(final 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 final 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 final void nextBytes(final 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 final 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 final 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 final 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 final int nextInt()
{
return rnd.nextInt();
}
/**
* @see com.l2jserver.util.Rnd#get(int n)
*/
public static final int nextInt(final 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 final long nextLong()
{
return rnd.nextLong();
}
}
@@ -0,0 +1,267 @@
/*
* $Header$
*
* $Author: fordfrog $ $Date$ $Revision$ $Log$
*
*
* 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.l2jserver.util;
import javolution.text.TextBuilder;
/**
* String utilities optimized for the best performance. <h1>How to Use It</h1> <h2>concat() or append()</h2> If concatenating strings in single call, use StringUtil.concat(), otherwise use StringUtil.append() and its variants. <h2>Minimum Calls</h2> Bad:
*
* <pre>
* final StringBuilder sbString = new StringBuilder();
* StringUtil.append(sbString, &quot;text 1&quot;, String.valueOf(npcId));
* StringUtil.append(&quot;text 2&quot;);
* </pre>
*
* Good:
*
* <pre>
* final StringBuilder sbString = new StringBuilder();
* StringUtil.append(sbString, &quot;text 1&quot;, String.valueOf(npcId), &quot;text 2&quot;);
* </pre>
*
* Why?<br/>
* Because the less calls you do, the less memory re-allocations have to be done so the whole text fits into the memory and less array copy tasks has to be performed. So if using less calls, less memory is used and string concatenation is faster. <h2>Size Hints for Loops</h2> Bad:
*
* <pre>
* final StringBuilder sbString = new StringBuilder();
* StringUtil.append(sbString, &quot;header start&quot;, someText, &quot;header end&quot;);
* for (int i = 0; i &lt; 50; i++)
* {
* StringUtil.append(sbString, &quot;text 1&quot;, stringArray[i], &quot;text 2&quot;);
* }
* </pre>
*
* Good:
*
* <pre>
* final StringBuilder sbString = StringUtil.startAppend(1300, &quot;header start&quot;, someText, &quot;header end&quot;);
* for (int i = 0; i &lt; 50; i++)
* {
* StringUtil.append(sbString, &quot;text 1&quot;, stringArray[i], &quot;text 2&quot;);
* }
* </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>. <h2>Concatenation and Constants</h2> Bad:
*
* <pre>
* StringUtil.concat(&quot;text 1 &quot;, &quot;text 2&quot;, String.valueOf(npcId));
* </pre>
*
* Good:
*
* <pre>
* StringUtil.concat(&quot;text 1 &quot; + &quot;text 2&quot;, String.valueOf(npcId));
* </pre>
*
* or
*
* <pre>
* StringUtil.concat(&quot;text 1 text 2&quot;, 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. <h2>Concatenation and Constant
* Variables</h2> Bad:
*
* <pre>
* String glue = &quot;some glue&quot;;
* StringUtil.concat(&quot;text 1&quot;, glue, &quot;text 2&quot;, glue, String.valueOf(npcId));
* </pre>
*
* Good:
*
* <pre>
* final String glue = &quot;some glue&quot;;
* StringUtil.concat(&quot;text 1&quot; + glue + &quot;text2&quot; + 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>. <h2>StringBuilder Reuse</h2> Bad:
*
* <pre>
* final StringBuilder sbString1 = new StringBuilder();
* StringUtil.append(sbString1, &quot;text 1&quot;, String.valueOf(npcId), &quot;text 2&quot;);
* ... // output of sbString1, it is no more needed
* final StringBuilder sbString2 = new StringBuilder();
* StringUtil.append(sbString2, &quot;text 3&quot;, String.valueOf(npcId), &quot;text 4&quot;);
* </pre>
*
* Good:
*
* <pre>
* final StringBuilder sbString = new StringBuilder();
* StringUtil.append(sbString, &quot;text 1&quot;, String.valueOf(npcId), &quot;text 2&quot;);
* ... // output of sbString, it is no more needed
* sbString.setLength(0);
* StringUtil.append(sbString, &quot;text 3&quot;, String.valueOf(npcId), &quot;text 4&quot;);
* </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(). <h2>How much faster is it?</h2> 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.
*
* <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
* @see StringUtil
*/
public static String concat(final String... strings)
{
final TextBuilder sbString = TextBuilder.newInstance();
for (final String string : strings)
{
sbString.append(string);
}
String result = sbString.toString();
TextBuilder.recycle(sbString);
return result;
}
/**
* 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
* @see StringUtil
*/
public static StringBuilder startAppend(final int sizeHint, final String... strings)
{
final int length = getLength(strings);
final StringBuilder sbString = new StringBuilder(sizeHint > length ? sizeHint : length);
for (final String string : strings)
{
sbString.append(string);
}
return sbString;
}
/**
* Appends strings to existing string builder.
* @param sbString string builder
* @param strings strings to be appended
* @see StringUtil
*/
public static void append(final StringBuilder sbString, final String... strings)
{
sbString.ensureCapacity(sbString.length() + getLength(strings));
for (final String string : strings)
{
sbString.append(string);
}
}
/**
* Counts total length of all the strings.
* @param strings array of strings
* @return total length of all the strings
*/
private static int getLength(final String[] strings)
{
int length = 0;
for (final String string : strings)
{
if (string == null)
{
length += 4;
}
else
{
length += string.length();
}
}
return length;
}
public static String getTraceString(StackTraceElement[] trace)
{
final TextBuilder sbString = TextBuilder.newInstance();
for (final StackTraceElement element : trace)
{
sbString.append(element.toString()).append("\n");
}
String result = sbString.toString();
TextBuilder.recycle(sbString);
return result;
}
}
@@ -0,0 +1,160 @@
/*
* $Header: Util.java, 14-Jul-2005 03:27:51 luisantonioa Exp $
*
* $Author: luisantonioa $ $Date: 14-Jul-2005 03:27:51 $ $Revision: 1 $ $Log:
* Util.java,v $ Revision 1 14-Jul-2005 03:27:51 luisantonioa Added copyright
* notice
*
*
* 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.l2jserver.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
public class Util
{
public static boolean isInternalIP(String ipAddress)
{
java.net.InetAddress addr = null;
try
{
addr = java.net.InetAddress.getByName(ipAddress);
return addr.isSiteLocalAddress() || addr.isLoopbackAddress();
}
catch (UnknownHostException e)
{
e.printStackTrace();
}
return false;
}
public static String printData(byte[] data, int len)
{
final StringBuilder result = new StringBuilder(len * 4);
int counter = 0;
for (int i = 0; i < len; i++)
{
if ((counter % 16) == 0)
{
result.append(fillHex(i, 4) + ": ");
}
result.append(fillHex(data[i] & 0xff, 2) + " ");
counter++;
if (counter == 16)
{
result.append(" ");
int charpoint = i - 15;
for (int a = 0; a < 16; a++)
{
int t1 = 0xFF & data[charpoint++];
if ((t1 > 0x1f) && (t1 < 0x80))
{
result.append((char) t1);
}
else
{
result.append('.');
}
}
result.append("\n");
counter = 0;
}
}
int rest = data.length % 16;
if (rest > 0)
{
for (int i = 0; i < (17 - rest); i++)
{
result.append(" ");
}
int charpoint = data.length - rest;
for (int a = 0; a < rest; a++)
{
int t1 = 0xFF & data[charpoint++];
if ((t1 > 0x1f) && (t1 < 0x80))
{
result.append((char) t1);
}
else
{
result.append('.');
}
}
result.append("\n");
}
return result.toString();
}
public static String fillHex(int data, int digits)
{
String number = Integer.toHexString(data);
for (int i = number.length(); i < digits; i++)
{
number = "0" + number;
}
return number;
}
/**
* @param raw
* @return
*/
public static String printData(byte[] raw)
{
return printData(raw, raw.length);
}
public static String printData(ByteBuffer buf)
{
byte[] data = new byte[buf.remaining()];
buf.get(data);
String hex = Util.printData(data, data.length);
buf.position(buf.position() - data.length);
return hex;
}
public static byte[] generateHex(int size)
{
byte[] array = new byte[size];
Rnd.nextBytes(array);
return array;
}
public static String getStackTrace(Throwable t)
{
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
}
@@ -0,0 +1,133 @@
/*
* $Header: WorldObjectMap.java, 22/07/2005 14:15:11 luisantonioa Exp $
*
* $Author: luisantonioa $
* $Date: 22/07/2005 14:15:11 $
* $Revision: 1 $
* $Log: WorldObjectMap.java,v $
* Revision 1 22/07/2005 14:15:11 luisantonioa
* Added copyright notice
*
*
* 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.l2jserver.util;
import java.util.Iterator;
import java.util.Map;
import javolution.util.FastMap;
import com.l2jserver.gameserver.model.L2Object;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
public class WorldObjectMap<T extends L2Object> extends L2ObjectMap<T>
{
Map<Integer, T> _objectMap = new FastMap<Integer, T>().shared();
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#size()
*/
@Override
public int size()
{
return _objectMap.size();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#isEmpty()
*/
@Override
public boolean isEmpty()
{
return _objectMap.isEmpty();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#clear()
*/
@Override
public void clear()
{
_objectMap.clear();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#put(T)
*/
@Override
public void put(T obj)
{
if (obj != null)
{
_objectMap.put(obj.getObjectId(), obj);
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#remove(T)
*/
@Override
public void remove(T obj)
{
if (obj != null)
{
_objectMap.remove(obj.getObjectId());
}
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#get(int)
*/
@Override
public T get(int id)
{
return _objectMap.get(id);
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#contains(T)
*/
@Override
public boolean contains(T obj)
{
if (obj == null)
{
return false;
}
return _objectMap.get(obj.getObjectId()) != null;
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectMap#iterator()
*/
@Override
public Iterator<T> iterator()
{
return _objectMap.values().iterator();
}
}
@@ -0,0 +1,118 @@
/*
* $Header: WorldObjectSet.java, 22/07/2005 14:11:29 luisantonioa Exp $
*
* $Author: luisantonioa $
* $Date: 22/07/2005 14:11:29 $
* $Revision: 1 $
* $Log: WorldObjectSet.java,v $
* Revision 1 22/07/2005 14:11:29 luisantonioa
* Added copyright notice
*
*
* 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.l2jserver.util;
import java.util.Iterator;
import java.util.Map;
import javolution.util.FastMap;
import com.l2jserver.gameserver.model.L2Object;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
*/
public class WorldObjectSet<T extends L2Object> extends L2ObjectSet<T>
{
private final Map<Integer, T> _objectMap;
public WorldObjectSet()
{
_objectMap = new FastMap<Integer, T>().shared();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#size()
*/
@Override
public int size()
{
return _objectMap.size();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#isEmpty()
*/
@Override
public boolean isEmpty()
{
return _objectMap.isEmpty();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#clear()
*/
@Override
public void clear()
{
_objectMap.clear();
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#put(T)
*/
@Override
public void put(T obj)
{
_objectMap.put(obj.getObjectId(), obj);
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#remove(T)
*/
@Override
public void remove(T obj)
{
_objectMap.remove(obj.getObjectId());
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#contains(T)
*/
@Override
public boolean contains(T obj)
{
return _objectMap.containsKey(obj.getObjectId());
}
/*
* (non-Javadoc)
* @see com.l2jserver.util.L2ObjectSet#iterator()
*/
@Override
public Iterator<T> iterator()
{
return _objectMap.values().iterator();
}
}
@@ -0,0 +1,180 @@
/*
* 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.l2jserver.util;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.l2jserver.gameserver.model.L2Object;
/**
* @author dishkols
*/
public class WorldObjectTree<T extends L2Object> extends L2ObjectMap<T>
{
private final TreeMap<Integer, T> _objectMap = new TreeMap<>();
private final ReentrantReadWriteLock _rwl = new ReentrantReadWriteLock();
private final Lock _r = _rwl.readLock();
private final Lock _w = _rwl.writeLock();
/**
* @see com.l2jserver.util.L2ObjectMap#size()
*/
@Override
public int size()
{
_r.lock();
try
{
return _objectMap.size();
}
finally
{
_r.unlock();
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#isEmpty()
*/
@Override
public boolean isEmpty()
{
_r.lock();
try
{
return _objectMap.isEmpty();
}
finally
{
_r.unlock();
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#clear()
*/
@Override
public void clear()
{
_w.lock();
try
{
_objectMap.clear();
}
finally
{
_w.unlock();
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#put(T)
*/
@Override
public void put(T obj)
{
if (obj != null)
{
_w.lock();
try
{
_objectMap.put(obj.getObjectId(), obj);
}
finally
{
_w.unlock();
}
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#remove(T)
*/
@Override
public void remove(T obj)
{
if (obj != null)
{
_w.lock();
try
{
_objectMap.remove(obj.getObjectId());
}
finally
{
_w.unlock();
}
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#get(int)
*/
@Override
public T get(int id)
{
_r.lock();
try
{
return _objectMap.get(id);
}
finally
{
_r.unlock();
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#contains(T)
*/
@Override
public boolean contains(T obj)
{
if (obj == null)
{
return false;
}
_r.lock();
try
{
return _objectMap.containsValue(obj);
}
finally
{
_r.unlock();
}
}
/**
* @see com.l2jserver.util.L2ObjectMap#iterator()
*/
@Override
public Iterator<T> iterator()
{
_r.lock();
try
{
return _objectMap.values().iterator();
}
finally
{
_r.unlock();
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
/*
* 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.l2jserver.util.crypt;
import java.io.IOException;
import com.l2jserver.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 final NewCrypt _staticCrypt = new NewCrypt(STATIC_BLOWFISH_KEY);
private NewCrypt _crypt;
private boolean _static = true;
public void setKey(byte[] key)
{
_crypt = new NewCrypt(key);
}
public boolean decrypt(byte[] raw, final int offset, final int size) throws IOException
{
_crypt.decrypt(raw, offset, size);
return NewCrypt.verifyChecksum(raw, offset, size);
}
public int encrypt(byte[] raw, final int offset, int size) throws IOException
{
// reserve checksum
size += 4;
if (_static)
{
// reserve for XOR "key"
size += 4;
// padding
size += 8 - (size % 8);
NewCrypt.encXORPass(raw, offset, size, Rnd.nextInt());
_staticCrypt.crypt(raw, offset, size);
_static = false;
}
else
{
// padding
size += 8 - (size % 8);
NewCrypt.appendChecksum(raw, offset, size);
_crypt.crypt(raw, offset, size);
}
return size;
}
}
@@ -0,0 +1,213 @@
/*
* 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.l2jserver.util.crypt;
import java.io.IOException;
import java.util.logging.Logger;
/**
* This class ...
* @version $Revision: 1.3.4.1 $ $Date: 2005/03/27 15:30:09 $
*/
public class NewCrypt
{
protected static Logger _log = Logger.getLogger(NewCrypt.class.getName());
BlowfishEngine _crypt;
BlowfishEngine _decrypt;
/**
* @param blowfishKey
*/
public NewCrypt(byte[] blowfishKey)
{
_crypt = new BlowfishEngine();
_crypt.init(true, blowfishKey);
_decrypt = new BlowfishEngine();
_decrypt.init(false, blowfishKey);
}
public NewCrypt(String key)
{
this(key.getBytes());
}
public static boolean verifyChecksum(byte[] raw)
{
return NewCrypt.verifyChecksum(raw, 0, raw.length);
}
public static boolean verifyChecksum(byte[] raw, final int offset, final 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;
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;
}
public static void appendChecksum(byte[] raw)
{
NewCrypt.appendChecksum(raw, 0, raw.length);
}
public static void appendChecksum(byte[] raw, final int offset, final int size)
{
long chksum = 0;
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". 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". 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 begining of the data to be encrypted
* @param size Length of the data to be encrypted
* @param key The 4 bytes (int) XOR key
*/
public static void encXORPass(byte[] raw, final int offset, final int size, int key)
{
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);
}
public byte[] decrypt(byte[] raw) throws IOException
{
byte[] result = new byte[raw.length];
int count = raw.length / 8;
for (int i = 0; i < count; i++)
{
_decrypt.processBlock(raw, i * 8, result, i * 8);
}
return result;
}
public void decrypt(byte[] raw, final int offset, final int size) throws IOException
{
byte[] result = new byte[size];
int count = size / 8;
for (int i = 0; i < count; i++)
{
_decrypt.processBlock(raw, offset + (i * 8), result, i * 8);
}
// TODO can the crypt and decrypt go direct to the array
System.arraycopy(result, 0, raw, offset, size);
}
public byte[] crypt(byte[] raw) throws IOException
{
int count = raw.length / 8;
byte[] result = new byte[raw.length];
for (int i = 0; i < count; i++)
{
_crypt.processBlock(raw, i * 8, result, i * 8);
}
return result;
}
public void crypt(byte[] raw, final int offset, final int size) throws IOException
{
int count = size / 8;
byte[] result = new byte[size];
for (int i = 0; i < count; i++)
{
_crypt.processBlock(raw, offset + (i * 8), result, i * 8);
}
// TODO can the crypt and decrypt go direct to the array
System.arraycopy(result, 0, raw, offset, size);
}
}
@@ -0,0 +1,73 @@
/*
* 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.l2jserver.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))
{
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++)
{
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,71 @@
/*
* 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/>.
*/
/**
coded by Balancer
balancer@balancer.ru
http://balancer.ru
version 0.1, 2005-06-06
*/
package com.l2jserver.util.lib;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Log
{
private static final Logger _log = Logger.getLogger(Log.class.getName());
public static final void add(String text, String cat)
{
/*
* Logger _log = logs.get(cat); if(_log == null) { _log = Logger.getLogger(cat); logs.put(cat, _log); }
*/
String date = (new SimpleDateFormat("yy.MM.dd H:mm:ss")).format(new Date());
String curr = (new SimpleDateFormat("yyyy-MM-dd-")).format(new Date());
new File("log/game").mkdirs();
FileWriter save = null;
try
{
File file = new File("log/game/" + (curr != null ? curr : "") + (cat != null ? cat : "unk") + ".txt");
save = new FileWriter(file, true);
String out = "[" + date + "] " + text + "\n";
save.write(out);
}
catch (IOException e)
{
_log.log(Level.WARNING, "Error saving logfile: ", e);
}
finally
{
try
{
save.close();
}
catch (Exception e)
{
}
}
}
}
@@ -0,0 +1,190 @@
/*
* 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.l2jserver.util.lib;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jserver.L2DatabaseFactory;
public class SqlUtils
{
private static Logger _log = Logger.getLogger(SqlUtils.class.getName());
private SqlUtils()
{
}
// =========================================================
// Property - Public
public static SqlUtils getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Method - Public
public static Integer getIntValue(String resultField, String tableName, String whereClause)
{
String query = "";
Integer res = null;
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[]
{
resultField
}, tableName, whereClause, true);
PreparedStatement statement = con.prepareStatement(query);
ResultSet rset = statement.executeQuery();
if (rset.next())
{
res = rset.getInt(1);
}
rset.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error in query '" + query + "':", e);
}
finally
{
L2DatabaseFactory.close(con);
}
return res;
}
public static Integer[] getIntArray(String resultField, String tableName, String whereClause)
{
String query = "";
Integer[] res = null;
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[]
{
resultField
}, tableName, whereClause, false);
PreparedStatement statement = con.prepareStatement(query);
ResultSet rset = statement.executeQuery();
int rows = 0;
while (rset.next())
{
rows++;
}
if (rows == 0)
{
return new Integer[0];
}
res = new Integer[rows - 1];
rset.first();
int row = 0;
while (rset.next())
{
res[row] = rset.getInt(1);
}
rset.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "mSGI: Error in query '" + query + "':", e);
}
finally
{
L2DatabaseFactory.close(con);
}
return res;
}
public static Integer[][] get2DIntArray(String[] resultFields, String usedTables, String whereClause)
{
long start = System.currentTimeMillis();
String query = "";
Connection con = null;
Integer res[][] = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
query = L2DatabaseFactory.getInstance().prepQuerySelect(resultFields, usedTables, whereClause, false);
PreparedStatement statement = con.prepareStatement(query);
ResultSet rset = statement.executeQuery();
int rows = 0;
while (rset.next())
{
rows++;
}
res = new Integer[rows - 1][resultFields.length];
rset.first();
int row = 0;
while (rset.next())
{
for (int i = 0; i < resultFields.length; i++)
{
res[row][i] = rset.getInt(i + 1);
}
row++;
}
rset.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error in query '" + query + "':", e);
}
finally
{
L2DatabaseFactory.close(con);
}
_log.fine("Get all rows in query '" + query + "' in " + (System.currentTimeMillis() - start) + "ms");
return res;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final SqlUtils _instance = new SqlUtils();
}
}
@@ -0,0 +1,106 @@
/*
* 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.l2jserver.util.network;
/**
* This class ...
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:12 $
*/
public abstract class BaseRecievePacket
{
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()
{
int result = _decrypt[_off++] & 0xff;
return result;
}
public int readH()
{
int result = _decrypt[_off++] & 0xff;
result |= (_decrypt[_off++] << 8) & 0xff00;
return result;
}
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));
}
catch (Exception e)
{
e.printStackTrace();
}
_off += (result.length() * 2) + 2;
return result;
}
public final byte[] readB(int length)
{
byte[] result = new byte[length];
for (int i = 0; i < length; i++)
{
result[i] = _decrypt[_off + i];
}
_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,132 @@
/*
* 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.l2jserver.util.network;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* This class ...
* @version $Revision: 1.2.4.1 $ $Date: 2005/03/27 15:30:11 $
*/
public abstract class BaseSendablePacket
{
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)
{
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)
{
e.printStackTrace();
}
_bao.write(0);
_bao.write(0);
}
protected void writeB(byte[] array)
{
try
{
_bao.write(array);
}
catch (IOException e)
{
e.printStackTrace();
}
}
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
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;
}