Project update.

This commit is contained in:
MobiusDev
2015-12-31 23:53:41 +00:00
parent e0d681a17e
commit ad2bcd79be
4084 changed files with 83696 additions and 86998 deletions

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 java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.CharInfo;
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
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 targeted.<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>
* <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>
* @param character
* @param mov
*/
public static void toPlayersTargettingMyself(L2Character character, L2GameServerPacket mov)
{
final Collection<L2PcInstance> plrs = character.getKnownList().getKnownPlayers().values();
for (L2PcInstance player : plrs)
{
if (player.getTarget() != character)
{
continue;
}
player.sendPacket(mov);
}
}
/**
* Send a packet to all L2PcInstance in the _KnownPlayers of the L2Character.<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>
* <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>
* @param character
* @param mov
*/
public static void toKnownPlayers(L2Character character, L2GameServerPacket mov)
{
final Collection<L2PcInstance> plrs = character.getKnownList().getKnownPlayers().values();
for (L2PcInstance player : plrs)
{
if (player == null)
{
continue;
}
try
{
player.sendPacket(mov);
if ((mov instanceof CharInfo) && (character.isPlayer()))
{
final int relation = ((L2PcInstance) character).getRelation(player);
final Integer oldrelation = character.getKnownList().getKnownRelations().get(player.getObjectId());
if ((oldrelation != null) && (oldrelation != relation))
{
final RelationChanged rc = new RelationChanged();
rc.addRelation((L2PcInstance) character, relation, character.isAutoAttackable(player));
if (character.hasSummon())
{
final L2Summon pet = character.getPet();
if (pet != null)
{
rc.addRelation(pet, relation, character.isAutoAttackable(player));
}
if (character.hasServitors())
{
character.getServitors().values().forEach(s -> rc.addRelation(s, relation, character.isAutoAttackable(player)));
}
}
player.sendPacket(rc);
character.getKnownList().getKnownRelations().put(player.getObjectId(), relation);
}
}
}
catch (NullPointerException e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
}
}
/**
* Send a packet to all L2PcInstance in the _KnownPlayers (in the specified radius) of the L2Character.<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>
* <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>
* @param character
* @param mov
* @param radius
*/
public static void toKnownPlayersInRadius(L2Character character, L2GameServerPacket mov, int radius)
{
if (radius < 0)
{
radius = 1500;
}
final Collection<L2PcInstance> plrs = character.getKnownList().getKnownPlayers().values();
for (L2PcInstance player : plrs)
{
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>
* <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>
* @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, int radius)
{
if (radius < 0)
{
radius = 600;
}
if (character instanceof L2PcInstance)
{
character.sendPacket(mov);
}
final Collection<L2PcInstance> plrs = character.getKnownList().getKnownPlayers().values();
for (L2PcInstance player : plrs)
{
if ((player != null) && Util.checkIfInRange(radius, character, player, false))
{
player.sendPacket(mov);
}
}
}
/**
* Send a packet to all L2PcInstance present in the world.<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>
* <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>
* @param packet
*/
public static void toAllOnlinePlayers(L2GameServerPacket packet)
{
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
if (player.isOnline())
{
player.sendPacket(packet);
}
}
}
public static void toAllOnlinePlayers(String text)
{
toAllOnlinePlayers(text, false);
}
public static void toAllOnlinePlayers(String text, boolean isCritical)
{
toAllOnlinePlayers(new CreatureSay(0, isCritical ? ChatType.CRITICAL_ANNOUNCE : ChatType.ANNOUNCEMENT, "", text));
}
public static void toPlayersInInstance(L2GameServerPacket packet, int instanceId)
{
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
if (player.isOnline() && (player.getInstanceId() == instanceId))
{
player.sendPacket(packet);
}
}
}
public static void toAllOnlinePlayersOnScreen(String text)
{
toAllOnlinePlayers(new ExShowScreenMessage(text, 10000));
}
}

View File

