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,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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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());
}
}

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.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;
}
}

View File

@@ -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;
}
}

View File

@@ -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
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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");
}
}
}

View 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;
}
}
}

View 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;
}
}