Chronicle 4 branch.
This commit is contained in:
228
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Broadcast.java
Normal file
228
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Broadcast.java
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.model.L2Character;
|
||||
import com.l2jmobius.gameserver.model.L2World;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
import com.l2jmobius.gameserver.network.clientpackets.Say2;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.CharInfo;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
|
||||
import com.l2jmobius.gameserver.network.serverpackets.RelationChanged;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
*/
|
||||
public final class Broadcast
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(Broadcast.class.getName());
|
||||
|
||||
/**
|
||||
* Send a packet to all L2PcInstance in the _KnownPlayers of the L2Character that have the Character targetted.<BR>
|
||||
* <BR>
|
||||
* <B><U> Concept</U> :</B><BR>
|
||||
* L2PcInstance in the detection area of the L2Character are identified in <B>_knownPlayers</B>.<BR>
|
||||
* In order to inform other players of state modification on the L2Character, server just need to go through _knownPlayers to send Server->Client Packet<BR>
|
||||
* <BR>
|
||||
* <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packet to this L2Character (to do this use method toSelfAndKnownPlayers)</B></FONT><BR>
|
||||
* <BR>
|
||||
* @param character
|
||||
* @param mov
|
||||
*/
|
||||
public static void toPlayersTargettingMyself(L2Character character, L2GameServerPacket mov)
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.fine("players to notify:" + character.getKnownList().getKnownPlayers().size() + " packet:" + mov.getType());
|
||||
}
|
||||
|
||||
for (final L2PcInstance player : character.getKnownList().getKnownPlayers().values())
|
||||
{
|
||||
if ((player == null) || (player.getTarget() != character))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
player.sendPacket(mov);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to all L2PcInstance in the _KnownPlayers of the L2Character.<BR>
|
||||
* <BR>
|
||||
* <B><U> Concept</U> :</B><BR>
|
||||
* L2PcInstance in the detection area of the L2Character are identified in <B>_knownPlayers</B>.<BR>
|
||||
* In order to inform other players of state modification on the L2Character, server just need to go through _knownPlayers to send Server->Client Packet<BR>
|
||||
* <BR>
|
||||
* <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packet to this L2Character (to do this use method toSelfAndKnownPlayers)</B></FONT><BR>
|
||||
* <BR>
|
||||
* @param character
|
||||
* @param mov
|
||||
*/
|
||||
public static void toKnownPlayers(L2Character character, L2GameServerPacket mov)
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.fine("players to notify:" + character.getKnownList().getKnownPlayers().size() + " packet:" + mov.getType());
|
||||
}
|
||||
|
||||
for (final L2PcInstance player : character.getKnownList().getKnownPlayers().values())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
player.sendPacket(mov);
|
||||
if ((mov instanceof CharInfo) && (character instanceof L2PcInstance))
|
||||
{
|
||||
final int relation = ((L2PcInstance) character).getRelation(player);
|
||||
if ((character.getKnownList().getKnownRelations().get(player.getObjectId()) != null) && (character.getKnownList().getKnownRelations().get(player.getObjectId()) != relation))
|
||||
{
|
||||
|
||||
player.sendPacket(new RelationChanged((L2PcInstance) character, relation, player.isAutoAttackable(character)));
|
||||
|
||||
if (((L2PcInstance) character).getPet() != null)
|
||||
{
|
||||
player.sendPacket(new RelationChanged(((L2PcInstance) character).getPet(), relation, player.isAutoAttackable(character)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (final NullPointerException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to all L2PcInstance in the _KnownPlayers (in the specified radius) of the L2Character.<BR>
|
||||
* <BR>
|
||||
* <B><U> Concept</U> :</B><BR>
|
||||
* L2PcInstance in the detection area of the L2Character are identified in <B>_knownPlayers</B>.<BR>
|
||||
* In order to inform other players of state modification on the L2Character, server just needs to go through _knownPlayers to send Server->Client Packet and check the distance between the targets.<BR>
|
||||
* <BR>
|
||||
* <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packet to this L2Character (to do this use method toSelfAndKnownPlayers)</B></FONT><BR>
|
||||
* <BR>
|
||||
* @param character
|
||||
* @param mov
|
||||
* @param radius
|
||||
*/
|
||||
public static void toKnownPlayersInRadius(L2Character character, L2GameServerPacket mov, int radius)
|
||||
{
|
||||
if (radius < 0)
|
||||
{
|
||||
radius = 1500;
|
||||
}
|
||||
|
||||
for (final L2PcInstance player : character.getKnownList().getKnownPlayers().values())
|
||||
{
|
||||
if (player == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (character.isInsideRadius(player, radius, false, false))
|
||||
{
|
||||
player.sendPacket(mov);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to all L2PcInstance in the _KnownPlayers of the L2Character and to the specified character.<BR>
|
||||
* <BR>
|
||||
* <B><U> Concept</U> :</B><BR>
|
||||
* L2PcInstance in the detection area of the L2Character are identified in <B>_knownPlayers</B>.<BR>
|
||||
* In order to inform other players of state modification on the L2Character, server just need to go through _knownPlayers to send Server->Client Packet<BR>
|
||||
* <BR>
|
||||
* @param character
|
||||
* @param mov
|
||||
*/
|
||||
public static void toSelfAndKnownPlayers(L2Character character, L2GameServerPacket mov)
|
||||
{
|
||||
if (character instanceof L2PcInstance)
|
||||
{
|
||||
character.sendPacket(mov);
|
||||
}
|
||||
|
||||
toKnownPlayers(character, mov);
|
||||
}
|
||||
|
||||
// To improve performance we are comparing values of radius^2 instead of calculating sqrt all the time
|
||||
public static void toSelfAndKnownPlayersInRadius(L2Character character, L2GameServerPacket mov, long radiusSq)
|
||||
{
|
||||
if (radiusSq < 0)
|
||||
{
|
||||
radiusSq = 360000;
|
||||
}
|
||||
|
||||
if (character instanceof L2PcInstance)
|
||||
{
|
||||
character.sendPacket(mov);
|
||||
}
|
||||
|
||||
for (final L2PcInstance player : character.getKnownList().getKnownPlayers().values())
|
||||
{
|
||||
if ((player != null) && (character.getDistanceSq(player) <= radiusSq))
|
||||
{
|
||||
player.sendPacket(mov);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet to all L2PcInstance present in the world.<BR>
|
||||
* <BR>
|
||||
* <B><U> Concept</U> :</B><BR>
|
||||
* In order to inform other players of state modification on the L2Character, server just need to go through _allPlayers to send Server->Client Packet<BR>
|
||||
* <BR>
|
||||
* <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packet to this L2Character (to do this use method toSelfAndKnownPlayers)</B></FONT><BR>
|
||||
* <BR>
|
||||
* @param mov
|
||||
*/
|
||||
public static void toAllOnlinePlayers(L2GameServerPacket mov)
|
||||
{
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.fine("Players to notify: " + L2World.getInstance().getAllPlayersCount() + " (with packet " + mov.getType() + ")");
|
||||
}
|
||||
|
||||
for (final L2PcInstance onlinePlayer : L2World.getInstance().getAllPlayers())
|
||||
{
|
||||
if (onlinePlayer == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
onlinePlayer.sendPacket(mov);
|
||||
}
|
||||
}
|
||||
|
||||
public static void announceToOnlinePlayers(String text)
|
||||
{
|
||||
final CreatureSay cs = new CreatureSay(0, Say2.ANNOUNCEMENT, "", text);
|
||||
toAllOnlinePlayers(cs);
|
||||
}
|
||||
}
|
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
|
||||
/**
|
||||
* extension loader for l2j
|
||||
* @author galun
|
||||
* @version $Id: DynamicExtension.java,v 1.3 2006/05/14 17:19:39 galun Exp $
|
||||
*/
|
||||
public class DynamicExtension
|
||||
{
|
||||
private static Logger log = Logger.getLogger(DynamicExtension.class.getCanonicalName());
|
||||
private JarClassLoader classLoader;
|
||||
private Properties prop;
|
||||
private ConcurrentHashMap<String, Object> loadedExtensions;
|
||||
private static DynamicExtension instance;
|
||||
private final ConcurrentHashMap<String, ExtensionFunction> getters;
|
||||
private final ConcurrentHashMap<String, ExtensionFunction> setters;
|
||||
|
||||
/**
|
||||
* create an instance of DynamicExtension this will be done by GameServer according to the altsettings.properties
|
||||
*/
|
||||
private DynamicExtension()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
getters = new ConcurrentHashMap<>();
|
||||
setters = new ConcurrentHashMap<>();
|
||||
initExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the singleton of DynamicInstance
|
||||
* @return the singleton instance
|
||||
*/
|
||||
public static DynamicExtension getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new DynamicExtension();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* get an extension object by class name
|
||||
* @param className he class name as defined in the extension properties
|
||||
* @return the object or null if not found
|
||||
*/
|
||||
public Object getExtension(String className)
|
||||
{
|
||||
return loadedExtensions.get(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize all configured extensions
|
||||
* @return
|
||||
*/
|
||||
public String initExtensions()
|
||||
{
|
||||
prop = new Properties();
|
||||
String res = "";
|
||||
loadedExtensions = new ConcurrentHashMap<>();
|
||||
|
||||
try (FileInputStream fs = new FileInputStream(Config.EXTENSIONS_CONFIGURATION_FILE))
|
||||
{
|
||||
prop.load(fs);
|
||||
}
|
||||
catch (final FileNotFoundException ex)
|
||||
{
|
||||
log.info(ex.getMessage() + ": no extensions to load");
|
||||
}
|
||||
catch (final Exception ex)
|
||||
{
|
||||
log.log(Level.WARNING, "could not load properties", ex);
|
||||
}
|
||||
classLoader = new JarClassLoader();
|
||||
for (final Object o : prop.keySet())
|
||||
{
|
||||
final String k = (String) o;
|
||||
if (k.endsWith("Class"))
|
||||
{
|
||||
res += initExtension(prop.getProperty(k)) + "\n";
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* init a named extension
|
||||
* @param name the class name and optionally a jar file name delimited with a '@' if the jar file is not in the class path
|
||||
* @return
|
||||
*/
|
||||
public String initExtension(String name)
|
||||
{
|
||||
String className = name;
|
||||
final String[] p = name.split("@");
|
||||
String res = name + " loaded";
|
||||
if (p.length > 1)
|
||||
{
|
||||
classLoader.addJarFile(p[1]);
|
||||
className = p[0];
|
||||
}
|
||||
if (loadedExtensions.containsKey(className))
|
||||
{
|
||||
return "already loaded";
|
||||
}
|
||||
try
|
||||
{
|
||||
final Class<?> extension = Class.forName(className, true, classLoader);
|
||||
final Object obj = extension.newInstance();
|
||||
extension.getMethod("init", new Class[0]).invoke(obj, new Object[0]);
|
||||
log.info("Extension " + className + " loaded.");
|
||||
loadedExtensions.put(className, obj);
|
||||
}
|
||||
catch (final Exception ex)
|
||||
{
|
||||
log.log(Level.WARNING, name, ex);
|
||||
res = ex.toString();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new class loader which resets the cache (jar files and loaded classes) on next class loading request it will read the jar again
|
||||
*/
|
||||
protected void clearCache()
|
||||
{
|
||||
classLoader = new JarClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* call unloadExtension() for all known extensions
|
||||
* @return
|
||||
*/
|
||||
public String unloadExtensions()
|
||||
{
|
||||
String res = "";
|
||||
for (final String e : loadedExtensions.keySet())
|
||||
{
|
||||
res += unloadExtension(e) + "\n";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all loaded extensions
|
||||
* @return a String array with the class names
|
||||
*/
|
||||
public String[] getExtensions()
|
||||
{
|
||||
final String[] l = new String[loadedExtensions.size()];
|
||||
loadedExtensions.keySet().toArray(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* unload a named extension
|
||||
* @param name the class name and optionally a jar file name delimited with a '@'
|
||||
* @return
|
||||
*/
|
||||
public String unloadExtension(String name)
|
||||
{
|
||||
String className = name;
|
||||
final String[] p = name.split("@");
|
||||
if (p.length > 1)
|
||||
{
|
||||
classLoader.addJarFile(p[1]);
|
||||
className = p[0];
|
||||
}
|
||||
String res = className + " unloaded";
|
||||
try
|
||||
{
|
||||
final Object obj = loadedExtensions.get(className);
|
||||
final Class<?> extension = obj.getClass();
|
||||
loadedExtensions.remove(className);
|
||||
extension.getMethod("unload", new Class[0]).invoke(obj, new Object[0]);
|
||||
log.info("Extension " + className + " unloaded.");
|
||||
}
|
||||
catch (final Exception ex)
|
||||
{
|
||||
log.log(Level.WARNING, "could not unload " + className, ex);
|
||||
res = ex.toString();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* unloads all extensions, resets the cache and initializes all configured extensions
|
||||
*/
|
||||
public void reload()
|
||||
{
|
||||
unloadExtensions();
|
||||
clearCache();
|
||||
initExtensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* unloads a named extension, resets the cache and initializes the extension
|
||||
* @param name the class name and optionally a jar file name delimited with a '@' if the jar file is not in the class path
|
||||
*/
|
||||
public void reload(String name)
|
||||
{
|
||||
unloadExtension(name);
|
||||
clearCache();
|
||||
initExtension(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* register a getter function given a (hopefully) unique name
|
||||
* @param name the name of the function
|
||||
* @param function the ExtensionFunction implementation
|
||||
*/
|
||||
public void addGetter(String name, ExtensionFunction function)
|
||||
{
|
||||
getters.put(name, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* deregister a getter function
|
||||
* @param name the name used for registering
|
||||
*/
|
||||
public void removeGetter(String name)
|
||||
{
|
||||
getters.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* call a getter function registered with DynamicExtension
|
||||
* @param name the function name
|
||||
* @param arg a function argument
|
||||
* @return an object from the extension
|
||||
*/
|
||||
public Object get(String name, String arg)
|
||||
{
|
||||
final ExtensionFunction func = getters.get(name);
|
||||
if (func != null)
|
||||
{
|
||||
return func.get(arg);
|
||||
}
|
||||
return "<none>";
|
||||
}
|
||||
|
||||
/**
|
||||
* register a setter function given a (hopefully) unique name
|
||||
* @param name the name of the function
|
||||
* @param function the ExtensionFunction implementation
|
||||
*/
|
||||
public void addSetter(String name, ExtensionFunction function)
|
||||
{
|
||||
setters.put(name, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* deregister a setter function
|
||||
* @param name the name used for registering
|
||||
*/
|
||||
public void removeSetter(String name)
|
||||
{
|
||||
setters.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* call a setter function registered with DynamicExtension
|
||||
* @param name the function name
|
||||
* @param arg a function argument
|
||||
* @param obj an object to set
|
||||
*/
|
||||
public void set(String name, String arg, Object obj)
|
||||
{
|
||||
final ExtensionFunction func = setters.get(name);
|
||||
if (func != null)
|
||||
{
|
||||
func.set(arg, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public JarClassLoader getClassLoader()
|
||||
{
|
||||
return classLoader;
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.gameserver.util;
|
||||
|
||||
/**
|
||||
* This interface can be implemented by extensions to register simple functions with the DynamicExtension handler It's in the responsibility of the extensions to interpret the get and set functions
|
||||
* @version $Revision: $ $Date: $
|
||||
* @author Galun
|
||||
*/
|
||||
public interface ExtensionFunction
|
||||
{
|
||||
/**
|
||||
* get an object identified with a name (should have a human readable output with toString())
|
||||
* @param name the name of an object or a result of a function
|
||||
* @return the object
|
||||
*/
|
||||
public Object get(String name);
|
||||
|
||||
/**
|
||||
* set the named object to the new value supplied in obj
|
||||
* @param name the name of the object
|
||||
* @param obj the new value
|
||||
*/
|
||||
public void set(String name, Object obj);
|
||||
}
|
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.gameserver.GameTimeController;
|
||||
import com.l2jmobius.gameserver.LoginServerThread;
|
||||
import com.l2jmobius.gameserver.network.L2GameClient;
|
||||
import com.l2jmobius.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Flood protector implementation.
|
||||
* @author fordfrog
|
||||
*/
|
||||
public final class FloodProtectorAction
|
||||
{
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private static final Logger _log = Logger.getLogger(FloodProtectorAction.class.getName());
|
||||
|
||||
/**
|
||||
* Client for this instance of flood protector.
|
||||
*/
|
||||
private final L2GameClient _client;
|
||||
|
||||
/**
|
||||
* Configuration of this instance of flood protector.
|
||||
*/
|
||||
private final FloodProtectorConfig _config;
|
||||
|
||||
/**
|
||||
* Next game tick when new request is allowed.
|
||||
*/
|
||||
private volatile int _nextGameTick = GameTimeController.getGameTicks();
|
||||
|
||||
/**
|
||||
* Request counter.
|
||||
*/
|
||||
private final AtomicInteger _count = new AtomicInteger(0);
|
||||
|
||||
/**
|
||||
* Flag determining whether exceeding request has been logged.
|
||||
*/
|
||||
private boolean _logged;
|
||||
|
||||
/**
|
||||
* Flag determining whether punishment application is in progress so that we do not apply punisment multiple times (flooding).
|
||||
*/
|
||||
private volatile boolean _punishmentInProgress;
|
||||
|
||||
/**
|
||||
* Creates new instance of FloodProtectorAction.
|
||||
* @param client player for which flood protection is being created
|
||||
* @param config flood protector configuration
|
||||
*/
|
||||
public FloodProtectorAction(final L2GameClient client, final FloodProtectorConfig config)
|
||||
{
|
||||
super();
|
||||
_client = client;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the request is flood protected or not.
|
||||
* @param command command issued or short command description
|
||||
* @return true if action is allowed, otherwise false
|
||||
*/
|
||||
public boolean tryPerformAction(final String command)
|
||||
{
|
||||
final int curTick = GameTimeController.getGameTicks();
|
||||
|
||||
if ((curTick < _nextGameTick) || _punishmentInProgress)
|
||||
{
|
||||
if (_config.LOG_FLOODING && !_logged && _log.isLoggable(Level.WARNING))
|
||||
{
|
||||
log("called command ", command, " ~", String.valueOf((_config.FLOOD_PROTECTION_INTERVAL - (_nextGameTick - curTick)) * GameTimeController.MILLIS_IN_TICK), " ms after previous command");
|
||||
_logged = true;
|
||||
}
|
||||
|
||||
_count.incrementAndGet();
|
||||
|
||||
if (!_punishmentInProgress && (_config.PUNISHMENT_LIMIT > 0) && (_count.get() >= _config.PUNISHMENT_LIMIT) && (_config.PUNISHMENT_TYPE != null))
|
||||
{
|
||||
_punishmentInProgress = true;
|
||||
|
||||
if ("kick".equals(_config.PUNISHMENT_TYPE))
|
||||
{
|
||||
kickPlayer();
|
||||
}
|
||||
else if ("ban".equals(_config.PUNISHMENT_TYPE))
|
||||
{
|
||||
banAccount();
|
||||
}
|
||||
else if ("jail".equals(_config.PUNISHMENT_TYPE))
|
||||
{
|
||||
jailChar();
|
||||
}
|
||||
|
||||
_punishmentInProgress = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_count.get() > 0)
|
||||
{
|
||||
if (_config.LOG_FLOODING && _log.isLoggable(Level.WARNING))
|
||||
{
|
||||
log("issued ", String.valueOf(_count), " extra requests within ~", String.valueOf(_config.FLOOD_PROTECTION_INTERVAL * GameTimeController.MILLIS_IN_TICK), " ms");
|
||||
}
|
||||
}
|
||||
|
||||
_nextGameTick = curTick + _config.FLOOD_PROTECTION_INTERVAL;
|
||||
_logged = false;
|
||||
_count.set(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick player from game (close network connection).
|
||||
*/
|
||||
private void kickPlayer()
|
||||
{
|
||||
if (_log.isLoggable(Level.WARNING))
|
||||
{
|
||||
log("was kicked for flooding");
|
||||
}
|
||||
|
||||
if (_client.getActiveChar() != null)
|
||||
{
|
||||
_client.getActiveChar().logout(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_client.closeNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bans account and char if possible and logs out the char.
|
||||
*/
|
||||
private void banAccount()
|
||||
{
|
||||
if (_log.isLoggable(Level.WARNING))
|
||||
{
|
||||
log("was banned for flooding");
|
||||
}
|
||||
|
||||
if (_client.getAccountName() != null)
|
||||
{
|
||||
LoginServerThread.getInstance().sendAccessLevel(_client.getAccountName(), -100);
|
||||
}
|
||||
|
||||
if (_client.getActiveChar() != null)
|
||||
{
|
||||
_client.getActiveChar().setAccessLevel(-100);
|
||||
_client.getActiveChar().logout();
|
||||
}
|
||||
else
|
||||
{
|
||||
_client.closeNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Jails char.
|
||||
*/
|
||||
private void jailChar()
|
||||
{
|
||||
if (_client.getActiveChar() != null)
|
||||
{
|
||||
if (_log.isLoggable(Level.WARNING))
|
||||
{
|
||||
log("was jailed for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + _config.PUNISHMENT_TIME + " mins");
|
||||
}
|
||||
|
||||
if (!_client.getActiveChar().isInJail())
|
||||
{
|
||||
_client.getActiveChar().setInJail(true, _config.PUNISHMENT_TIME);
|
||||
}
|
||||
else
|
||||
{
|
||||
_client.getActiveChar().logout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("unable to jail: no active player");
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String... lines)
|
||||
{
|
||||
final StringBuilder output = StringUtil.startAppend(100, _config.FLOOD_PROTECTOR_TYPE, ": ");
|
||||
|
||||
String address = null;
|
||||
try
|
||||
{
|
||||
if (!_client.isDetached())
|
||||
{
|
||||
address = _client.getConnection().getInetAddress().getHostAddress();
|
||||
}
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
}
|
||||
|
||||
switch (_client.getState())
|
||||
{
|
||||
case IN_GAME:
|
||||
if (_client.getActiveChar() != null)
|
||||
{
|
||||
StringUtil.append(output, _client.getActiveChar().getName());
|
||||
StringUtil.append(output, "(", String.valueOf(_client.getActiveChar().getObjectId()), ") ");
|
||||
}
|
||||
break;
|
||||
case AUTHED:
|
||||
if (_client.getAccountName() != null)
|
||||
{
|
||||
StringUtil.append(output, _client.getAccountName(), " ");
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
if (address != null)
|
||||
{
|
||||
StringUtil.append(output, address);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Missing state on switch");
|
||||
}
|
||||
|
||||
StringUtil.append(output, lines);
|
||||
_log.warning(output.toString());
|
||||
}
|
||||
}
|
@@ -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.gameserver.util;
|
||||
|
||||
/**
|
||||
* Flood protector configuration
|
||||
* @author fordfrog
|
||||
*/
|
||||
public final class FloodProtectorConfig
|
||||
{
|
||||
/**
|
||||
* Type used for identification of logging output.
|
||||
*/
|
||||
public String FLOOD_PROTECTOR_TYPE;
|
||||
/**
|
||||
* Flood protection interval in game ticks.
|
||||
*/
|
||||
public int FLOOD_PROTECTION_INTERVAL;
|
||||
/**
|
||||
* Whether flooding should be logged.
|
||||
*/
|
||||
public boolean LOG_FLOODING;
|
||||
/**
|
||||
* If specified punishment limit is exceeded, punishment is applied.
|
||||
*/
|
||||
public int PUNISHMENT_LIMIT;
|
||||
/**
|
||||
* Punishment type. Either 'none', 'kick', 'ban' or 'jail'.
|
||||
*/
|
||||
public String PUNISHMENT_TYPE;
|
||||
/**
|
||||
* For how long should the char/account be punished.
|
||||
*/
|
||||
public int PUNISHMENT_TIME;
|
||||
|
||||
/**
|
||||
* Creates new instance of FloodProtectorConfig.
|
||||
* @param floodProtectorType {@link #FLOOD_PROTECTOR_TYPE}
|
||||
*/
|
||||
public FloodProtectorConfig(final String floodProtectorType)
|
||||
{
|
||||
super();
|
||||
FLOOD_PROTECTOR_TYPE = floodProtectorType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.network.L2GameClient;
|
||||
|
||||
/**
|
||||
* Collection of flood protectors for single player.
|
||||
* @author fordfrog
|
||||
*/
|
||||
public final class FloodProtectors
|
||||
{
|
||||
/**
|
||||
* Use-item flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _useItem;
|
||||
/**
|
||||
* Roll-dice flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _rollDice;
|
||||
/**
|
||||
* Firework flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _firework;
|
||||
/**
|
||||
* Item-pet-summon flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _itemPetSummon;
|
||||
/**
|
||||
* Hero-voice flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _heroVoice;
|
||||
/**
|
||||
* Global-chat flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _globalChat;
|
||||
/**
|
||||
* Subclass flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _subclass;
|
||||
/**
|
||||
* Drop-item flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _dropItem;
|
||||
/**
|
||||
* Server-bypass flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _serverBypass;
|
||||
/**
|
||||
* Multisell flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _multiSell;
|
||||
/**
|
||||
* Transaction flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _transaction;
|
||||
/**
|
||||
* Manufacture flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _manufacture;
|
||||
/**
|
||||
* Manor flood protector.
|
||||
*/
|
||||
private final FloodProtectorAction _manor;
|
||||
/**
|
||||
* Character Select protector
|
||||
*/
|
||||
private final FloodProtectorAction _characterSelect;
|
||||
|
||||
/**
|
||||
* Creates new instance of FloodProtectors.
|
||||
* @param client
|
||||
*/
|
||||
public FloodProtectors(final L2GameClient client)
|
||||
{
|
||||
super();
|
||||
_useItem = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_USE_ITEM);
|
||||
_rollDice = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_ROLL_DICE);
|
||||
_firework = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_FIREWORK);
|
||||
_itemPetSummon = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_ITEM_PET_SUMMON);
|
||||
_heroVoice = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_HERO_VOICE);
|
||||
_globalChat = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_GLOBAL_CHAT);
|
||||
_subclass = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_SUBCLASS);
|
||||
_dropItem = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_DROP_ITEM);
|
||||
_serverBypass = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_SERVER_BYPASS);
|
||||
_multiSell = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_MULTISELL);
|
||||
_transaction = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_TRANSACTION);
|
||||
_manufacture = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_MANUFACTURE);
|
||||
_manor = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_MANOR);
|
||||
_characterSelect = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_CHARACTER_SELECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_useItem}.
|
||||
* @return {@link #_useItem}
|
||||
*/
|
||||
public FloodProtectorAction getUseItem()
|
||||
{
|
||||
return _useItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_rollDice}.
|
||||
* @return {@link #_rollDice}
|
||||
*/
|
||||
public FloodProtectorAction getRollDice()
|
||||
{
|
||||
return _rollDice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_firework}.
|
||||
* @return {@link #_firework}
|
||||
*/
|
||||
public FloodProtectorAction getFirework()
|
||||
{
|
||||
return _firework;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_itemPetSummon}.
|
||||
* @return {@link #_itemPetSummon}
|
||||
*/
|
||||
public FloodProtectorAction getItemPetSummon()
|
||||
{
|
||||
return _itemPetSummon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_heroVoice}.
|
||||
* @return {@link #_heroVoice}
|
||||
*/
|
||||
public FloodProtectorAction getHeroVoice()
|
||||
{
|
||||
return _heroVoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_globalChat}.
|
||||
* @return {@link #_globalChat}
|
||||
*/
|
||||
public FloodProtectorAction getGlobalChat()
|
||||
{
|
||||
return _globalChat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_subclass}.
|
||||
* @return {@link #_subclass}
|
||||
*/
|
||||
public FloodProtectorAction getSubclass()
|
||||
{
|
||||
return _subclass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_dropItem}.
|
||||
* @return {@link #_dropItem}
|
||||
*/
|
||||
public FloodProtectorAction getDropItem()
|
||||
{
|
||||
return _dropItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_serverBypass}.
|
||||
* @return {@link #_serverBypass}
|
||||
*/
|
||||
public FloodProtectorAction getServerBypass()
|
||||
{
|
||||
return _serverBypass;
|
||||
}
|
||||
|
||||
public FloodProtectorAction getMultiSell()
|
||||
{
|
||||
return _multiSell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_transaction}.
|
||||
* @return {@link #_transaction}
|
||||
*/
|
||||
public FloodProtectorAction getTransaction()
|
||||
{
|
||||
return _transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_manufacture}.
|
||||
* @return {@link #_manufacture}
|
||||
*/
|
||||
public FloodProtectorAction getManufacture()
|
||||
{
|
||||
return _manufacture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_manor}.
|
||||
* @return {@link #_manor}
|
||||
*/
|
||||
public FloodProtectorAction getManor()
|
||||
{
|
||||
return _manor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link #_characterSelect}.
|
||||
* @return {@link #_characterSelect}
|
||||
*/
|
||||
public FloodProtectorAction getCharacterSelect()
|
||||
{
|
||||
return _characterSelect;
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import com.l2jserver.gameserver.geoengine.Direction;
|
||||
|
||||
/**
|
||||
* @author FBIagent
|
||||
*/
|
||||
public final class GeoUtils
|
||||
{
|
||||
public interface PointListener
|
||||
{
|
||||
/**
|
||||
* @param x
|
||||
* @param y
|
||||
* @return true proceed, false abort
|
||||
*/
|
||||
boolean onPoint(int x, int y);
|
||||
}
|
||||
|
||||
/**
|
||||
* difference between x values: never abover 1<br>
|
||||
* difference between y values: never above 1
|
||||
* @param lastX
|
||||
* @param lastY
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*/
|
||||
public static Direction computeDirection(int lastX, int lastY, int x, int y)
|
||||
{
|
||||
if (x > lastX) // east
|
||||
{
|
||||
if (y > lastY)
|
||||
{
|
||||
return Direction.SOUTH_EAST;
|
||||
}
|
||||
else if (y < lastY)
|
||||
{
|
||||
return Direction.NORTH_EAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Direction.EAST;
|
||||
}
|
||||
}
|
||||
else if (x < lastX) // west
|
||||
{
|
||||
if (y > lastY)
|
||||
{
|
||||
return Direction.SOUTH_WEST;
|
||||
}
|
||||
else if (y < lastY)
|
||||
{
|
||||
return Direction.NORTH_WEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Direction.WEST;
|
||||
}
|
||||
}
|
||||
else
|
||||
// unchanged x
|
||||
{
|
||||
if (y > lastY)
|
||||
{
|
||||
return Direction.SOUTH;
|
||||
}
|
||||
else if (y < lastY)
|
||||
{
|
||||
return Direction.NORTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;// error, should never happen, TODO: Logging
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.datatables.GmListTable;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
*/
|
||||
public final class IllegalPlayerAction implements Runnable
|
||||
{
|
||||
private static Logger _logAudit = Logger.getLogger("audit");
|
||||
|
||||
String _message;
|
||||
int _punishment;
|
||||
L2PcInstance _actor;
|
||||
|
||||
public static final int PUNISH_BROADCAST = 1;
|
||||
public static final int PUNISH_KICK = 2;
|
||||
public static final int PUNISH_KICKBAN = 3;
|
||||
public static final int PUNISH_JAIL = 4;
|
||||
|
||||
public IllegalPlayerAction(L2PcInstance actor, String message, int punishment)
|
||||
{
|
||||
_message = message;
|
||||
_punishment = punishment;
|
||||
_actor = actor;
|
||||
|
||||
switch (punishment)
|
||||
{
|
||||
case PUNISH_KICK:
|
||||
_actor.sendMessage("You will be kicked for illegal action, GM informed.");
|
||||
break;
|
||||
case PUNISH_KICKBAN:
|
||||
_actor.setAccessLevel(-100);
|
||||
_actor.setAccountAccesslevel(-100);
|
||||
_actor.sendMessage("You are banned for illegal action, GM informed.");
|
||||
break;
|
||||
case PUNISH_JAIL:
|
||||
_actor.sendMessage("Illegal action performed!");
|
||||
_actor.sendMessage("You will be teleported to GM Consultation Service area and be jailed.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final LogRecord record = new LogRecord(Level.INFO, "AUDIT:" + _message);
|
||||
record.setLoggerName("audit");
|
||||
record.setParameters(new Object[]
|
||||
{
|
||||
_actor,
|
||||
_punishment
|
||||
});
|
||||
_logAudit.log(record);
|
||||
|
||||
GmListTable.broadcastMessageToGMs(_message);
|
||||
|
||||
switch (_punishment)
|
||||
{
|
||||
case PUNISH_BROADCAST:
|
||||
return;
|
||||
case PUNISH_KICK:
|
||||
_actor.logout(false);
|
||||
break;
|
||||
case PUNISH_KICKBAN:
|
||||
_actor.logout();
|
||||
break;
|
||||
case PUNISH_JAIL:
|
||||
if (_actor.isInJail())
|
||||
{
|
||||
_actor.logout();
|
||||
}
|
||||
else
|
||||
{
|
||||
_actor.setInJail(true, Config.DEFAULT_PUNISH_PARAM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* This is a class loader for the dynamic extensions used by DynamicExtension class.
|
||||
* @version $Revision: $ $Date: $
|
||||
* @author galun
|
||||
*/
|
||||
public class JarClassLoader extends ClassLoader
|
||||
{
|
||||
private static Logger log = Logger.getLogger(JarClassLoader.class.getCanonicalName());
|
||||
HashSet<String> jars = new HashSet<>();
|
||||
|
||||
public void addJarFile(String filename)
|
||||
{
|
||||
jars.add(filename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
try
|
||||
{
|
||||
final byte[] b = loadClassData(name);
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] loadClassData(String name) throws IOException
|
||||
{
|
||||
byte[] classData = null;
|
||||
for (final String jarFile : jars)
|
||||
{
|
||||
final File file = new File(jarFile);
|
||||
@SuppressWarnings("resource")
|
||||
final ZipFile zipFile = new ZipFile(file);
|
||||
final String fileName = name.replace('.', '/') + ".class";
|
||||
final ZipEntry entry = zipFile.getEntry(fileName);
|
||||
if (entry == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try (DataInputStream zipStream = new DataInputStream(zipFile.getInputStream(entry)))
|
||||
{
|
||||
classData = new byte[(int) entry.getSize()];
|
||||
zipStream.readFully(classData, 0, (int) entry.getSize());
|
||||
break;
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
log.log(Level.WARNING, jarFile + ":" + e.toString(), e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (classData == null)
|
||||
{
|
||||
throw new IOException("class not found in " + jars);
|
||||
}
|
||||
return classData;
|
||||
}
|
||||
}
|
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
/**
|
||||
* @author FBIagent
|
||||
*/
|
||||
public final class LinePointIterator
|
||||
{
|
||||
// src is moved towards dst in next()
|
||||
private int _srcX;
|
||||
private int _srcY;
|
||||
private final int _dstX;
|
||||
private final int _dstY;
|
||||
|
||||
private final long _dx;
|
||||
private final long _dy;
|
||||
private final long _sx;
|
||||
private final long _sy;
|
||||
private long _error;
|
||||
|
||||
private boolean _first;
|
||||
|
||||
public LinePointIterator(int srcX, int srcY, int dstX, int dstY)
|
||||
{
|
||||
_srcX = srcX;
|
||||
_srcY = srcY;
|
||||
_dstX = dstX;
|
||||
_dstY = dstY;
|
||||
_dx = Math.abs((long) dstX - srcX);
|
||||
_dy = Math.abs((long) dstY - srcY);
|
||||
_sx = srcX < dstX ? 1 : -1;
|
||||
_sy = srcY < dstY ? 1 : -1;
|
||||
|
||||
if (_dx >= _dy)
|
||||
{
|
||||
_error = _dx / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_error = _dy / 2;
|
||||
}
|
||||
|
||||
_first = true;
|
||||
}
|
||||
|
||||
public boolean next()
|
||||
{
|
||||
if (_first)
|
||||
{
|
||||
_first = false;
|
||||
return true;
|
||||
}
|
||||
else if (_dx >= _dy)
|
||||
{
|
||||
if (_srcX != _dstX)
|
||||
{
|
||||
_srcX += _sx;
|
||||
|
||||
_error += _dy;
|
||||
if (_error >= _dx)
|
||||
{
|
||||
_srcY += _sy;
|
||||
_error -= _dx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_srcY != _dstY)
|
||||
{
|
||||
_srcY += _sy;
|
||||
|
||||
_error += _dx;
|
||||
if (_error >= _dy)
|
||||
{
|
||||
_srcX += _sx;
|
||||
_error -= _dy;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int x()
|
||||
{
|
||||
return _srcX;
|
||||
}
|
||||
|
||||
public int y()
|
||||
{
|
||||
return _srcY;
|
||||
}
|
||||
}
|
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
/**
|
||||
* @author FBIagent
|
||||
*/
|
||||
public final class LinePointIterator3D
|
||||
{
|
||||
private int _srcX;
|
||||
private int _srcY;
|
||||
private int _srcZ;
|
||||
private final int _dstX;
|
||||
private final int _dstY;
|
||||
private final int _dstZ;
|
||||
private final long _dx;
|
||||
private final long _dy;
|
||||
private final long _dz;
|
||||
private final long _sx;
|
||||
private final long _sy;
|
||||
private final long _sz;
|
||||
private long _error;
|
||||
private long _error2;
|
||||
private boolean _first;
|
||||
|
||||
public LinePointIterator3D(int srcX, int srcY, int srcZ, int dstX, int dstY, int dstZ)
|
||||
{
|
||||
_srcX = srcX;
|
||||
_srcY = srcY;
|
||||
_srcZ = srcZ;
|
||||
_dstX = dstX;
|
||||
_dstY = dstY;
|
||||
_dstZ = dstZ;
|
||||
_dx = Math.abs((long) dstX - srcX);
|
||||
_dy = Math.abs((long) dstY - srcY);
|
||||
_dz = Math.abs((long) dstZ - srcZ);
|
||||
_sx = srcX < dstX ? 1 : -1;
|
||||
_sy = srcY < dstY ? 1 : -1;
|
||||
_sz = srcZ < dstZ ? 1 : -1;
|
||||
|
||||
if ((_dx >= _dy) && (_dx >= _dz))
|
||||
{
|
||||
_error = _error2 = _dx / 2;
|
||||
}
|
||||
else if ((_dy >= _dx) && (_dy >= _dz))
|
||||
{
|
||||
_error = _error2 = _dy / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_error = _error2 = _dz / 2;
|
||||
}
|
||||
|
||||
_first = true;
|
||||
}
|
||||
|
||||
public boolean next()
|
||||
{
|
||||
if (_first)
|
||||
{
|
||||
_first = false;
|
||||
return true;
|
||||
}
|
||||
else if ((_dx >= _dy) && (_dx >= _dz))
|
||||
{
|
||||
if (_srcX != _dstX)
|
||||
{
|
||||
_srcX += _sx;
|
||||
|
||||
_error += _dy;
|
||||
if (_error >= _dx)
|
||||
{
|
||||
_srcY += _sy;
|
||||
_error -= _dx;
|
||||
}
|
||||
|
||||
_error2 += _dz;
|
||||
if (_error2 >= _dx)
|
||||
{
|
||||
_srcZ += _sz;
|
||||
_error2 -= _dx;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ((_dy >= _dx) && (_dy >= _dz))
|
||||
{
|
||||
if (_srcY != _dstY)
|
||||
{
|
||||
_srcY += _sy;
|
||||
|
||||
_error += _dx;
|
||||
if (_error >= _dy)
|
||||
{
|
||||
_srcX += _sx;
|
||||
_error -= _dy;
|
||||
}
|
||||
|
||||
_error2 += _dz;
|
||||
if (_error2 >= _dy)
|
||||
{
|
||||
_srcZ += _sz;
|
||||
_error2 -= _dy;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_srcZ != _dstZ)
|
||||
{
|
||||
_srcZ += _sz;
|
||||
|
||||
_error += _dx;
|
||||
if (_error >= _dz)
|
||||
{
|
||||
_srcX += _sx;
|
||||
_error -= _dz;
|
||||
}
|
||||
|
||||
_error2 += _dy;
|
||||
if (_error2 >= _dz)
|
||||
{
|
||||
_srcY += _sy;
|
||||
_error2 -= _dz;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int x()
|
||||
{
|
||||
return _srcX;
|
||||
}
|
||||
|
||||
public int y()
|
||||
{
|
||||
return _srcY;
|
||||
}
|
||||
|
||||
public int z()
|
||||
{
|
||||
return _srcZ;
|
||||
}
|
||||
}
|
267
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/MinionList.java
Normal file
267
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/MinionList.java
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.l2jmobius.Config;
|
||||
import com.l2jmobius.gameserver.datatables.NpcTable;
|
||||
import com.l2jmobius.gameserver.idfactory.IdFactory;
|
||||
import com.l2jmobius.gameserver.model.L2MinionData;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MinionInstance;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
|
||||
import com.l2jmobius.gameserver.templates.L2NpcTemplate;
|
||||
import com.l2jmobius.util.Rnd;
|
||||
|
||||
import javolution.util.FastList;
|
||||
import javolution.util.FastMap;
|
||||
import javolution.util.FastSet;
|
||||
|
||||
/**
|
||||
* This class ...
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
*/
|
||||
public class MinionList
|
||||
{
|
||||
private static Logger _log = Logger.getLogger(L2MonsterInstance.class.getName());
|
||||
|
||||
/** List containing the current spawned minions for this L2MonsterInstance */
|
||||
private final List<L2MinionInstance> minionReferences;
|
||||
protected FastMap<Long, Integer> _respawnTasks = new FastMap<Long, Integer>().shared();
|
||||
private final L2MonsterInstance master;
|
||||
|
||||
public MinionList(L2MonsterInstance pMaster)
|
||||
{
|
||||
minionReferences = new FastList<>();
|
||||
master = pMaster;
|
||||
}
|
||||
|
||||
public int countSpawnedMinions()
|
||||
{
|
||||
synchronized (minionReferences)
|
||||
{
|
||||
return minionReferences.size();
|
||||
}
|
||||
}
|
||||
|
||||
public int countSpawnedMinionsById(int minionId)
|
||||
{
|
||||
int count = 0;
|
||||
synchronized (minionReferences)
|
||||
{
|
||||
for (final L2MinionInstance minion : getSpawnedMinions())
|
||||
{
|
||||
if (minion.getNpcId() == minionId)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean hasMinions()
|
||||
{
|
||||
return getSpawnedMinions().size() > 0;
|
||||
}
|
||||
|
||||
public List<L2MinionInstance> getSpawnedMinions()
|
||||
{
|
||||
return minionReferences;
|
||||
}
|
||||
|
||||
public void addSpawnedMinion(L2MinionInstance minion)
|
||||
{
|
||||
synchronized (minionReferences)
|
||||
{
|
||||
minionReferences.add(minion);
|
||||
}
|
||||
}
|
||||
|
||||
public int lazyCountSpawnedMinionsGroups()
|
||||
{
|
||||
final Set<Integer> seenGroups = new FastSet<>();
|
||||
for (final L2MinionInstance minion : getSpawnedMinions())
|
||||
{
|
||||
seenGroups.add(minion.getNpcId());
|
||||
}
|
||||
return seenGroups.size();
|
||||
}
|
||||
|
||||
public void removeSpawnedMinion(L2MinionInstance minion)
|
||||
{
|
||||
synchronized (minionReferences)
|
||||
{
|
||||
minionReferences.remove(minion);
|
||||
}
|
||||
}
|
||||
|
||||
public void moveMinionToRespawnList(L2MinionInstance minion)
|
||||
{
|
||||
final Long current = System.currentTimeMillis();
|
||||
synchronized (minionReferences)
|
||||
{
|
||||
minionReferences.remove(minion);
|
||||
if (_respawnTasks.get(current) == null)
|
||||
{
|
||||
_respawnTasks.put(current, minion.getNpcId());
|
||||
}
|
||||
else
|
||||
{
|
||||
// nice AoE
|
||||
for (int i = 1; i < 30; i++)
|
||||
{
|
||||
if (_respawnTasks.get(current + i) == null)
|
||||
{
|
||||
_respawnTasks.put(current + i, minion.getNpcId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearRespawnList()
|
||||
{
|
||||
_respawnTasks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage respawning of minions for this RaidBoss.<BR>
|
||||
* <BR>
|
||||
*/
|
||||
public void maintainMinions()
|
||||
{
|
||||
if ((master == null) || master.isAlikeDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
final Long current = System.currentTimeMillis();
|
||||
if (_respawnTasks != null)
|
||||
{
|
||||
for (final long deathTime : _respawnTasks.keySet())
|
||||
{
|
||||
final double delay = Config.RAID_MINION_RESPAWN_TIMER;
|
||||
if ((current - deathTime) > delay)
|
||||
{
|
||||
spawnSingleMinion(_respawnTasks.get(deathTime));
|
||||
_respawnTasks.remove(deathTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the spawn of all Minions of this RaidBoss.<BR>
|
||||
* <BR>
|
||||
* <B><U> Actions</U> :</B><BR>
|
||||
* <BR>
|
||||
* <li>Get the Minion data of all Minions that must be spawn</li>
|
||||
* <li>For each Minion type, spawn the amount of Minion needed</li><BR>
|
||||
* <BR>
|
||||
*/
|
||||
public void spawnMinions()
|
||||
{
|
||||
if ((master == null) || master.isAlikeDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
final List<L2MinionData> minions = master.getTemplate().getMinionData();
|
||||
|
||||
if (minions == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (minionReferences)
|
||||
{
|
||||
int minionCount, minionId, minionsToSpawn;
|
||||
for (final L2MinionData minion : minions)
|
||||
{
|
||||
minionCount = minion.getAmount();
|
||||
minionId = minion.getMinionId();
|
||||
|
||||
minionsToSpawn = minionCount - countSpawnedMinionsById(minionId);
|
||||
|
||||
for (int i = 0; i < minionsToSpawn; i++)
|
||||
{
|
||||
spawnSingleMinion(minionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init a Minion and add it in the world as a visible object.<BR>
|
||||
* <BR>
|
||||
* <B><U> Actions</U> :</B><BR>
|
||||
* <BR>
|
||||
* <li>Get the template of the Minion to spawn</li>
|
||||
* <li>Create and Init the Minion and generate its Identifier</li>
|
||||
* <li>Set the Minion HP, MP and Heading</li>
|
||||
* <li>Set the Minion leader to this RaidBoss</li>
|
||||
* <li>Init the position of the Minion and add it in the world as a visible object</li><BR>
|
||||
* <BR>
|
||||
* @param minionid The L2NpcTemplate Identifier of the Minion to spawn
|
||||
*/
|
||||
public void spawnSingleMinion(int minionid)
|
||||
{
|
||||
|
||||
// Get the template of the Minion to spawn
|
||||
final L2NpcTemplate minionTemplate = NpcTable.getInstance().getTemplate(minionid);
|
||||
|
||||
// Create and Init the Minion and generate its Identifier
|
||||
final L2MinionInstance monster = new L2MinionInstance(IdFactory.getInstance().getNextId(), minionTemplate);
|
||||
|
||||
// Set the Minion HP, MP and Heading
|
||||
monster.setCurrentHpMp(monster.getMaxHp(), monster.getMaxMp());
|
||||
monster.setHeading(master.getHeading());
|
||||
|
||||
// Set the Minion leader to this RaidBoss
|
||||
monster.setLeader(master);
|
||||
|
||||
// Init the position of the Minion and add it in the world as a visible object
|
||||
int spawnConstant;
|
||||
final int randSpawnLim = 170;
|
||||
int randPlusMin = 1;
|
||||
spawnConstant = Rnd.nextInt(randSpawnLim);
|
||||
// randomize +/-
|
||||
randPlusMin = Rnd.nextInt(2);
|
||||
if (randPlusMin == 1)
|
||||
{
|
||||
spawnConstant *= -1;
|
||||
}
|
||||
final int newX = master.getX() + Math.round(spawnConstant);
|
||||
spawnConstant = Rnd.nextInt(randSpawnLim);
|
||||
// randomize +/-
|
||||
randPlusMin = Rnd.nextInt(2);
|
||||
if (randPlusMin == 1)
|
||||
{
|
||||
spawnConstant *= -1;
|
||||
}
|
||||
final int newY = master.getY() + Math.round(spawnConstant);
|
||||
|
||||
monster.spawnMe(newX, newY, master.getZ());
|
||||
|
||||
if (Config.DEBUG)
|
||||
{
|
||||
_log.fine("Spawned minion template " + minionTemplate.npcId + " with objid: " + monster.getObjectId() + " to boss " + master.getObjectId() + " ,at: " + monster.getX() + " x, " + monster.getY() + " y, " + monster.getZ() + " z");
|
||||
}
|
||||
}
|
||||
}
|
311
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/MultiSort.java
Normal file
311
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/MultiSort.java
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javolution.util.FastList;
|
||||
|
||||
/**
|
||||
* Descending Integer Sort Algorithm - Fast ordering system. - Can easily be ported elsewhere. - Can handle any number of values, from a list or even from a map. - Handles duplicate values.
|
||||
* @author Tempy
|
||||
*/
|
||||
public class MultiSort
|
||||
{
|
||||
public static final int SORT_ASCENDING = 0;
|
||||
public static final int SORT_DESCENDING = 1;
|
||||
|
||||
private List<?> _keyList;
|
||||
private List<Integer> _valueList;
|
||||
|
||||
private boolean _isSortDescending;
|
||||
private boolean _isSorted;
|
||||
|
||||
public MultiSort(int[] valueList)
|
||||
{
|
||||
_valueList = getIntList(valueList);
|
||||
}
|
||||
|
||||
public MultiSort(Collection<Integer> valueList)
|
||||
{
|
||||
_valueList = getIntList(valueList);
|
||||
}
|
||||
|
||||
public MultiSort(Object[] keyList, int[] valueList)
|
||||
{
|
||||
_keyList = getList(keyList);
|
||||
_valueList = getIntList(valueList);
|
||||
}
|
||||
|
||||
public MultiSort(Map<?, Integer> valueMap)
|
||||
{
|
||||
_keyList = getList(valueMap.keySet());
|
||||
_valueList = getIntList(valueMap.values());
|
||||
}
|
||||
|
||||
private final List<Integer> getIntList(Collection<Integer> valueList)
|
||||
{
|
||||
return Arrays.asList(valueList.toArray(new Integer[valueList.size()]));
|
||||
}
|
||||
|
||||
private final List<Integer> getIntList(int[] valueList)
|
||||
{
|
||||
final Integer[] tempIntList = new Integer[valueList.length];
|
||||
|
||||
for (int i = 0; i < valueList.length; i++)
|
||||
{
|
||||
tempIntList[i] = new Integer(valueList[i]);
|
||||
}
|
||||
|
||||
return Arrays.asList(tempIntList);
|
||||
}
|
||||
|
||||
private final List<?> getList(Collection<?> valueList)
|
||||
{
|
||||
return getList(valueList.toArray(new Object[valueList.size()]));
|
||||
}
|
||||
|
||||
private final List<Object> getList(Object[] valueList)
|
||||
{
|
||||
return Arrays.asList(valueList);
|
||||
}
|
||||
|
||||
public final int getCount()
|
||||
{
|
||||
return getValues().size();
|
||||
}
|
||||
|
||||
public final int getHarmonicMean()
|
||||
{
|
||||
if (getValues().isEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int totalValue = 0;
|
||||
|
||||
for (final int currValue : getValues())
|
||||
{
|
||||
totalValue += (1 / currValue);
|
||||
}
|
||||
|
||||
return (getCount() / totalValue);
|
||||
}
|
||||
|
||||
public final List<?> getKeys()
|
||||
{
|
||||
if (_keyList == null)
|
||||
{
|
||||
return new FastList<>();
|
||||
}
|
||||
|
||||
return _keyList;
|
||||
}
|
||||
|
||||
public final int getFrequency(int checkValue)
|
||||
{
|
||||
return Collections.frequency(getValues(), checkValue);
|
||||
}
|
||||
|
||||
public final int getMaxValue()
|
||||
{
|
||||
return Collections.max(getValues());
|
||||
}
|
||||
|
||||
public final int getMinValue()
|
||||
{
|
||||
return Collections.min(getValues());
|
||||
}
|
||||
|
||||
public final int getMean()
|
||||
{
|
||||
if (getValues().isEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (getTotalValue() / getCount());
|
||||
}
|
||||
|
||||
public final double getStandardDeviation()
|
||||
{
|
||||
if (getValues().isEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
final List<Double> tempValList = new FastList<>();
|
||||
|
||||
final int meanValue = getMean();
|
||||
final int numValues = getCount();
|
||||
|
||||
for (final int value : getValues())
|
||||
{
|
||||
final double adjValue = Math.pow(value - meanValue, 2);
|
||||
tempValList.add(adjValue);
|
||||
}
|
||||
|
||||
double totalValue = 0;
|
||||
|
||||
for (final double storedVal : tempValList)
|
||||
{
|
||||
totalValue += storedVal;
|
||||
}
|
||||
|
||||
return Math.sqrt(totalValue / (numValues - 1));
|
||||
}
|
||||
|
||||
public final int getTotalValue()
|
||||
{
|
||||
if (getValues().isEmpty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int totalValue = 0;
|
||||
|
||||
for (final int currValue : getValues())
|
||||
{
|
||||
totalValue += currValue;
|
||||
}
|
||||
|
||||
return totalValue;
|
||||
}
|
||||
|
||||
public final List<Integer> getValues()
|
||||
{
|
||||
if (_valueList == null)
|
||||
{
|
||||
return new FastList<>();
|
||||
}
|
||||
|
||||
return _valueList;
|
||||
}
|
||||
|
||||
public final boolean isSortDescending()
|
||||
{
|
||||
return _isSortDescending;
|
||||
}
|
||||
|
||||
public final boolean isSorted()
|
||||
{
|
||||
return _isSorted;
|
||||
}
|
||||
|
||||
public final void setSortDescending(boolean isDescending)
|
||||
{
|
||||
_isSortDescending = isDescending;
|
||||
}
|
||||
|
||||
public boolean sort()
|
||||
{
|
||||
try
|
||||
{
|
||||
final List<Object> newKeyList = new FastList<>();
|
||||
final List<Integer> newValueList = new FastList<>();
|
||||
|
||||
// Sort the list of values in ascending numerical order.
|
||||
Collections.sort(getValues());
|
||||
|
||||
int lastValue = 0;
|
||||
|
||||
if (!isSortDescending())
|
||||
{
|
||||
// If there are no keys, just return the ascendingly sorted values.
|
||||
if (getKeys().isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Iterate through the list of ordered numerical values.
|
||||
for (int i = getValues().size() - 1; i > -1; i--)
|
||||
{
|
||||
final int currValue = getValues().get(i);
|
||||
|
||||
// If the current value is equal to the last value, we have at least one
|
||||
// duplicate that has been outputted already, so continue.
|
||||
if (currValue == lastValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set the last value to the current value, to prevent duplication.
|
||||
lastValue = currValue;
|
||||
|
||||
// Iterate through each key and match it to its stored integer value,
|
||||
// then output both sets of data in the correct descending numerical order.
|
||||
for (int j = 0; j < getKeys().size(); j++)
|
||||
{
|
||||
final Object currKey = getKeys().get(j);
|
||||
|
||||
if (getValues().get(j) == currValue)
|
||||
{
|
||||
newKeyList.add(currKey);
|
||||
newValueList.add(currValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there are no keys, just sort the value list in reverse order.
|
||||
if (getKeys().isEmpty())
|
||||
{
|
||||
Collections.reverse(getValues());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Do the exact same as above, but in descending order.
|
||||
for (int i = 0; i < getValues().size(); i++)
|
||||
{
|
||||
final int currValue = getValues().get(i);
|
||||
|
||||
if (currValue == lastValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lastValue = currValue;
|
||||
|
||||
for (int j = 0; j < getKeys().size(); j++)
|
||||
{
|
||||
final Object currKey = getKeys().get(j);
|
||||
|
||||
if (getValues().get(j) == currValue)
|
||||
{
|
||||
newKeyList.add(currKey);
|
||||
newValueList.add(currValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_keyList = newKeyList;
|
||||
_valueList = newValueList;
|
||||
_isSorted = true;
|
||||
return true;
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
328
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Util.java
Normal file
328
L2J_Mobius_C4/java/com/l2jmobius/gameserver/util/Util.java
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 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.gameserver.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.l2jmobius.gameserver.ThreadPoolManager;
|
||||
import com.l2jmobius.gameserver.model.L2Character;
|
||||
import com.l2jmobius.gameserver.model.L2Object;
|
||||
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||
|
||||
/**
|
||||
* General Utility functions related to Gameserver
|
||||
* @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
|
||||
*/
|
||||
public final class Util
|
||||
{
|
||||
public static void handleIllegalPlayerAction(L2PcInstance actor, String message, int punishment)
|
||||
{
|
||||
ThreadPoolManager.getInstance().scheduleGeneral(new IllegalPlayerAction(actor, message, punishment), 5000);
|
||||
}
|
||||
|
||||
public static String getRelativePath(File base, File file)
|
||||
{
|
||||
return file.toURI().getPath().substring(base.toURI().getPath().length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return degree value of object 2 to the horizontal line with object 1 being the origin
|
||||
* @param obj1
|
||||
* @param obj2
|
||||
* @return
|
||||
*/
|
||||
public static double calculateAngleFrom(L2Object obj1, L2Object obj2)
|
||||
{
|
||||
return calculateAngleFrom(obj1.getX(), obj1.getY(), obj2.getX(), obj2.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return degree value of object 2 to the horizontal line with object 1 being the origin
|
||||
* @param obj1X
|
||||
* @param obj1Y
|
||||
* @param obj2X
|
||||
* @param obj2Y
|
||||
* @return
|
||||
*/
|
||||
public final static double calculateAngleFrom(int obj1X, int obj1Y, int obj2X, int obj2Y)
|
||||
{
|
||||
double angleTarget = Math.toDegrees(Math.atan2(obj2Y - obj1Y, obj2X - obj1X));
|
||||
if (angleTarget < 0)
|
||||
{
|
||||
angleTarget = 360 + angleTarget;
|
||||
}
|
||||
return angleTarget;
|
||||
}
|
||||
|
||||
public final static double convertHeadingToDegree(int clientHeading)
|
||||
{
|
||||
final double degree = clientHeading / 182.044444444;
|
||||
return degree;
|
||||
}
|
||||
|
||||
public final static int convertDegreeToClientHeading(double degree)
|
||||
{
|
||||
if (degree < 0)
|
||||
{
|
||||
degree = 360 + degree;
|
||||
}
|
||||
return (int) (degree * 182.044444444);
|
||||
}
|
||||
|
||||
public static int calculateHeadingFrom(L2Object obj1, L2Object obj2)
|
||||
{
|
||||
return calculateHeadingFrom(obj1.getX(), obj1.getY(), obj2.getX(), obj2.getY());
|
||||
}
|
||||
|
||||
public static int calculateHeadingFrom(int obj1X, int obj1Y, int obj2X, int obj2Y)
|
||||
{
|
||||
double angleTarget = Math.toDegrees(Math.atan2(obj2Y - obj1Y, obj2X - obj1X));
|
||||
if (angleTarget < 0)
|
||||
{
|
||||
angleTarget = 360 + angleTarget;
|
||||
}
|
||||
return (int) (angleTarget * 182.044444444);
|
||||
}
|
||||
|
||||
public final static int calculateHeadingFrom(double dx, double dy)
|
||||
{
|
||||
double angleTarget = Math.toDegrees(Math.atan2(dy, dx));
|
||||
if (angleTarget < 0)
|
||||
{
|
||||
angleTarget = 360 + angleTarget;
|
||||
}
|
||||
return (int) (angleTarget * 182.044444444);
|
||||
}
|
||||
|
||||
public static double calculateDistance(int x1, int y1, int z1, int x2, int y2)
|
||||
{
|
||||
return calculateDistance(x1, y1, 0, x2, y2, 0, false);
|
||||
}
|
||||
|
||||
public static double calculateDistance(int x1, int y1, int z1, int x2, int y2, int z2, boolean includeZAxis)
|
||||
{
|
||||
final double dx = (double) x1 - x2;
|
||||
final double dy = (double) y1 - y2;
|
||||
|
||||
if (includeZAxis)
|
||||
{
|
||||
final double dz = z1 - z2;
|
||||
return Math.sqrt((dx * dx) + (dy * dy) + (dz * dz));
|
||||
}
|
||||
return Math.sqrt((dx * dx) + (dy * dy));
|
||||
}
|
||||
|
||||
public static double calculateDistance(L2Object obj1, L2Object obj2, boolean includeZAxis)
|
||||
{
|
||||
if ((obj1 == null) || (obj2 == null))
|
||||
{
|
||||
return 1000000;
|
||||
}
|
||||
return calculateDistance(obj1.getPosition().getX(), obj1.getPosition().getY(), obj1.getPosition().getZ(), obj2.getPosition().getX(), obj2.getPosition().getY(), obj2.getPosition().getZ(), includeZAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalizes the first letter of a string, and returns the result.<BR>
|
||||
* (Based on ucfirst() function of PHP)
|
||||
* @param str
|
||||
* @return String containing the modified string.
|
||||
*/
|
||||
public static String capitalizeFirst(String str)
|
||||
{
|
||||
str = str.trim();
|
||||
|
||||
if ((str.length() > 0) && Character.isLetter(str.charAt(0)))
|
||||
{
|
||||
return str.substring(0, 1).toUpperCase() + str.substring(1);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capitalizes the first letter of every "word" in a string.<BR>
|
||||
* (Based on ucwords() function of PHP)
|
||||
* @param str
|
||||
* @return String containing the modified string.
|
||||
*/
|
||||
public static String capitalizeWords(String str)
|
||||
{
|
||||
final char[] charArray = str.toCharArray();
|
||||
String result = "";
|
||||
|
||||
// Capitalize the first letter in the given string!
|
||||
charArray[0] = Character.toUpperCase(charArray[0]);
|
||||
|
||||
for (int i = 0; i < charArray.length; i++)
|
||||
{
|
||||
if (Character.isWhitespace(charArray[i]))
|
||||
{
|
||||
charArray[i + 1] = Character.toUpperCase(charArray[i + 1]);
|
||||
}
|
||||
|
||||
result += Character.toString(charArray[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if object is within range, adding collisionRadius
|
||||
*/
|
||||
public static boolean checkIfInRange(int range, L2Object obj1, L2Object obj2, boolean includeZAxis)
|
||||
{
|
||||
if ((obj1 == null) || (obj2 == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (range == -1)
|
||||
{
|
||||
return true; // not limited
|
||||
}
|
||||
|
||||
int rad = 0;
|
||||
if (obj1 instanceof L2Character)
|
||||
{
|
||||
rad += ((L2Character) obj1).getTemplate().collisionRadius;
|
||||
}
|
||||
if (obj2 instanceof L2Character)
|
||||
{
|
||||
rad += ((L2Character) obj2).getTemplate().collisionRadius;
|
||||
}
|
||||
|
||||
final double dx = obj1.getX() - obj2.getX();
|
||||
final double dy = obj1.getY() - obj2.getY();
|
||||
|
||||
if (includeZAxis)
|
||||
{
|
||||
final double dz = obj1.getZ() - obj2.getZ();
|
||||
final double d = (dx * dx) + (dy * dy) + (dz * dz);
|
||||
|
||||
return d <= ((range * range) + (2 * range * rad) + (rad * rad));
|
||||
}
|
||||
final double d = (dx * dx) + (dy * dy);
|
||||
|
||||
return d <= ((range * range) + (2 * range * rad) + (rad * rad));
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if object is within short (sqrt(int.max_value)) radius, not using collisionRadius. Faster calculation than checkIfInRange if distance is short and collisionRadius isn't needed. Not for long distance checks (potential teleports, far away castles etc)
|
||||
*/
|
||||
public static boolean checkIfInShortRadius(int radius, L2Object obj1, L2Object obj2, boolean includeZAxis)
|
||||
{
|
||||
if ((obj1 == null) || (obj2 == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (radius == -1)
|
||||
{
|
||||
return true; // not limited
|
||||
}
|
||||
|
||||
final int dx = obj1.getX() - obj2.getX();
|
||||
final int dy = obj1.getY() - obj2.getY();
|
||||
|
||||
if (includeZAxis)
|
||||
{
|
||||
final int dz = obj1.getZ() - obj2.getZ();
|
||||
return ((dx * dx) + (dy * dy) + (dz * dz)) <= (radius * radius);
|
||||
}
|
||||
return ((dx * dx) + (dy * dy)) <= (radius * radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of "words" in a given string.
|
||||
* @param str
|
||||
* @return int numWords
|
||||
*/
|
||||
public static int countWords(String str)
|
||||
{
|
||||
return str.trim().split(" ").length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a delimited string for an given array of string elements.<BR>
|
||||
* (Based on implode() in PHP)
|
||||
* @param strArray
|
||||
* @param strDelim
|
||||
* @return String implodedString
|
||||
*/
|
||||
public static String implodeString(String[] strArray, String strDelim)
|
||||
{
|
||||
String result = "";
|
||||
|
||||
for (final String strValue : strArray)
|
||||
{
|
||||
result += strValue + strDelim;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a delimited string for an given collection of string elements.<BR>
|
||||
* (Based on implode() in PHP)
|
||||
* @param strCollection
|
||||
* @param strDelim
|
||||
* @return String implodedString
|
||||
*/
|
||||
public static String implodeString(Collection<String> strCollection, String strDelim)
|
||||
{
|
||||
return implodeString(strCollection.toArray(new String[strCollection.size()]), strDelim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rounded value of val to specified number of digits after the decimal point.<BR>
|
||||
* (Based on round() in PHP)
|
||||
* @param val
|
||||
* @param numPlaces
|
||||
* @return float roundedVal
|
||||
*/
|
||||
public static float roundTo(float val, int numPlaces)
|
||||
{
|
||||
if (numPlaces <= 1)
|
||||
{
|
||||
return Math.round(val);
|
||||
}
|
||||
|
||||
final float exponent = (float) Math.pow(10, numPlaces);
|
||||
|
||||
return (Math.round(val * exponent) / exponent);
|
||||
}
|
||||
|
||||
public static boolean isAlphaNumeric(String text)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
final char[] chars = text.toCharArray();
|
||||
for (int i = 0; i < chars.length; i++)
|
||||
{
|
||||
if (!Character.isLetterOrDigit(chars[i]))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user