Chronicle 4 branch.

This commit is contained in:
MobiusDev
2017-07-19 21:24:06 +00:00
parent 9a69bec286
commit 3a0bf3539a
13496 changed files with 641683 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.Announcements;
import com.l2jmobius.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;
// JDK 1.5 only supports the findMonitorDeadlockedThreads()
// method, so you need to comment out the following three lines
if (tmx.isSynchronizerUsageSupported())
{
ids = tmx.findDeadlockedThreads();
}
else
{
ids = tmx.findMonitorDeadlockedThreads();
}
if (ids != null)
{
deadlock = true;
final ThreadInfo[] tis = tmx.getThreadInfo(ids, true, true);
String info = "DeadLock Found!\n";
for (final ThreadInfo ti : tis)
{
info += ti.toString();
}
for (final ThreadInfo ti : tis)
{
final LockInfo[] locks = ti.getLockedSynchronizers();
final MonitorInfo[] monitors = ti.getLockedMonitors();
if ((locks.length == 0) && (monitors.length == 0))
{
continue;
}
ThreadInfo dl = ti;
info += "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)
{
final Announcements an = Announcements.getInstance();
an.announceToAll("Server has stability issues - restarting now.");
Shutdown.getInstance().startTelnetShutdown("DeadLockDetector - Auto Restart", 60, true);
}
}
Thread.sleep(_sleepTime);
}
catch (final Exception e)
{
_log.log(Level.WARNING, "DeadLockDetector: ", e);
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.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;
}
}

View File