@ -0,0 +1,332 @@
/*
* 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.sql.Connection;
import java.sql.PreparedStatement;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.pool.impl.ConnectionFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.data.xml.impl.PetDataTable;
import com.l2jmobius.gameserver.model.L2PetData;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExAdenaInvenCount;
import com.l2jmobius.gameserver.network.serverpackets.ExUserInfoInvenWeight;
import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate;
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillLaunched;
import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* UnAfraid: TODO: MOVE IT TO DP AI
*/
public final class Evolve
{
protected static final Logger _log = Logger.getLogger(Evolve.class.getName());
public static final boolean doEvolve(L2PcInstance player, L2Npc npc, int itemIdtake, int itemIdgive, int petminlvl)
{
if ((itemIdtake == 0) || (itemIdgive == 0) || (petminlvl == 0))
{
return false;
}
final L2Summon pet = player.getPet();
if (pet == null)
{
return false;
}
final L2PetInstance currentPet = (L2PetInstance) pet;
if (currentPet.isAlikeDead())
{
Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to use death pet exploit!", Config.DEFAULT_PUNISH);
return false;
}
L2ItemInstance item = null;
long petexp = currentPet.getStat().getExp();
final String oldname = currentPet.getName();
final int oldX = currentPet.getX();
final int oldY = currentPet.getY();
final int oldZ = currentPet.getZ();
final L2PetData oldData = PetDataTable.getInstance().getPetDataByItemId(itemIdtake);
if (oldData == null)
{
return false;
}
final int oldnpcID = oldData.getNpcId();
if ((currentPet.getStat().getLevel() < petminlvl) || (currentPet.getId() != oldnpcID))
{
return false;
}
final L2PetData petData = PetDataTable.getInstance().getPetDataByItemId(itemIdgive);
if (petData == null)
{
return false;
}
final int npcID = petData.getNpcId();
if (npcID == 0)
{
return false;
}
final L2NpcTemplate npcTemplate = NpcData.getInstance().getTemplate(npcID);
currentPet.unSummon(player);
// deleting old pet item
currentPet.destroyControlItem(player, true);
item = player.getInventory().addItem("Evolve", itemIdgive, 1, player, npc);
// Summoning new pet
final L2PetInstance petSummon = L2PetInstance.spawnPet(npcTemplate, player, item);
if (petSummon == null)
{
return false;
}
// Fix for non-linear baby pet exp
final long _minimumexp = petSummon.getStat().getExpForLevel(petminlvl);
if (petexp < _minimumexp)
{
petexp = _minimumexp;
}
petSummon.getStat().addExp(petexp);
petSummon.setCurrentHp(petSummon.getMaxHp());
petSummon.setCurrentMp(petSummon.getMaxMp());
petSummon.setCurrentFed(petSummon.getMaxFed());
petSummon.setTitle(player.getName());
petSummon.setName(oldname);
petSummon.setRunning();
petSummon.storeMe();
player.setPet(petSummon);
player.sendPacket(new MagicSkillUse(npc, 2046, 1, 1000, 600000));
player.sendPacket(SystemMessageId.SUMMONING_YOUR_PET);
// L2World.getInstance().storeObject(petSummon);
petSummon.spawnMe(oldX, oldY, oldZ);
petSummon.startFeed();
item.setEnchantLevel(petSummon.getLevel());
ThreadPoolManager.getInstance().scheduleGeneral(new EvolveFinalizer(player, petSummon), 900);
if (petSummon.getCurrentFed() <= 0)
{
ThreadPoolManager.getInstance().scheduleGeneral(new EvolveFeedWait(player, petSummon), 60000);
}
else
{
petSummon.startFeed();
}
return true;
}
public static final boolean doRestore(L2PcInstance player, L2Npc npc, int itemIdtake, int itemIdgive, int petminlvl)
{
if ((itemIdtake == 0) || (itemIdgive == 0) || (petminlvl == 0))
{
return false;
}
final L2ItemInstance item = player.getInventory().getItemByItemId(itemIdtake);
if (item == null)
{
return false;
}
int oldpetlvl = item.getEnchantLevel();
if (oldpetlvl < petminlvl)
{
oldpetlvl = petminlvl;
}
final L2PetData oldData = PetDataTable.getInstance().getPetDataByItemId(itemIdtake);
if (oldData == null)
{
return false;
}
final L2PetData petData = PetDataTable.getInstance().getPetDataByItemId(itemIdgive);
if (petData == null)
{
return false;
}
final int npcId = petData.getNpcId();
if (npcId == 0)
{
return false;
}
final L2NpcTemplate npcTemplate = NpcData.getInstance().getTemplate(npcId);
// deleting old pet item
final L2ItemInstance removedItem = player.getInventory().destroyItem("PetRestore", item, player, npc);
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_DISAPPEARED);
sm.addItemName(removedItem);
player.sendPacket(sm);
// Give new pet item
final L2ItemInstance addedItem = player.getInventory().addItem("PetRestore", itemIdgive, 1, player, npc);
// Summoning new pet
final L2PetInstance petSummon = L2PetInstance.spawnPet(npcTemplate, player, addedItem);
if (petSummon == null)
{
return false;
}
final long _maxexp = petSummon.getStat().getExpForLevel(oldpetlvl);
petSummon.getStat().addExp(_maxexp);
petSummon.setCurrentHp(petSummon.getMaxHp());
petSummon.setCurrentMp(petSummon.getMaxMp());
petSummon.setCurrentFed(petSummon.getMaxFed());
petSummon.setTitle(player.getName());
petSummon.setRunning();
petSummon.storeMe();
player.setPet(petSummon);
player.sendPacket(new MagicSkillUse(npc, 2046, 1, 1000, 600000));
player.sendPacket(SystemMessageId.SUMMONING_YOUR_PET);
// L2World.getInstance().storeObject(petSummon);
petSummon.spawnMe(player.getX(), player.getY(), player.getZ());
petSummon.startFeed();
addedItem.setEnchantLevel(petSummon.getLevel());
// Inventory update
final InventoryUpdate iu = new InventoryUpdate();
iu.addRemovedItem(removedItem);
player.sendPacket(iu);
player.sendPacket(new ExUserInfoInvenWeight(player));
player.sendPacket(new ExAdenaInvenCount(player));
player.broadcastUserInfo();
final L2World world = L2World.getInstance();
world.removeObject(removedItem);
ThreadPoolManager.getInstance().scheduleGeneral(new EvolveFinalizer(player, petSummon), 900);
if (petSummon.getCurrentFed() <= 0)
{
ThreadPoolManager.getInstance().scheduleGeneral(new EvolveFeedWait(player, petSummon), 60000);
}
else
{
petSummon.startFeed();
}
// pet control item no longer exists, delete the pet from the db
try (Connection con = ConnectionFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM pets WHERE item_obj_id=?"))
{
ps.setInt(1, removedItem.getObjectId());
ps.execute();
}
catch (Exception e)
{
}
return true;
}
static final class EvolveFeedWait implements Runnable
{
private final L2PcInstance _activeChar;
private final L2PetInstance _petSummon;
EvolveFeedWait(L2PcInstance activeChar, L2PetInstance petSummon)
{
_activeChar = activeChar;
_petSummon = petSummon;
}
@Override
public void run()
{
try
{
if (_petSummon.getCurrentFed() <= 0)
{
_petSummon.unSummon(_activeChar);
}
else
{
_petSummon.startFeed();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "", e);
}
}
}
static final class EvolveFinalizer implements Runnable
{
private final L2PcInstance _activeChar;
private final L2PetInstance _petSummon;
EvolveFinalizer(L2PcInstance activeChar, L2PetInstance petSummon)
{
_activeChar = activeChar;
_petSummon = petSummon;
}
@Override
public void run()
{
try
{
_activeChar.sendPacket(new MagicSkillLaunched(_activeChar, 2046, 1));
_petSummon.setFollowStatus(true);
_petSummon.setShowSummonAnimation(false);
}
catch (Throwable e)
{
_log.log(Level.WARNING, "", e);
}
}
}
}

View File

@ -0,0 +1,242 @@
/*
* 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.instancemanager.PunishmentManager;
import com.l2jmobius.gameserver.model.PcCondOverride;
import com.l2jmobius.gameserver.model.punishment.PunishmentAffect;
import com.l2jmobius.gameserver.model.punishment.PunishmentTask;
import com.l2jmobius.gameserver.model.punishment.PunishmentType;
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.getInstance().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 the game client 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.getInstance().getGameTicks();
if ((_client.getActiveChar() != null) && _client.getActiveChar().canOverrideCond(PcCondOverride.FLOOD_CONDITIONS))
{
return true;
}
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 (_client.getActiveChar() != null)
{
_client.getActiveChar().logout(false);
}
else
{
_client.closeNow();
}
if (_log.isLoggable(Level.WARNING))
{
log("kicked for flooding");
}
}
/**
* Bans char account and logs out the char.
*/
private void banAccount()
{
PunishmentManager.getInstance().startPunishment(new PunishmentTask(_client.getAccountName(), PunishmentAffect.ACCOUNT, PunishmentType.BAN, System.currentTimeMillis() + _config.PUNISHMENT_TIME, "", getClass().getSimpleName()));
if (_log.isLoggable(Level.WARNING))
{
log(" banned for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + (_config.PUNISHMENT_TIME / 60000) + " mins");
}
}
/**
* Jails char.
*/
private void jailChar()
{
if (_client.getActiveChar() != null)
{
final int charId = _client.getActiveChar().getObjectId();
if (charId > 0)
{
PunishmentManager.getInstance().startPunishment(new PunishmentTask(charId, PunishmentAffect.CHARACTER, PunishmentType.JAIL, System.currentTimeMillis() + _config.PUNISHMENT_TIME, "", getClass().getSimpleName()));
}
if (_log.isLoggable(Level.WARNING))
{
log(" jailed for flooding ", _config.PUNISHMENT_TIME <= 0 ? "forever" : "for " + (_config.PUNISHMENT_TIME / 60000) + " mins");
}
}
}
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 (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 long 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,260 @@
/*
* 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;
/**
* Send mail flood protector.
*/
private final FloodProtectorAction _sendMail;
/**
* Character Select protector
*/
private final FloodProtectorAction _characterSelect;
/**
* Item Auction
*/
private final FloodProtectorAction _itemAuction;
/**
* Creates new instance of FloodProtectors.
* @param client game client for which the collection of flood protectors is being created.
*/
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);
_sendMail = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_SENDMAIL);
_characterSelect = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_CHARACTER_SELECT);
_itemAuction = new FloodProtectorAction(client, Config.FLOOD_PROTECTOR_ITEM_AUCTION);
}
/**
* 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;
}
/**
* @return {@link #_multiSell}
*/
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 #_sendMail}.
* @return {@link #_sendMail}
*/
public FloodProtectorAction getSendMail()
{
return _sendMail;
}
/**
* Returns {@link #_characterSelect}.
* @return {@link #_characterSelect}
*/
public FloodProtectorAction getCharacterSelect()
{
return _characterSelect;
}
/**
* Returns {@link #_itemAuction}.
* @return {@link #_itemAuction}
*/
public FloodProtectorAction getItemAuction()
{
return _itemAuction;
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
/**
* Audits Game Master's actions.
*/
public class GMAudit
{
private static final Logger _log = Logger.getLogger(GMAudit.class.getName());
static
{
new File("log/GMAudit").mkdirs();
}
/**
* Logs a Game Master's action into a file.
* @param gmName the Game Master's name
* @param action the performed action
* @param target the target's name
* @param params the parameters
*/
public static void auditGMAction(String gmName, String action, String target, String params)
{
final SimpleDateFormat _formatter = new SimpleDateFormat("dd/MM/yyyy H:mm:ss");
final String date = _formatter.format(new Date());
String name = com.l2jmobius.util.Util.replaceIllegalCharacters(gmName);
if (!com.l2jmobius.util.Util.isValidFileName(name))
{
name = "INVALID_GM_NAME_" + date;
}
final File file = new File("log/GMAudit/" + name + ".txt");
try (FileWriter save = new FileWriter(file, true))
{
save.write(date + ">" + gmName + ">" + action + ">" + target + ">" + params + Config.EOL);
}
catch (IOException e)
{
_log.log(Level.SEVERE, "GMAudit for GM " + gmName + " could not be saved: ", e);
}
}
/**
* Wrapper method.
* @param gmName the Game Master's name
* @param action the performed action
* @param target the target's name
*/
public static void auditGMAction(String gmName, String action, String target)
{
auditGMAction(gmName, action, target, "");
}
}

View File

@ -0,0 +1,233 @@
/*
* 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.awt.Color;
import com.l2jmobius.commons.geodriver.Cell;
import com.l2jmobius.gameserver.GeoData;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.serverpackets.ExServerPrimitive;
/**
* @author HorridoJoho
*/
public final class GeoUtils
{
public static void debug2DLine(L2PcInstance player, int x, int y, int tx, int ty, int z)
{
final int gx = GeoData.getInstance().getGeoX(x);
final int gy = GeoData.getInstance().getGeoY(y);
final int tgx = GeoData.getInstance().getGeoX(tx);
final int tgy = GeoData.getInstance().getGeoY(ty);
final ExServerPrimitive prim = new ExServerPrimitive("Debug2DLine", x, y, z);
prim.addLine(Color.BLUE, GeoData.getInstance().getWorldX(gx), GeoData.getInstance().getWorldY(gy), z, GeoData.getInstance().getWorldX(tgx), GeoData.getInstance().getWorldY(tgy), z);
final LinePointIterator iter = new LinePointIterator(gx, gy, tgx, tgy);
while (iter.next())
{
final int wx = GeoData.getInstance().getWorldX(iter.x());
final int wy = GeoData.getInstance().getWorldY(iter.y());
prim.addPoint(Color.RED, wx, wy, z);
}
player.sendPacket(prim);
}
public static void debug3DLine(L2PcInstance player, int x, int y, int z, int tx, int ty, int tz)
{
final int gx = GeoData.getInstance().getGeoX(x);
final int gy = GeoData.getInstance().getGeoY(y);
final int tgx = GeoData.getInstance().getGeoX(tx);
final int tgy = GeoData.getInstance().getGeoY(ty);
final ExServerPrimitive prim = new ExServerPrimitive("Debug3DLine", x, y, z);
prim.addLine(Color.BLUE, GeoData.getInstance().getWorldX(gx), GeoData.getInstance().getWorldY(gy), z, GeoData.getInstance().getWorldX(tgx), GeoData.getInstance().getWorldY(tgy), tz);
final LinePointIterator3D iter = new LinePointIterator3D(gx, gy, z, tgx, tgy, tz);
iter.next();
int prevX = iter.x();
int prevY = iter.y();
int wx = GeoData.getInstance().getWorldX(prevX);
int wy = GeoData.getInstance().getWorldY(prevY);
int wz = iter.z();
prim.addPoint(Color.RED, wx, wy, wz);
while (iter.next())
{
final int curX = iter.x();
final int curY = iter.y();
if ((curX != prevX) || (curY != prevY))
{
wx = GeoData.getInstance().getWorldX(curX);
wy = GeoData.getInstance().getWorldY(curY);
wz = iter.z();
prim.addPoint(Color.RED, wx, wy, wz);
prevX = curX;
prevY = curY;
}
}
player.sendPacket(prim);
}
private static Color getDirectionColor(int x, int y, int z, int nswe)
{
if (GeoData.getInstance().checkNearestNswe(x, y, z, nswe))
{
return Color.GREEN;
}
return Color.RED;
}
public static void debugGrid(L2PcInstance player)
{
final int geoRadius = 10;
final int blocksPerPacket = 49;
int iBlock = blocksPerPacket;
int iPacket = 0;
ExServerPrimitive exsp = null;
final GeoData gd = GeoData.getInstance();
final int playerGx = gd.getGeoX(player.getX());
final int playerGy = gd.getGeoY(player.getY());
for (int dx = -geoRadius; dx <= geoRadius; ++dx)
{
for (int dy = -geoRadius; dy <= geoRadius; ++dy)
{
if (iBlock >= blocksPerPacket)
{
iBlock = 0;
if (exsp != null)
{
++iPacket;
player.sendPacket(exsp);
}
exsp = new ExServerPrimitive("DebugGrid_" + iPacket, player.getX(), player.getY(), -16000);
}
if (exsp == null)
{
throw new IllegalStateException();
}
final int gx = playerGx + dx;
final int gy = playerGy + dy;
final int x = gd.getWorldX(gx);
final int y = gd.getWorldY(gy);
final int z = gd.getNearestZ(gx, gy, player.getZ());
// north arrow
Color col = getDirectionColor(gx, gy, z, Cell.NSWE_NORTH);
exsp.addLine(col, x - 1, y - 7, z, x + 1, y - 7, z);
exsp.addLine(col, x - 2, y - 6, z, x + 2, y - 6, z);
exsp.addLine(col, x - 3, y - 5, z, x + 3, y - 5, z);
exsp.addLine(col, x - 4, y - 4, z, x + 4, y - 4, z);
// east arrow
col = getDirectionColor(gx, gy, z, Cell.NSWE_EAST);
exsp.addLine(col, x + 7, y - 1, z, x + 7, y + 1, z);
exsp.addLine(col, x + 6, y - 2, z, x + 6, y + 2, z);
exsp.addLine(col, x + 5, y - 3, z, x + 5, y + 3, z);
exsp.addLine(col, x + 4, y - 4, z, x + 4, y + 4, z);
// south arrow
col = getDirectionColor(gx, gy, z, Cell.NSWE_SOUTH);
exsp.addLine(col, x - 1, y + 7, z, x + 1, y + 7, z);
exsp.addLine(col, x - 2, y + 6, z, x + 2, y + 6, z);
exsp.addLine(col, x - 3, y + 5, z, x + 3, y + 5, z);
exsp.addLine(col, x - 4, y + 4, z, x + 4, y + 4, z);
col = getDirectionColor(gx, gy, z, Cell.NSWE_WEST);
exsp.addLine(col, x - 7, y - 1, z, x - 7, y + 1, z);
exsp.addLine(col, x - 6, y - 2, z, x - 6, y + 2, z);
exsp.addLine(col, x - 5, y - 3, z, x - 5, y + 3, z);
exsp.addLine(col, x - 4, y - 4, z, x - 4, y + 4, z);
++iBlock;
}
}
player.sendPacket(exsp);
}
/**
* difference between x values: never above 1<br>
* difference between y values: never above 1
* @param lastX
* @param lastY
* @param x
* @param y
* @return
*/
public static int computeNswe(int lastX, int lastY, int x, int y)
{
if (x > lastX) // east
{
if (y > lastY)
{
return Cell.NSWE_SOUTH_EAST;// Direction.SOUTH_EAST;
}
else if (y < lastY)
{
return Cell.NSWE_NORTH_EAST;// Direction.NORTH_EAST;
}
else
{
return Cell.NSWE_EAST;// Direction.EAST;
}
}
else if (x < lastX) // west
{
if (y > lastY)
{
return Cell.NSWE_SOUTH_WEST;// Direction.SOUTH_WEST;
}
else if (y < lastY)
{
return Cell.NSWE_NORTH_WEST;// Direction.NORTH_WEST;
}
else
{
return Cell.NSWE_WEST;// Direction.WEST;
}
}
else
// unchanged x
{
if (y > lastY)
{
return Cell.NSWE_SOUTH;// Direction.SOUTH;
}
else if (y < lastY)
{
return Cell.NSWE_NORTH;// Direction.NORTH;
}
else
{
throw new RuntimeException();
}
}
}
}

View File

@ -0,0 +1,247 @@
/*
* 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.function.Function;
import com.l2jmobius.gameserver.model.PageResult;
import com.l2jmobius.util.StringUtil;
/**
* A class containing useful methods for constructing HTML
* @author NosBit
*/
public class HtmlUtil
{
/**
* Gets the HTML representation of CP gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getCpGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_CP_bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_CP_Center", 17, -13);
}
/**
* Gets the HTML representation of HP gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getHpGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_HP_bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_HP_Center", 17, -13);
}
/**
* Gets the HTML representation of HP Warn gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getHpWarnGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_HPWarn_bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_HPWarn_Center", 17, -13);
}
/**
* Gets the HTML representation of HP Fill gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getHpFillGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_HPFill_bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_HPFill_Center", 17, -13);
}
/**
* Gets the HTML representation of MP Warn gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getMpGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_MP_bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_MP_Center", 17, -13);
}
/**
* Gets the HTML representation of EXP Warn gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getExpGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_EXP_bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_EXP_Center", 17, -13);
}
/**
* Gets the HTML representation of Food gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getFoodGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_Food_Bg_Center", "L2UI_CT1.Gauges.Gauge_DF_Large_Food_Center", 17, -13);
}
/**
* Gets the HTML representation of Weight gauge automatically changing level depending on current/max.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @return the HTML
*/
public static String getWeightGauge(int width, long current, long max, boolean displayAsPercentage)
{
return getWeightGauge(width, current, max, displayAsPercentage, Util.map(current, 0, max, 1, 5));
}
/**
* Gets the HTML representation of Weight gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @param level a number from 1 to 5 for the 5 different colors of weight gauge
* @return the HTML
*/
public static String getWeightGauge(int width, long current, long max, boolean displayAsPercentage, long level)
{
return getGauge(width, current, max, displayAsPercentage, "L2UI_CT1.Gauges.Gauge_DF_Large_Weight_bg_Center" + level, "L2UI_CT1.Gauges.Gauge_DF_Large_Weight_Center" + level, 17, -13);
}
/**
* Gets the HTML representation of a gauge.
* @param width the width
* @param current the current value
* @param max the max value
* @param displayAsPercentage if {@code true} the text in middle will be displayed as percent else it will be displayed as "current / max"
* @param backgroundImage the background image
* @param image the foreground image
* @param imageHeight the image height
* @param top the top adjustment
* @return the HTML
*/
private static String getGauge(int width, long current, long max, boolean displayAsPercentage, String backgroundImage, String image, long imageHeight, long top)
{
current = Math.min(current, max);
final StringBuilder sb = new StringBuilder();
StringUtil.append(sb, "<table width=", String.valueOf(width), " cellpadding=0 cellspacing=0><tr><td background=\"" + backgroundImage + "\">");
StringUtil.append(sb, "<img src=\"" + image + "\" width=", String.valueOf((long) (((double) current / max) * width)), " height=", String.valueOf(imageHeight), ">");
StringUtil.append(sb, "</td></tr><tr><td align=center><table cellpadding=0 cellspacing=", String.valueOf(top), "><tr><td>");
if (displayAsPercentage)
{
StringUtil.append(sb, "<table cellpadding=0 cellspacing=2><tr><td>", String.format("%.2f%%", ((double) current / max) * 100), "</td></tr></table>");
}
else
{
final String tdWidth = String.valueOf((width - 10) / 2);
StringUtil.append(sb, "<table cellpadding=0 cellspacing=0><tr><td width=" + tdWidth + " align=right>", String.valueOf(current), "</td>");
StringUtil.append(sb, "<td width=10 align=center>/</td><td width=" + tdWidth + ">", String.valueOf(max), "</td></tr></table>");
}
StringUtil.append(sb, "</td></tr></table></td></tr></table>");
return sb.toString();
}
public static <T> PageResult createPage(Collection<T> elements, int page, int elementsPerPage, Function<Integer, String> pagerFunction, Function<T, String> bodyFunction)
{
return createPage(elements, elements.size(), page, elementsPerPage, pagerFunction, bodyFunction);
}
public static <T> PageResult createPage(T[] elements, int page, int elementsPerPage, Function<Integer, String> pagerFunction, Function<T, String> bodyFunction)
{
return createPage(Arrays.asList(elements), elements.length, page, elementsPerPage, pagerFunction, bodyFunction);
}
public static <T> PageResult createPage(Iterable<T> elements, int size, int page, int elementsPerPage, Function<Integer, String> pagerFunction, Function<T, String> bodyFunction)
{
int pages = size / elementsPerPage;
if ((elementsPerPage * pages) < size)
{
pages++;
}
final StringBuilder pagerTemplate = new StringBuilder();
if (pages > 1)
{
int breakit = 0;
for (int i = 0; i < pages; i++)
{
pagerTemplate.append(pagerFunction.apply(i));
breakit++;
if (breakit > 5)
{
pagerTemplate.append("</tr><tr>");
breakit = 0;
}
}
}
if (page >= pages)
{
page = pages - 1;
}
int start = 0;
if (page > 0)
{
start = elementsPerPage * page;
}
final StringBuilder sb = new StringBuilder();
int i = 0;
for (T element : elements)
{
if (i++ < start)
{
continue;
}
sb.append(bodyFunction.apply(element));
if (i >= (elementsPerPage + start))
{
break;
}
}
return new PageResult(pages, pagerTemplate, sb);
}
}

View File

@ -0,0 +1,113 @@
/*
* 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 HorridoJoho
*/
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,165 @@
/*
* 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 HorridoJoho
*/
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,414 @@
/*
* 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.concurrent.CopyOnWriteArrayList;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.holders.MinionHolder;
import com.l2jmobius.gameserver.taskmanager.DecayTaskManager;
import com.l2jmobius.util.Rnd;
/**
* @author luisantonioa, DS
*/
public class MinionList
{
private static final Logger _log = Logger.getLogger(MinionList.class.getName());
protected final L2MonsterInstance _master;
/** List containing the current spawned minions */
private final List<L2MonsterInstance> _minionReferences = new CopyOnWriteArrayList<>();
/** List containing the cached deleted minions for reuse */
protected List<L2MonsterInstance> _reusedMinionReferences = null;
public MinionList(L2MonsterInstance pMaster)
{
if (pMaster == null)
{
throw new NullPointerException("MinionList: master is null");
}
_master = pMaster;
}
/**
* @return list of the spawned (alive) minions.
*/
public List<L2MonsterInstance> getSpawnedMinions()
{
return _minionReferences;
}
/**
* Manage the spawn of Minions.<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>
* @param minions
*/
public final void spawnMinions(final List<MinionHolder> minions)
{
if (_master.isAlikeDead())
{
return;
}
// List<MinionHolder> minions = _master.getTemplate().getParameters().getMinionList("Privates");
if (minions == null)
{
return;
}
int minionCount, minionId;
long minionsToSpawn;
for (MinionHolder minion : minions)
{
minionCount = minion.getCount();
minionId = minion.getId();
minionsToSpawn = minionCount - countSpawnedMinionsById(minionId);
if (minionsToSpawn > 0)
{
for (int i = 0; i < minionsToSpawn; i++)
{
spawnMinion(minionId);
}
}
}
// remove non-needed minions
deleteReusedMinions();
}
/**
* Delete all spawned minions and try to reuse them.
*/
public void deleteSpawnedMinions()
{
if (!_minionReferences.isEmpty())
{
for (L2MonsterInstance minion : _minionReferences)
{
if (minion != null)
{
minion.setLeader(null);
minion.deleteMe();
if (_reusedMinionReferences != null)
{
_reusedMinionReferences.add(minion);
}
}
}
_minionReferences.clear();
}
}
/**
* Delete all reused minions to prevent memory leaks.
*/
public void deleteReusedMinions()
{
if (_reusedMinionReferences != null)
{
_reusedMinionReferences.clear();
}
}
// hooks
/**
* Called on the master spawn Old minions (from previous spawn) are deleted. If master can respawn - enabled reuse of the killed minions.
*/
public void onMasterSpawn()
{
deleteSpawnedMinions();
// if master has spawn and can respawn - try to reuse minions
if ((_reusedMinionReferences == null) && (_master.getTemplate().getParameters().getSet().get("SummonPrivateRate") == null) && !_master.getTemplate().getParameters().getMinionList("Privates").isEmpty() && (_master.getSpawn() != null) && _master.getSpawn().isRespawnEnabled())
{
_reusedMinionReferences = new CopyOnWriteArrayList<>();
}
}
/**
* Called on the minion spawn and added them in the list of the spawned minions.
* @param minion
*/
public void onMinionSpawn(L2MonsterInstance minion)
{
_minionReferences.add(minion);
}
/**
* Called on the master death/delete.
* @param force if true - force delete of the spawned minions By default minions deleted only for raidbosses
*/
public void onMasterDie(boolean force)
{
if (_master.isRaid() || force)
{
deleteSpawnedMinions();
}
}
/**
* Called on the minion death/delete. Removed minion from the list of the spawned minions and reuse if possible.
* @param minion
* @param respawnTime (ms) enable respawning of this minion while master is alive. -1 - use default value: 0 (disable) for mobs and config value for raids.
*/
public void onMinionDie(L2MonsterInstance minion, int respawnTime)
{
minion.setLeader(null); // prevent memory leaks
_minionReferences.remove(minion);
if (_reusedMinionReferences != null)
{
_reusedMinionReferences.add(minion);
}
final int time = respawnTime < 0 ? _master.isRaid() ? (int) Config.RAID_MINION_RESPAWN_TIMER : 0 : respawnTime;
if ((time > 0) && !_master.isAlikeDead())
{
ThreadPoolManager.getInstance().scheduleGeneral(new MinionRespawnTask(minion), time);
}
}
/**
* Called if master/minion was attacked. Master and all free minions receive aggro against attacker.
* @param caller
* @param attacker
*/
public void onAssist(L2Character caller, L2Character attacker)
{
if (attacker == null)
{
return;
}
if (!_master.isAlikeDead() && !_master.isInCombat())
{
_master.addDamageHate(attacker, 0, 1);
}
final boolean callerIsMaster = caller == _master;
int aggro = callerIsMaster ? 10 : 1;
if (_master.isRaid())
{
aggro *= 10;
}
for (L2MonsterInstance minion : _minionReferences)
{
if ((minion != null) && !minion.isDead() && (callerIsMaster || !minion.isInCombat()))
{
minion.addDamageHate(attacker, 0, aggro);
}
}
}
/**
* Called from onTeleported() of the master Alive and able to move minions teleported to master.
*/
public void onMasterTeleported()
{
final int offset = 200;
final int minRadius = (int) _master.getCollisionRadius() + 30;
for (L2MonsterInstance minion : _minionReferences)
{
if ((minion != null) && !minion.isDead() && !minion.isMovementDisabled())
{
int newX = Rnd.get(minRadius * 2, offset * 2); // x
int newY = Rnd.get(newX, offset * 2); // distance
newY = (int) Math.sqrt((newY * newY) - (newX * newX)); // y
if (newX > (offset + minRadius))
{
newX = (_master.getX() + newX) - offset;
}
else
{
newX = (_master.getX() - newX) + minRadius;
}
if (newY > (offset + minRadius))
{
newY = (_master.getY() + newY) - offset;
}
else
{
newY = (_master.getY() - newY) + minRadius;
}
minion.teleToLocation(new Location(newX, newY, _master.getZ()));
}
}
}
private final void spawnMinion(int minionId)
{
if (minionId == 0)
{
return;
}
// searching in reused minions
if (_reusedMinionReferences != null)
{
final L2MonsterInstance minion = _reusedMinionReferences.stream().filter(m -> (m.getId() == minionId)).findFirst().orElse(null);
if (minion != null)
{
DecayTaskManager.getInstance().cancel(minion);
minion.onDecay();
_reusedMinionReferences.remove(minion);
minion.refreshID();
initializeNpcInstance(_master, minion);
return;
}
}
// not found in cache
spawnMinion(_master, minionId);
}
private final class MinionRespawnTask implements Runnable
{
private final L2MonsterInstance _minion;
public MinionRespawnTask(L2MonsterInstance minion)
{
_minion = minion;
}
@Override
public void run()
{
if (!_master.isAlikeDead() && _master.isVisible())
{
// minion can be already spawned or deleted
if (!_minion.isVisible())
{
if (_reusedMinionReferences != null)
{
_reusedMinionReferences.remove(_minion);
}
_minion.refreshID();
initializeNpcInstance(_master, _minion);
}
}
}
}
/**
* 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 master L2MonsterInstance used as master for this minion
* @param minionId The L2NpcTemplate Identifier of the Minion to spawn
* @return
*/
public static final L2MonsterInstance spawnMinion(L2MonsterInstance master, int minionId)
{
// Get the template of the Minion to spawn
final L2NpcTemplate minionTemplate = NpcData.getInstance().getTemplate(minionId);
if (minionTemplate == null)
{
return null;
}
return initializeNpcInstance(master, new L2MonsterInstance(minionTemplate));
}
protected static final L2MonsterInstance initializeNpcInstance(L2MonsterInstance master, L2MonsterInstance minion)
{
minion.stopAllEffects();
minion.setIsDead(false);
minion.setDecayed(false);
// Set the Minion HP, MP and Heading
minion.setCurrentHpMp(minion.getMaxHp(), minion.getMaxMp());
minion.setHeading(master.getHeading());
// Set the Minion leader to this RaidBoss
minion.setLeader(master);
// move monster to masters instance
minion.setInstanceId(master.getInstanceId());
// Init the position of the Minion and add it in the world as a visible object
final int offset = 200;
final int minRadius = (int) master.getCollisionRadius() + 30;
int newX = Rnd.get(minRadius * 2, offset * 2); // x
int newY = Rnd.get(newX, offset * 2); // distance
newY = (int) Math.sqrt((newY * newY) - (newX * newX)); // y
if (newX > (offset + minRadius))
{
newX = (master.getX() + newX) - offset;
}
else
{
newX = (master.getX() - newX) + minRadius;
}
if (newY > (offset + minRadius))
{
newY = (master.getY() + newY) - offset;
}
else
{
newY = (master.getY() - newY) + minRadius;
}
minion.spawnMe(newX, newY, master.getZ());
if (Config.DEBUG)
{
_log.info("Spawned minion template " + minion.getId() + " with objid: " + minion.getObjectId() + " to boss " + master.getObjectId() + " ,at: " + minion.getX() + " x, " + minion.getY() + " y, " + minion.getZ() + " z");
}
return minion;
}
// Statistics part
private final long countSpawnedMinionsById(int minionId)
{
return _minionReferences.stream().filter(npc -> npc.getId() == minionId).count();
}
public final int countSpawnedMinions()
{
return _minionReferences.size();
}
public final long lazyCountSpawnedMinionsGroups()
{
return _minionReferences.stream().map(L2MonsterInstance::getId).distinct().count();
}
}

File diff suppressed because it is too large Load Diff