@@ -0,0 +1,146 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.net.InetAddress;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import org.mmocore.network.IAcceptFilter;
/**
* Formatted Forsaiken's IPv4Filter [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<>();
final Thread t = new Thread(this);
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)
{
final InetAddress addr = sc.socket().getInetAddress();
final int h = hash(addr.getAddress());
final long current = System.currentTimeMillis();
Flood f;
synchronized (_ipFloodMap)
{
f = _ipFloodMap.get(h);
}
if (f != null)
{
if (f.trys == -1)
{
f.lastAccess = current;
return false;
}
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)
{
final long reference = System.currentTimeMillis() - (1000 * 300);
synchronized (_ipFloodMap)
{
final Iterator<Entry<Integer, Flood>> it = _ipFloodMap.entrySet().iterator();
while (it.hasNext())
{
final Flood f = it.next().getValue();
if (f.lastAccess < reference)
{
it.remove();
}
}
}
try
{
Thread.sleep(SLEEP_TIME);
}
catch (final InterruptedException e)
{
}
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
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>
* @param <T>
*/
public class L2FastList<T extends Object>extends FastList<T>
{
static final long serialVersionUID = 1L;
/**
* Public inner interface used by ForEach iterations<br>
* @author Julian
* @param <T>
*/
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 (final T e : this)
{
if (!func.ForEach(e))
{
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,529 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.l2jmobius.Config;
import com.l2jmobius.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 final boolean TRACE = false;
private 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 (final int prime : primes)
{
if (prime >= min)
{
return prime;
}
}
throw new OutOfMemoryError();
}
@SuppressWarnings("unchecked")
public L2ObjectHashMap()
{
final int size = primes[0];
table = (T[]) new L2Object[size];
keys = new int[size];
if (DEBUG)
{
check();
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#size()
*/
@Override
public int size()
{
return count;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#isEmpty()
*/
@Override
public boolean isEmpty()
{
return count == 0;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#clear()
*/
@Override
@SuppressWarnings("unchecked")
public synchronized void clear()
{
final 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++)
{
final 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.l2jmobius.util.L2ObjectMap#put(T)
*/
@Override
public synchronized void put(T obj)
{
if (count >= (table.length / 2))
{
expand();
}
final int hashcode = obj.getObjectId();
if (Config.ASSERT)
{
assert hashcode > 0;
}
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (table.length - 1));
int ntry = 0;
int slot = -1; // keep last found slot
do
{
final 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
if (Config.ASSERT)
{
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.l2jmobius.util.L2ObjectMap#remove(T)
*/
@Override
public synchronized void remove(T obj)
{
final int hashcode = obj.getObjectId();
if (Config.ASSERT)
{
assert hashcode > 0;
}
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (table.length - 1));
int ntry = 0;
do
{
final 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.l2jmobius.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;
final int incr = 1 + (((seed >> 5) + 1) % (size - 1));
int ntry = 0;
do
{
final 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.l2jmobius.util.L2ObjectMap#contains(T)
*/
@Override
public boolean contains(T obj)
{
return get(obj.getObjectId()) != null;
}
@SuppressWarnings("unchecked")
private /* already synchronized in put() */ void expand()
{
final int newSize = getPrime(table.length + 1);
final L2Object[] newTable = new L2Object[newSize];
final int[] newKeys = new int[newSize];
// over all old entries
next_entry: for (int i = 0; i < table.length; i++)
{
final L2Object obj = table[i];
if (obj == null)
{
continue;
}
final int hashcode = keys[i] & 0x7FFFFFFF;
if (Config.ASSERT)
{
assert hashcode == obj.getObjectId();
}
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (newSize - 1));
int ntry = 0;
do
{
final int pos = (seed % newSize) & 0x7FFFFFFF;
if (newTable[pos] == null)
{
if (Config.ASSERT)
{
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.l2jmobius.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);
}
}
}

View File

@@ -0,0 +1,519 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.l2jmobius.Config;
import com.l2jmobius.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 final boolean TRACE = false;
private 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 (final int prime : primes)
{
if (prime >= min)
{
return prime;
}
}
throw new OutOfMemoryError();
}
@SuppressWarnings("unchecked")
public L2ObjectHashSet()
{
final int size = primes[0];
table = (T[]) new L2Object[size];
collisions = new int[(size + 31) >> 5];
if (DEBUG)
{
check();
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#size()
*/
@Override
public int size()
{
return count;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#isEmpty()
*/
@Override
public boolean isEmpty()
{
return count == 0;
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#clear()
*/
@Override
@SuppressWarnings("unchecked")
public synchronized void clear()
{
final 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 (final T obj : table)
{
if (obj != null)
{
cnt++;
}
}
assert cnt == count;
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.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();
if (Config.ASSERT)
{
assert hashcode > 0;
}
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (table.length - 1));
int ntry = 0;
int slot = -1; // keep last found slot
do
{
final 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
if (Config.ASSERT)
{
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.l2jmobius.util.L2ObjectSet#remove(T)
*/
@Override
public synchronized void remove(T obj)
{
if (obj == null)
{
return;
}
if (!contains(obj))
{
return;
}
final int hashcode = obj.getObjectId();
if (Config.ASSERT)
{
assert hashcode > 0;
}
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (table.length - 1));
int ntry = 0;
do
{
final 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.l2jmobius.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;
}
final int hashcode = obj.getObjectId();
if (Config.ASSERT)
{
assert hashcode > 0;
}
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (size - 1));
int ntry = 0;
do
{
final 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()
{
final int newSize = getPrime(table.length + 1);
final L2Object[] newTable = new L2Object[newSize];
final int[] newCollisions = new int[(newSize + 31) >> 5];
// over all old entries
next_entry: for (int i = 0; i < table.length; i++)
{
final L2Object obj = table[i];
if (obj == null)
{
continue;
}
final int hashcode = obj.getObjectId();
int seed = hashcode;
final int incr = 1 + (((seed >> 5) + 1) % (newSize - 1));
int ntry = 0;
do
{
final 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.l2jmobius.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);
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2Object;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
* @param <T>
*/
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<>();
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2PlayableInstance;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
* @param <T>
*/
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<L2PlayableInstance> 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();
}

View File

@@ -0,0 +1,102 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/*
* coded by Balancer
* balancer@balancer.ru
* http://balancer.ru
*
* version 0.1, 2005-06-06
*/
public class Log
{
private static final Logger _log = Logger.getLogger(Log.class.getName());
public static final void add(String text, String cat)
{
final String date = (new SimpleDateFormat("yy.MM.dd H:mm:ss")).format(new Date());
new File("log/game").mkdirs();
File file = new File("log/game/" + (cat != null ? cat : "_all") + ".txt");
try (FileWriter save = new FileWriter(file, true))
{
final String out = "[" + date + "] '---': " + text + "\n";
save.write(out);
save.flush();
file = null;
}
catch (final IOException e)
{
_log.warning("saving chat log failed: " + e);
e.printStackTrace();
}
if (cat != null)
{
add(text, null);
}
}
public static final void addEvent(L2PcInstance pc, String text)
{
final String date = (new SimpleDateFormat("yy.MM.dd H:mm:ss")).format(new Date());
final String filedate = (new SimpleDateFormat("yyMMdd_H")).format(new Date());
new File("log/game").mkdirs();
final File file = new File("log/game/actions_" + filedate + ".txt");
try (FileWriter save = new FileWriter(file, true))
{
final String out = "[" + date + "] '<" + pc.getName() + ">': " + text + "\n"; // "+char_name()+"
save.write(out);
}
catch (final IOException e)
{
_log.warning("saving actions log failed: " + e);
e.printStackTrace();
}
}
public static final void Assert(boolean exp)
{
Assert(exp, "");
}
public static final void Assert(boolean exp, String cmt)
{
if (exp || !Config.ASSERT)
{
return;
}
System.out.println("Assertion error [" + cmt + "]");
Thread.dumpStack();
}
}

View File

@@ -0,0 +1,170 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.io.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;
public 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)
{
final 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;
}
}

View File

@@ -0,0 +1,345 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Arrays;
/*
* 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 largestPrime = 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[] primeCapacities =
{
// chunk #0
largestPrime,
// 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(primeCapacities);
}
/**
* 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(primeCapacities, desiredCapacity);
if (i < 0)
{
// desired capacity not found, choose next prime greater
// than desired capacity
i = -i - 1; // remember the semantics of binarySearch...
}
return primeCapacities[i];
}
}

View File

@@ -0,0 +1,446 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.security.SecureRandom;
import java.util.Random;
/**
* @author Forsaiken
*/
public final class Rnd
{
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using a simple volatile flag to ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is much faster on parallel access, but may generate the same seed for 2 threads.
* @author Forsaiken
* @see java.util.Random
*/
public static final class NonAtomicRandom extends Random
{
private 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 synchronized 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.l2jmobius.util.Rnd#nextDouble()
*/
public final double get()
{
return _random.nextDouble();
}
/**
* Gets a random integer number from 0(inclusive) to n(exclusive)
* @param n The superior limit (exclusive)
* @return A random integer number from 0 to n-1
*/
public final int get(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.l2jmobius.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Each thread has it`s own random instance.<br>
* Provides best parallel access speed.
* @see com.l2jmobius.util.Rnd.ThreadLocalRandom
*/
UNSECURE_THREAD_LOCAL,
/**
* Like {@link com.l2jmobius.util.Rnd.RandomType#UNSECURE_ATOMIC}.<br>
* Provides much faster parallel access speed.
* @see com.l2jmobius.util.Rnd.NonAtomicRandom
*/
UNSECURE_VOLATILE
}
/**
* This class extends {@link java.util.Random} but do not compare and store atomically.<br>
* Instead it`s using thread local ensure reading and storing the whole 64bit seed chunk.<br>
* This implementation is the fastest, never generates the same seed for 2 threads.<br>
* Each thread has it`s own random instance.
* @author Forsaiken
* @see java.util.Random
*/
public static final class ThreadLocalRandom extends Random
{
private static final class Seed
{
long _seed;
Seed(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 synchronized 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.l2jmobius.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();
}
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();
}
}

View File

@@ -0,0 +1,166 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Logger;
import com.l2jmobius.L2DatabaseFactory;
public class SqlUtils
{
private static Logger _log = Logger.getLogger(SqlUtils.class.getName());
// =========================================================
// Data Field
private static SqlUtils _instance;
// =========================================================
// Property - Public
public static SqlUtils getInstance()
{
if (_instance == null)
{
_instance = new SqlUtils();
}
return _instance;
}
// =========================================================
// Method - Public
public static Integer getIntValue(String resultField, String tableName, String whereClause)
{
Integer res = null;
String query = "";
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[]
{
resultField
}, tableName, whereClause, true);
try (PreparedStatement statement = con.prepareStatement(query);
ResultSet rset = statement.executeQuery())
{
if (rset.next())
{
res = rset.getInt(1);
}
}
}
catch (final Exception e)
{
_log.warning("Error in query '" + query + "':" + e);
e.printStackTrace();
}
return res;
}
public static Integer[] getIntArray(String resultField, String tableName, String whereClause)
{
Integer[] res = null;
String query = "";
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
query = L2DatabaseFactory.getInstance().prepQuerySelect(new String[]
{
resultField
}, tableName, whereClause, false);
try (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();
final int row = 0;
while (rset.next())
{
res[row] = rset.getInt(1);
}
}
}
catch (final Exception e)
{
_log.warning("mSGI: Error in query '" + query + "':" + e);
e.printStackTrace();
}
return res;
}
public static Integer[][] get2DIntArray(String[] resultFields, String usedTables, String whereClause)
{
final long start = System.currentTimeMillis();
Integer res[][] = null;
String query = "";
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
query = L2DatabaseFactory.getInstance().prepQuerySelect(resultFields, usedTables, whereClause, false);
try (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++;
}
}
}
catch (final Exception e)
{
_log.warning("Error in query '" + query + "':" + e);
e.printStackTrace();
}
_log.fine("Get all rows in query '" + query + "' in " + (System.currentTimeMillis() - start) + "ms");
return res;
}
}

View File

@@ -0,0 +1,256 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
/**
* 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 StringBuilder sbString = new StringBuilder(getLength(strings));
for (final String string : strings)
{
sbString.append(string);
}
return sbString.toString();
}
/**
* Creates new string builder with size initializated to <code>sizeHint</code>, unless total length of strings is greater than <code>sizeHint</code>.
* @param sizeHint hint for string builder size allocation
* @param strings strings to be appended
* @return created string builder
* @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;
}
}

View File

@@ -0,0 +1,130 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.net.UnknownHostException;
import javolution.text.TextBuilder;
/**
* 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 (final UnknownHostException e)
{
e.printStackTrace();
}
return false;
}
public static String printData(byte[] data, int len)
{
final TextBuilder result = new TextBuilder();
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++)
{
final int t1 = data[charpoint++];
if ((t1 > 0x1f) && (t1 < 0x80))
{
result.append((char) t1);
}
else
{
result.append('.');
}
}
result.append("\n");
counter = 0;
}
}
final 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++)
{
final int t1 = 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);
}
}

View File

@@ -0,0 +1,125 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import java.util.Map;
import com.l2jmobius.gameserver.model.L2Object;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
* @param <T>
*/
public class WorldObjectMap<T extends L2Object>extends L2ObjectMap<T>
{
Map<Integer, T> objectMap = new FastMap<Integer, T>().shared();
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#size()
*/
@Override
public int size()
{
return objectMap.size();
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#isEmpty()
*/
@Override
public boolean isEmpty()
{
return objectMap.isEmpty();
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#clear()
*/
@Override
public void clear()
{
objectMap.clear();
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#put(T)
*/
@Override
public void put(T obj)
{
if (obj != null)
{
objectMap.put(obj.getObjectId(), obj);
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#remove(T)
*/
@Override
public void remove(T obj)
{
if (obj != null)
{
objectMap.remove(obj.getObjectId());
}
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectMap#get(int)
*/
@Override
public T get(int id)
{
return objectMap.get(id);
}
/*
* (non-Javadoc)
* @see com.l2jmobius.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.l2jmobius.util.L2ObjectMap#iterator()
*/
@Override
public Iterator<T> iterator()
{
return objectMap.values().iterator();
}
}

View File

@@ -0,0 +1,110 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import java.util.Map;
import com.l2jmobius.gameserver.model.L2Object;
import javolution.util.FastMap;
/**
* This class ...
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
* @param <T>
*/
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.l2jmobius.util.L2ObjectSet#size()
*/
@Override
public int size()
{
return objectMap.size();
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#isEmpty()
*/
@Override
public boolean isEmpty()
{
return objectMap.isEmpty();
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#clear()
*/
@Override
public void clear()
{
objectMap.clear();
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#put(T)
*/
@Override
public void put(T obj)
{
objectMap.put(obj.getObjectId(), obj);
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#remove(T)
*/
@Override
public void remove(T obj)
{
objectMap.remove(obj.getObjectId());
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#contains(T)
*/
@Override
public boolean contains(T obj)
{
return objectMap.containsKey(obj.getObjectId());
}
/*
* (non-Javadoc)
* @see com.l2jmobius.util.L2ObjectSet#iterator()
*/
@Override
public Iterator<T> iterator()
{
return objectMap.values().iterator();
}
}

View File

@@ -0,0 +1,173 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.l2jmobius.gameserver.model.L2Object;
/**
* @author dishkols
* @param <T>
*/
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.l2jmobius.util.L2ObjectMap#size()
*/
@Override
public int size()
{
r.lock();
try
{
return objectMap.size();
}
finally
{
r.unlock();
}
}
/**
* @see com.l2jmobius.util.L2ObjectMap#isEmpty()
*/
@Override
public boolean isEmpty()
{
r.lock();
try
{
return objectMap.isEmpty();
}
finally
{
r.unlock();
}
}
/**
* @see com.l2jmobius.util.L2ObjectMap#clear()
*/
@Override
public void clear()
{
w.lock();
try
{
objectMap.clear();
}
finally
{
w.unlock();
}
}
@Override
public void put(T obj)
{
if (obj != null)
{
w.lock();
try
{
objectMap.put(obj.getObjectId(), obj);
}
finally
{
w.unlock();
}
}
}
@Override
public void remove(T obj)
{
if (obj != null)
{
w.lock();
try
{
objectMap.remove(obj.getObjectId());
}
finally
{
w.unlock();
}
}
}
/**
* @see com.l2jmobius.util.L2ObjectMap#get(int)
*/
@Override
public T get(int id)
{
r.lock();
try
{
return objectMap.get(id);
}
finally
{
r.unlock();
}
}
@Override
public boolean contains(T obj)
{
if (obj == null)
{
return false;
}
r.lock();
try
{
return objectMap.containsValue(obj);
}
finally
{
r.unlock();
}
}
/**
* @see com.l2jmobius.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

View File

@@ -0,0 +1,218 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util.crypt;
/**
* Class to use a blowfish cipher with ECB processing.<br>
* Static methods are present to append/check the checksum of<br>
* packets exchanged between the following partners:<br>
* Login Server <-> Game Client<br>
* Login Server <-> Game Server<br>
* Also a static method is provided for the initial xor encryption between Login Server <-> Game Client.
*/
public final class NewCrypt
{
private final BlowfishEngine _cipher;
/**
* @param blowfishKey
*/
public NewCrypt(byte[] blowfishKey)
{
_cipher = new BlowfishEngine();
_cipher.init(blowfishKey);
}
public NewCrypt(String key)
{
this(key.getBytes());
}
/**
* Equivalent to calling {@link #verifyChecksum(byte[], int, int)} with parameters (raw, 0, raw.length)
* @param raw data array to be verified
* @return true when the checksum of the data is valid, false otherwise
*/
public static boolean verifyChecksum(byte[] raw)
{
return NewCrypt.verifyChecksum(raw, 0, raw.length);
}
/**
* Method to verify the checksum of a packet received by login server from game client.<br>
* This is also used for game server <-> login server communication.
* @param raw data array to be verified
* @param offset at which offset to start verifying
* @param size number of bytes to verify
* @return true if the checksum of the data is valid, false otherwise
*/
public static boolean verifyChecksum(byte[] raw, int offset, int size)
{
// check if size is multiple of 4 and if there is more then only the checksum
if (((size & 3) != 0) || (size <= 4))
{
return false;
}
long chksum = 0;
final int count = size - 4;
long check = -1;
int i;
for (i = offset; i < count; i += 4)
{
check = raw[i] & 0xff;
check |= (raw[i + 1] << 8) & 0xff00;
check |= (raw[i + 2] << 0x10) & 0xff0000;
check |= (raw[i + 3] << 0x18) & 0xff000000;
chksum ^= check;
}
check = raw[i] & 0xff;
check |= (raw[i + 1] << 8) & 0xff00;
check |= (raw[i + 2] << 0x10) & 0xff0000;
check |= (raw[i + 3] << 0x18) & 0xff000000;
return check == chksum;
}
/**
* Equivalent to calling {@link #appendChecksum(byte[], int, int)} with parameters (raw, 0, raw.length)
* @param raw data array to compute the checksum from
*/
public static void appendChecksum(byte[] raw)
{
NewCrypt.appendChecksum(raw, 0, raw.length);
}
/**
* Method to append packet checksum at the end of the packet.
* @param raw data array to compute the checksum from
* @param offset offset where to start in the data array
* @param size number of bytes to compute the checksum from
*/
public static void appendChecksum(byte[] raw, int offset, int size)
{
long chksum = 0;
final int count = size - 4;
long ecx;
int i;
for (i = offset; i < count; i += 4)
{
ecx = raw[i] & 0xff;
ecx |= (raw[i + 1] << 8) & 0xff00;
ecx |= (raw[i + 2] << 0x10) & 0xff0000;
ecx |= (raw[i + 3] << 0x18) & 0xff000000;
chksum ^= ecx;
}
ecx = raw[i] & 0xff;
ecx |= (raw[i + 1] << 8) & 0xff00;
ecx |= (raw[i + 2] << 0x10) & 0xff0000;
ecx |= (raw[i + 3] << 0x18) & 0xff000000;
raw[i] = (byte) (chksum & 0xff);
raw[i + 1] = (byte) ((chksum >> 0x08) & 0xff);
raw[i + 2] = (byte) ((chksum >> 0x10) & 0xff);
raw[i + 3] = (byte) ((chksum >> 0x18) & 0xff);
}
/**
* Packet is first XOR encoded with <code>key</code> then, the last 4 bytes are overwritten with the the XOR "key".<br>
* Thus this assume that there is enough room for the key to fit without overwriting data.
* @param raw The raw bytes to be encrypted
* @param key The 4 bytes (int) XOR key
*/
public static void encXORPass(byte[] raw, int key)
{
NewCrypt.encXORPass(raw, 0, raw.length, key);
}
/**
* Packet is first XOR encoded with <code>key</code> then, the last 4 bytes are overwritten with the the XOR "key".<br>
* Thus this assume that there is enough room for the key to fit without overwriting data.
* @param raw The raw bytes to be encrypted
* @param offset The beginning of the data to be encrypted
* @param size Length of the data to be encrypted
* @param key The 4 bytes (int) XOR key
*/
static void encXORPass(byte[] raw, int offset, int size, int key)
{
final int stop = size - 8;
int pos = 4 + offset;
int edx;
int ecx = key; // Initial xor key
while (pos < stop)
{
edx = raw[pos] & 0xFF;
edx |= (raw[pos + 1] & 0xFF) << 8;
edx |= (raw[pos + 2] & 0xFF) << 16;
edx |= (raw[pos + 3] & 0xFF) << 24;
ecx += edx;
edx ^= ecx;
raw[pos++] = (byte) (edx & 0xFF);
raw[pos++] = (byte) ((edx >> 8) & 0xFF);
raw[pos++] = (byte) ((edx >> 16) & 0xFF);
raw[pos++] = (byte) ((edx >> 24) & 0xFF);
}
raw[pos++] = (byte) (ecx & 0xFF);
raw[pos++] = (byte) ((ecx >> 8) & 0xFF);
raw[pos++] = (byte) ((ecx >> 16) & 0xFF);
raw[pos++] = (byte) ((ecx >> 24) & 0xFF);
}
/**
* Method to decrypt using Blowfish-Blockcipher in ECB mode.<br>
* The results will be directly placed inside {@code raw} array.<br>
* This method does not do any error checking, since the calling code<br>
* should ensure sizes.
* @param raw the data array to be decrypted
* @param offset the offset at which to start decrypting
* @param size the number of bytes to be decrypted
*/
public void decrypt(byte[] raw, int offset, int size)
{
for (int i = offset; i < (offset + size); i += 8)
{
_cipher.decryptBlock(raw, i);
}
}
/**
* Method to encrypt using Blowfish-Blockcipher in ECB mode.<br>
* The results will be directly placed inside {@code raw} array.<br>
* This method does not do any error checking, since the calling code should ensure sizes.
* @param raw the data array to be decrypted
* @param offset the offset at which to start decrypting
* @param size the number of bytes to be decrypted
*/
public void crypt(byte[] raw, int offset, int size)
{
for (int i = offset; i < (offset + size); i += 8)
{
_cipher.encryptBlock(raw, i);
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.util;
import java.util.HashMap;
import java.util.logging.Logger;
@Deprecated
public class memcache
{
private static Logger _log = Logger.getLogger(memcache.class.getName());
private final HashMap<Integer, String> _hms;
private final HashMap<Integer, Integer> _hmi;
private final HashMap<Integer, Long> _last_access;
private static final memcache _instance = new memcache();
public static memcache getInstance()
{
return _instance;
}
private memcache()
{
_hms = new HashMap<>();
_hmi = new HashMap<>();
_last_access = new HashMap<>();
}
private void check_expired()
{
for (final Integer k : _hmi.keySet())
{
if ((_last_access.get(k) + 3600000) < System.currentTimeMillis())
{
// _hmi.remove(k);
// _last_access.remove(k);
}
}
for (final Integer k : _hms.keySet())
{
if ((_last_access.get(k) + 3600000) < System.currentTimeMillis())
{
// _hms.remove(k);
// _last_access.remove(k);
}
}
}
public void set(String type, String key, int value)
{
final int hash = (type + "->" + key).hashCode();
// _log.fine("Set memcache "+type+"("+key+")["+hash+"] to "+value);
_hmi.put(hash, value);
_last_access.put(hash, System.currentTimeMillis());
check_expired();
}
public boolean is_set(String type, String key)
{
final int hash = (type + "->" + key).hashCode();
final boolean exists = _hmi.containsKey(hash) || _hms.containsKey(hash);
if (exists)
{
_last_access.put(hash, System.currentTimeMillis());
}
check_expired();
_log.fine("Check exists memcache " + type + "(" + key + ")[" + hash + "] is " + exists);
return exists;
}
public Integer get_int(String type, String key)
{
final int hash = (type + "->" + key).hashCode();
_last_access.put(hash, System.currentTimeMillis());
check_expired();
_log.fine("Get memcache " + type + "(" + key + ")[" + hash + "] = " + _hmi.get(hash));
return _hmi.get(hash);
}
}