Merged with released L2J-Unity files.

This commit is contained in:
mobiusdev
2016-06-12 01:34:09 +00:00
parent e003e87887
commit 635557f5da
18352 changed files with 3245113 additions and 2892959 deletions

View File

@@ -1,293 +1,325 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.AirShipTeleportList;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.instance.L2AirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2ControllableAirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jmobius.gameserver.network.serverpackets.ExAirShipTeleportList;
public class AirShipManager
{
private static final Logger _log = Logger.getLogger(AirShipManager.class.getName());
private static final String LOAD_DB = "SELECT * FROM airships";
private static final String ADD_DB = "INSERT INTO airships (owner_id,fuel) VALUES (?,?)";
private static final String UPDATE_DB = "UPDATE airships SET fuel=? WHERE owner_id=?";
private L2CharTemplate _airShipTemplate = null;
private final Map<Integer, StatsSet> _airShipsInfo = new HashMap<>();
private final Map<Integer, L2AirShipInstance> _airShips = new HashMap<>();
private final Map<Integer, AirShipTeleportList> _teleports = new HashMap<>();
protected AirShipManager()
{
final StatsSet npcDat = new StatsSet();
npcDat.set("npcId", 9);
npcDat.set("level", 0);
npcDat.set("jClass", "boat");
npcDat.set("baseShldDef", 0);
npcDat.set("baseShldRate", 0);
npcDat.set("baseAccCombat", 38);
npcDat.set("baseEvasRate", 38);
npcDat.set("baseCritRate", 38);
npcDat.set("collisionRadius", 0);
npcDat.set("collisionHeight", 0);
npcDat.set("sex", "male");
npcDat.set("type", "");
npcDat.set("baseAtkRange", 0);
npcDat.set("baseMpMax", 0);
npcDat.set("baseCpMax", 0);
npcDat.set("rewardExp", 0);
npcDat.set("rewardSp", 0);
npcDat.set("basePAtk", 0);
npcDat.set("baseMAtk", 0);
npcDat.set("basePAtkSpd", 0);
npcDat.set("aggroRange", 0);
npcDat.set("baseMAtkSpd", 0);
npcDat.set("rhand", 0);
npcDat.set("lhand", 0);
npcDat.set("armor", 0);
npcDat.set("baseWalkSpd", 0);
npcDat.set("baseRunSpd", 0);
npcDat.set("name", "AirShip");
npcDat.set("baseHpMax", 50000);
npcDat.set("baseHpReg", 3.e-3f);
npcDat.set("baseMpReg", 3.e-3f);
npcDat.set("basePDef", 100);
npcDat.set("baseMDef", 100);
_airShipTemplate = new L2CharTemplate(npcDat);
load();
}
public L2AirShipInstance getNewAirShip(int x, int y, int z, int heading)
{
final L2AirShipInstance airShip = new L2AirShipInstance(_airShipTemplate);
airShip.setHeading(heading);
airShip.setXYZInvisible(x, y, z);
airShip.spawnMe();
airShip.getStat().setMoveSpeed(280);
airShip.getStat().setRotationSpeed(2000);
return airShip;
}
public L2AirShipInstance getNewAirShip(int x, int y, int z, int heading, int ownerId)
{
final StatsSet info = _airShipsInfo.get(ownerId);
if (info == null)
{
return null;
}
final L2AirShipInstance airShip;
if (_airShips.containsKey(ownerId))
{
airShip = _airShips.get(ownerId);
airShip.refreshID();
}
else
{
airShip = new L2ControllableAirShipInstance(_airShipTemplate, ownerId);
_airShips.put(ownerId, airShip);
airShip.setMaxFuel(600);
airShip.setFuel(info.getInt("fuel"));
airShip.getStat().setMoveSpeed(280);
airShip.getStat().setRotationSpeed(2000);
}
airShip.setHeading(heading);
airShip.setXYZInvisible(x, y, z);
airShip.spawnMe();
return airShip;
}
public void removeAirShip(L2AirShipInstance ship)
{
if (ship.getOwnerId() == 0)
{
return;
}
storeInDb(ship.getOwnerId());
final StatsSet info = _airShipsInfo.get(ship.getOwnerId());
if (info != null)
{
info.set("fuel", ship.getFuel());
}
}
public boolean hasAirShipLicense(int ownerId)
{
return _airShipsInfo.containsKey(ownerId);
}
public void registerLicense(int ownerId)
{
if (_airShipsInfo.containsKey(ownerId))
{
return;
}
final StatsSet info = new StatsSet();
info.set("fuel", 600);
_airShipsInfo.put(ownerId, info);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(ADD_DB))
{
ps.setInt(1, ownerId);
ps.setInt(2, info.getInt("fuel"));
ps.executeUpdate();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not add new airship license: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing: " + e.getMessage(), e);
}
}
public boolean hasAirShip(int ownerId)
{
final L2AirShipInstance ship = _airShips.get(ownerId);
return (ship != null) && (ship.isVisible() || ship.isTeleporting());
}
public void registerAirShipTeleportList(int dockId, int locationId, VehiclePathPoint[][] tp, int[] fuelConsumption)
{
if (tp.length != fuelConsumption.length)
{
return;
}
_teleports.put(dockId, new AirShipTeleportList(locationId, fuelConsumption, tp));
}
public void sendAirShipTeleportList(L2PcInstance player)
{
if ((player == null) || !player.isInAirShip())
{
return;
}
final L2AirShipInstance ship = player.getAirShip();
if (!ship.isCaptain(player) || !ship.isInDock() || ship.isMoving())
{
return;
}
final int dockId = ship.getDockId();
if (!_teleports.containsKey(dockId))
{
return;
}
final AirShipTeleportList all = _teleports.get(dockId);
player.sendPacket(new ExAirShipTeleportList(all.getLocation(), all.getRoute(), all.getFuel()));
}
public VehiclePathPoint[] getTeleportDestination(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
return (all == null) || (index < -1) || (index >= all.getRoute().length) ? null : all.getRoute()[index + 1];
}
public int getFuelConsumption(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
return (all == null) || (index < -1) || (index >= all.getFuel().length) ? 0 : all.getFuel()[index + 1];
}
private void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(LOAD_DB))
{
StatsSet info;
while (rs.next())
{
info = new StatsSet();
info.set("fuel", rs.getInt("fuel"));
_airShipsInfo.put(rs.getInt("owner_id"), info);
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not load airships table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing: " + e.getMessage(), e);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _airShipsInfo.size() + " private airships");
}
private void storeInDb(int ownerId)
{
final StatsSet info = _airShipsInfo.get(ownerId);
if (info == null)
{
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(UPDATE_DB))
{
ps.setInt(1, info.getInt("fuel"));
ps.setInt(2, ownerId);
ps.executeUpdate();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not update airships table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while save: " + e.getMessage(), e);
}
}
public static AirShipManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AirShipManager _instance = new AirShipManager();
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.AirShipTeleportList;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.instance.L2AirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2ControllableAirShipInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jmobius.gameserver.network.serverpackets.ExAirShipTeleportList;
public class AirShipManager
{
private static final Logger LOGGER = Logger.getLogger(AirShipManager.class.getName());
private static final String LOAD_DB = "SELECT * FROM airships";
private static final String ADD_DB = "INSERT INTO airships (owner_id,fuel) VALUES (?,?)";
private static final String UPDATE_DB = "UPDATE airships SET fuel=? WHERE owner_id=?";
private L2CharTemplate _airShipTemplate = null;
private final Map<Integer, StatsSet> _airShipsInfo = new HashMap<>();
private final Map<Integer, L2AirShipInstance> _airShips = new HashMap<>();
private final Map<Integer, AirShipTeleportList> _teleports = new HashMap<>();
protected AirShipManager()
{
final StatsSet npcDat = new StatsSet();
npcDat.set("npcId", 9);
npcDat.set("level", 0);
npcDat.set("jClass", "boat");
npcDat.set("baseSTR", 0);
npcDat.set("baseCON", 0);
npcDat.set("baseDEX", 0);
npcDat.set("baseINT", 0);
npcDat.set("baseWIT", 0);
npcDat.set("baseMEN", 0);
npcDat.set("baseShldDef", 0);
npcDat.set("baseShldRate", 0);
npcDat.set("baseAccCombat", 38);
npcDat.set("baseEvasRate", 38);
npcDat.set("baseCritRate", 38);
npcDat.set("collision_radius", 0);
npcDat.set("collision_height", 0);
npcDat.set("sex", "male");
npcDat.set("type", "");
npcDat.set("baseAtkRange", 0);
npcDat.set("baseMpMax", 0);
npcDat.set("baseCpMax", 0);
npcDat.set("rewardExp", 0);
npcDat.set("rewardSp", 0);
npcDat.set("basePAtk", 0);
npcDat.set("baseMAtk", 0);
npcDat.set("basePAtkSpd", 0);
npcDat.set("aggroRange", 0);
npcDat.set("baseMAtkSpd", 0);
npcDat.set("rhand", 0);
npcDat.set("lhand", 0);
npcDat.set("armor", 0);
npcDat.set("baseWalkSpd", 0);
npcDat.set("baseRunSpd", 0);
npcDat.set("name", "AirShip");
npcDat.set("baseHpMax", 50000);
npcDat.set("baseHpReg", 3.e-3f);
npcDat.set("baseMpReg", 3.e-3f);
npcDat.set("basePDef", 100);
npcDat.set("baseMDef", 100);
_airShipTemplate = new L2CharTemplate(npcDat);
load();
}
public L2AirShipInstance getNewAirShip(int x, int y, int z, int heading)
{
final L2AirShipInstance airShip = new L2AirShipInstance(_airShipTemplate);
airShip.setHeading(heading);
airShip.setXYZInvisible(x, y, z);
airShip.spawnMe();
airShip.getStat().setMoveSpeed(280);
airShip.getStat().setRotationSpeed(2000);
return airShip;
}
public L2AirShipInstance getNewAirShip(int x, int y, int z, int heading, int ownerId)
{
final StatsSet info = _airShipsInfo.get(ownerId);
if (info == null)
{
return null;
}
final L2AirShipInstance airShip;
if (_airShips.containsKey(ownerId))
{
airShip = _airShips.get(ownerId);
airShip.refreshID();
}
else
{
airShip = new L2ControllableAirShipInstance(_airShipTemplate, ownerId);
_airShips.put(ownerId, airShip);
airShip.setMaxFuel(600);
airShip.setFuel(info.getInt("fuel"));
airShip.getStat().setMoveSpeed(280);
airShip.getStat().setRotationSpeed(2000);
}
airShip.setHeading(heading);
airShip.setXYZInvisible(x, y, z);
airShip.spawnMe();
return airShip;
}
public void removeAirShip(L2AirShipInstance ship)
{
if (ship.getOwnerId() != 0)
{
storeInDb(ship.getOwnerId());
final StatsSet info = _airShipsInfo.get(ship.getOwnerId());
if (info != null)
{
info.set("fuel", ship.getFuel());
}
}
}
public boolean hasAirShipLicense(int ownerId)
{
return _airShipsInfo.containsKey(ownerId);
}
public void registerLicense(int ownerId)
{
if (!_airShipsInfo.containsKey(ownerId))
{
final StatsSet info = new StatsSet();
info.set("fuel", 600);
_airShipsInfo.put(ownerId, info);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(ADD_DB))
{
ps.setInt(1, ownerId);
ps.setInt(2, info.getInt("fuel"));
ps.executeUpdate();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not add new airship license: ", e);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing: ", e);
}
}
}
public boolean hasAirShip(int ownerId)
{
final L2AirShipInstance ship = _airShips.get(ownerId);
if ((ship == null) || !(ship.isSpawned() || ship.isTeleporting()))
{
return false;
}
return true;
}
public void registerAirShipTeleportList(int dockId, int locationId, VehiclePathPoint[][] tp, int[] fuelConsumption)
{
if (tp.length != fuelConsumption.length)
{
return;
}
_teleports.put(dockId, new AirShipTeleportList(locationId, fuelConsumption, tp));
}
public void sendAirShipTeleportList(L2PcInstance player)
{
if ((player == null) || !player.isInAirShip())
{
return;
}
final L2AirShipInstance ship = player.getAirShip();
if (!ship.isCaptain(player) || !ship.isInDock() || ship.isMoving())
{
return;
}
final int dockId = ship.getDockId();
if (!_teleports.containsKey(dockId))
{
return;
}
final AirShipTeleportList all = _teleports.get(dockId);
player.sendPacket(new ExAirShipTeleportList(all.getLocation(), all.getRoute(), all.getFuel()));
}
public VehiclePathPoint[] getTeleportDestination(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
if (all == null)
{
return null;
}
if ((index < -1) || (index >= all.getRoute().length))
{
return null;
}
return all.getRoute()[index + 1];
}
public int getFuelConsumption(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
if (all == null)
{
return 0;
}
if ((index < -1) || (index >= all.getFuel().length))
{
return 0;
}
return all.getFuel()[index + 1];
}
private void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(LOAD_DB))
{
StatsSet info;
while (rs.next())
{
info = new StatsSet();
info.set("fuel", rs.getInt("fuel"));
_airShipsInfo.put(rs.getInt("owner_id"), info);
}
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not load airships table: ", e);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing: ", e);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _airShipsInfo.size() + " private airships");
}
private void storeInDb(int ownerId)
{
final StatsSet info = _airShipsInfo.get(ownerId);
if (info == null)
{
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(UPDATE_DB))
{
ps.setInt(1, info.getInt("fuel"));
ps.setInt(2, ownerId);
ps.executeUpdate();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not update airships table: ", e);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while save: ", e);
}
}
public static AirShipManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AirShipManager _instance = new AirShipManager();
}
}

View File

@@ -1,258 +1,278 @@
/*
* 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.instancemanager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.L2GameClient;
public final class AntiFeedManager
{
public static final int GAME_ID = 0;
public static final int OLYMPIAD_ID = 1;
public static final int TVT_ID = 2;
public static final int L2EVENT_ID = 3;
private final Map<Integer, Long> _lastDeathTimes = new ConcurrentHashMap<>();
private final Map<Integer, Map<Integer, AtomicInteger>> _eventIPs = new ConcurrentHashMap<>();
protected AntiFeedManager()
{
}
/**
* Set time of the last player's death to current
* @param objectId Player's objectId
*/
public final void setLastDeathTime(int objectId)
{
_lastDeathTimes.put(objectId, System.currentTimeMillis());
}
/**
* Check if current kill should be counted as non-feeded.
* @param attacker Attacker character
* @param target Target character
* @return True if kill is non-feeded.
*/
public final boolean check(L2Character attacker, L2Character target)
{
if (!Config.ANTIFEED_ENABLE)
{
return true;
}
if (target == null)
{
return false;
}
final L2PcInstance targetPlayer = target.getActingPlayer();
if ((targetPlayer == null) || ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId()) && ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL)))
{
return false;
}
if (!Config.ANTIFEED_DUALBOX || (attacker == null))
{
return true;
}
final L2PcInstance attackerPlayer = attacker.getActingPlayer();
if (attackerPlayer == null)
{
return false;
}
final L2GameClient targetClient = targetPlayer.getClient();
final L2GameClient attackerClient = attackerPlayer.getClient();
return (targetClient == null) || (attackerClient == null) || targetClient.isDetached() || attackerClient.isDetached() ? !Config.ANTIFEED_DISCONNECTED_AS_DUALBOX : !targetClient.getConnectionAddress().equals(attackerClient.getConnectionAddress());
}
/**
* Clears all timestamps
*/
public final void clear()
{
_lastDeathTimes.clear();
}
/**
* Register new event for dualbox check. Should be called only once.
* @param eventId
*/
public final void registerEvent(int eventId)
{
_eventIPs.putIfAbsent(eventId, new ConcurrentHashMap<Integer, AtomicInteger>());
}
/**
* @param eventId
* @param player
* @param max
* @return If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true.<br>
* False if number of all simultaneous connections from player's IP address higher than max.
*/
public final boolean tryAddPlayer(int eventId, L2PcInstance player, int max)
{
return tryAddClient(eventId, player.getClient(), max);
}
/**
* @param eventId
* @param client
* @param max
* @return If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true.<br>
* False if number of all simultaneous connections from player's IP address higher than max.
*/
public final boolean tryAddClient(int eventId, L2GameClient client, int max)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
final AtomicInteger connectionCount = event.computeIfAbsent(addrHash, k -> new AtomicInteger());
if ((connectionCount.get() + 1) > (max + Config.L2JMOD_DUALBOX_CHECK_WHITELIST.getOrDefault(addrHash, 0)))
{
return false;
}
connectionCount.incrementAndGet();
return true;
}
/**
* Decreasing number of active connection from player's IP address
* @param eventId
* @param player
* @return true if success and false if any problem detected.
*/
public final boolean removePlayer(int eventId, L2PcInstance player)
{
return removeClient(eventId, player.getClient());
}
/**
* Decreasing number of active connection from player's IP address
* @param eventId
* @param client
* @return true if success and false if any problem detected.
*/
public final boolean removeClient(int eventId, L2GameClient client)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
return event.computeIfPresent(addrHash, (k, v) ->
{
if ((v == null) || (v.decrementAndGet() == 0))
{
return null;
}
return v;
}) != null;
}
/**
* Remove player connection IP address from all registered events lists.
* @param client
*/
public final void onDisconnect(L2GameClient client)
{
if (client == null)
{
return;
}
_eventIPs.forEach((k, v) ->
{
removeClient(k, client);
});
}
/**
* Clear all entries for this eventId.
* @param eventId
*/
public final void clear(int eventId)
{
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event != null)
{
event.clear();
}
}
/**
* @param player
* @param max
* @return maximum number of allowed connections (whitelist + max)
*/
public final int getLimit(L2PcInstance player, int max)
{
return getLimit(player.getClient(), max);
}
/**
* @param client
* @param max
* @return maximum number of allowed connections (whitelist + max)
*/
public final int getLimit(L2GameClient client, int max)
{
if (client == null)
{
return max;
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
return Config.L2JMOD_DUALBOX_CHECK_WHITELIST.containsKey(addrHash) ? max + Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash) : max;
}
public static AntiFeedManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AntiFeedManager _instance = new AntiFeedManager();
}
/*
* 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.instancemanager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.client.L2GameClient;
public final class AntiFeedManager
{
public static final int GAME_ID = 0;
public static final int OLYMPIAD_ID = 1;
public static final int TVT_ID = 2;
public static final int L2EVENT_ID = 3;
private final Map<Integer, Long> _lastDeathTimes = new ConcurrentHashMap<>();
private final Map<Integer, Map<Integer, AtomicInteger>> _eventIPs = new ConcurrentHashMap<>();
protected AntiFeedManager()
{
}
/**
* Set time of the last player's death to current
* @param objectId Player's objectId
*/
public final void setLastDeathTime(int objectId)
{
_lastDeathTimes.put(objectId, System.currentTimeMillis());
}
/**
* Check if current kill should be counted as non-feeded.
* @param attacker Attacker character
* @param target Target character
* @return True if kill is non-feeded.
*/
public final boolean check(L2Character attacker, L2Character target)
{
if (!Config.ANTIFEED_ENABLE)
{
return true;
}
if (target == null)
{
return false;
}
final L2PcInstance targetPlayer = target.getActingPlayer();
if (targetPlayer == null)
{
return false;
}
if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId()))
{
if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL)
{
return false;
}
}
if (Config.ANTIFEED_DUALBOX && (attacker != null))
{
final L2PcInstance attackerPlayer = attacker.getActingPlayer();
if (attackerPlayer == null)
{
return false;
}
final L2GameClient targetClient = targetPlayer.getClient();
final L2GameClient attackerClient = attackerPlayer.getClient();
if ((targetClient == null) || (attackerClient == null) || targetClient.isDetached() || attackerClient.isDetached())
{
// unable to check ip address
return !Config.ANTIFEED_DISCONNECTED_AS_DUALBOX;
}
return !targetClient.getConnectionAddress().equals(attackerClient.getConnectionAddress());
}
return true;
}
/**
* Clears all timestamps
*/
public final void clear()
{
_lastDeathTimes.clear();
}
/**
* Register new event for dualbox check. Should be called only once.
* @param eventId
*/
public final void registerEvent(int eventId)
{
_eventIPs.putIfAbsent(eventId, new ConcurrentHashMap<>());
}
/**
* @param eventId
* @param player
* @param max
* @return If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true.<br>
* False if number of all simultaneous connections from player's IP address higher than max.
*/
public final boolean tryAddPlayer(int eventId, L2PcInstance player, int max)
{
return tryAddClient(eventId, player.getClient(), max);
}
/**
* @param eventId
* @param client
* @param max
* @return If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true.<br>
* False if number of all simultaneous connections from player's IP address higher than max.
*/
public final boolean tryAddClient(int eventId, L2GameClient client, int max)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
final AtomicInteger connectionCount = event.computeIfAbsent(addrHash, k -> new AtomicInteger());
if ((connectionCount.get() + 1) <= (max + Config.L2JMOD_DUALBOX_CHECK_WHITELIST.getOrDefault(addrHash, 0)))
{
connectionCount.incrementAndGet();
return true;
}
return false;
}
/**
* Decreasing number of active connection from player's IP address
* @param eventId
* @param player
* @return true if success and false if any problem detected.
*/
public final boolean removePlayer(int eventId, L2PcInstance player)
{
return removeClient(eventId, player.getClient());
}
/**
* Decreasing number of active connection from player's IP address
* @param eventId
* @param client
* @return true if success and false if any problem detected.
*/
public final boolean removeClient(int eventId, L2GameClient client)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
return event.computeIfPresent(addrHash, (k, v) ->
{
if ((v == null) || (v.decrementAndGet() == 0))
{
return null;
}
return v;
}) != null;
}
/**
* Remove player connection IP address from all registered events lists.
* @param client
*/
public final void onDisconnect(L2GameClient client)
{
if (client == null)
{
return;
}
_eventIPs.forEach((k, v) ->
{
removeClient(k, client);
});
}
/**
* Clear all entries for this eventId.
* @param eventId
*/
public final void clear(int eventId)
{
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event != null)
{
event.clear();
}
}
/**
* @param player
* @param max
* @return maximum number of allowed connections (whitelist + max)
*/
public final int getLimit(L2PcInstance player, int max)
{
return getLimit(player.getClient(), max);
}
/**
* @param client
* @param max
* @return maximum number of allowed connections (whitelist + max)
*/
public final int getLimit(L2GameClient client, int max)
{
if (client == null)
{
return max;
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
int limit = max;
if (Config.L2JMOD_DUALBOX_CHECK_WHITELIST.containsKey(addrHash))
{
limit += Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash);
}
return limit;
}
public static AntiFeedManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AntiFeedManager _instance = new AntiFeedManager();
}
}

View File

@@ -1,202 +1,208 @@
/*
* 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.instancemanager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.instance.L2BoatInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
public class BoatManager
{
private final Map<Integer, L2BoatInstance> _boats = new ConcurrentHashMap<>();
private final boolean[] _docksBusy = new boolean[3];
public static final int TALKING_ISLAND = 1;
public static final int GLUDIN_HARBOR = 2;
public static final int RUNE_HARBOR = 3;
public static BoatManager getInstance()
{
return SingletonHolder._instance;
}
protected BoatManager()
{
for (int i = 0; i < _docksBusy.length; i++)
{
_docksBusy[i] = false;
}
}
public L2BoatInstance getNewBoat(int boatId, int x, int y, int z, int heading)
{
if (!Config.ALLOW_BOAT)
{
return null;
}
final StatsSet npcDat = new StatsSet();
npcDat.set("npcId", boatId);
npcDat.set("level", 0);
npcDat.set("jClass", "boat");
npcDat.set("baseShldDef", 0);
npcDat.set("baseShldRate", 0);
npcDat.set("baseAccCombat", 38);
npcDat.set("baseEvasRate", 38);
npcDat.set("baseCritRate", 38);
// npcDat.set("name", "");
npcDat.set("collisionRadius", 0);
npcDat.set("collisionHeight", 0);
npcDat.set("sex", "male");
npcDat.set("type", "");
npcDat.set("baseAtkRange", 0);
npcDat.set("baseMpMax", 0);
npcDat.set("baseCpMax", 0);
npcDat.set("rewardExp", 0);
npcDat.set("rewardSp", 0);
npcDat.set("basePAtk", 0);
npcDat.set("baseMAtk", 0);
npcDat.set("basePAtkSpd", 0);
npcDat.set("aggroRange", 0);
npcDat.set("baseMAtkSpd", 0);
npcDat.set("rhand", 0);
npcDat.set("lhand", 0);
npcDat.set("armor", 0);
npcDat.set("baseWalkSpd", 0);
npcDat.set("baseRunSpd", 0);
npcDat.set("baseHpMax", 50000);
npcDat.set("baseHpReg", 3.e-3f);
npcDat.set("baseMpReg", 3.e-3f);
npcDat.set("basePDef", 100);
npcDat.set("baseMDef", 100);
final L2BoatInstance boat = new L2BoatInstance(new L2CharTemplate(npcDat));
boat.setHeading(heading);
boat.setXYZInvisible(x, y, z);
boat.spawnMe();
_boats.put(boat.getObjectId(), boat);
return boat;
}
/**
* @param boatId
* @return
*/
public L2BoatInstance getBoat(int boatId)
{
return _boats.get(boatId);
}
/**
* Lock/unlock dock so only one ship can be docked
* @param h Dock Id
* @param value True if dock is locked
*/
public void dockShip(int h, boolean value)
{
try
{
_docksBusy[h] = value;
}
catch (ArrayIndexOutOfBoundsException e)
{
}
}
/**
* Check if dock is busy
* @param h Dock Id
* @return Trye if dock is locked
*/
public boolean dockBusy(int h)
{
try
{
return _docksBusy[h];
}
catch (ArrayIndexOutOfBoundsException e)
{
return false;
}
}
/**
* Broadcast one packet in both path points
* @param point1
* @param point2
* @param packet
*/
public void broadcastPacket(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket packet)
{
broadcastPacketsToPlayers(point1, point2, packet);
}
/**
* Broadcast several packets in both path points
* @param point1
* @param point2
* @param packets
*/
public void broadcastPackets(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket... packets)
{
broadcastPacketsToPlayers(point1, point2, packets);
}
private void broadcastPacketsToPlayers(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket... packets)
{
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
double dx = (double) player.getX() - point1.getX();
double dy = (double) player.getY() - point1.getY();
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (L2GameServerPacket p : packets)
{
player.sendPacket(p);
}
}
else
{
dx = (double) player.getX() - point2.getX();
dy = (double) player.getY() - point2.getY();
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (L2GameServerPacket p : packets)
{
player.sendPacket(p);
}
}
}
}
}
private static class SingletonHolder
{
protected static final BoatManager _instance = new BoatManager();
}
/*
* 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.instancemanager;
import java.util.HashMap;
import java.util.Map;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.instance.L2BoatInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
public class BoatManager
{
private final Map<Integer, L2BoatInstance> _boats = new HashMap<>();
private final boolean[] _docksBusy = new boolean[3];
public static final int TALKING_ISLAND = 1;
public static final int GLUDIN_HARBOR = 2;
public static final int RUNE_HARBOR = 3;
public static BoatManager getInstance()
{
return SingletonHolder._instance;
}
protected BoatManager()
{
for (int i = 0; i < _docksBusy.length; i++)
{
_docksBusy[i] = false;
}
}
public L2BoatInstance getNewBoat(int boatId, int x, int y, int z, int heading)
{
if (!Config.ALLOW_BOAT)
{
return null;
}
final StatsSet npcDat = new StatsSet();
npcDat.set("npcId", boatId);
npcDat.set("level", 0);
npcDat.set("jClass", "boat");
npcDat.set("baseSTR", 0);
npcDat.set("baseCON", 0);
npcDat.set("baseDEX", 0);
npcDat.set("baseINT", 0);
npcDat.set("baseWIT", 0);
npcDat.set("baseMEN", 0);
npcDat.set("baseShldDef", 0);
npcDat.set("baseShldRate", 0);
npcDat.set("baseAccCombat", 38);
npcDat.set("baseEvasRate", 38);
npcDat.set("baseCritRate", 38);
// npcDat.set("name", "");
npcDat.set("collision_radius", 0);
npcDat.set("collision_height", 0);
npcDat.set("sex", "male");
npcDat.set("type", "");
npcDat.set("baseAtkRange", 0);
npcDat.set("baseMpMax", 0);
npcDat.set("baseCpMax", 0);
npcDat.set("rewardExp", 0);
npcDat.set("rewardSp", 0);
npcDat.set("basePAtk", 0);
npcDat.set("baseMAtk", 0);
npcDat.set("basePAtkSpd", 0);
npcDat.set("aggroRange", 0);
npcDat.set("baseMAtkSpd", 0);
npcDat.set("rhand", 0);
npcDat.set("lhand", 0);
npcDat.set("armor", 0);
npcDat.set("baseWalkSpd", 0);
npcDat.set("baseRunSpd", 0);
npcDat.set("baseHpMax", 50000);
npcDat.set("baseHpReg", 3.e-3f);
npcDat.set("baseMpReg", 3.e-3f);
npcDat.set("basePDef", 100);
npcDat.set("baseMDef", 100);
final L2CharTemplate template = new L2CharTemplate(npcDat);
final L2BoatInstance boat = new L2BoatInstance(template);
_boats.put(boat.getObjectId(), boat);
boat.setHeading(heading);
boat.setXYZInvisible(x, y, z);
boat.spawnMe();
return boat;
}
/**
* @param boatId
* @return
*/
public L2BoatInstance getBoat(int boatId)
{
return _boats.get(boatId);
}
/**
* Lock/unlock dock so only one ship can be docked
* @param h Dock Id
* @param value True if dock is locked
*/
public void dockShip(int h, boolean value)
{
try
{
_docksBusy[h] = value;
}
catch (ArrayIndexOutOfBoundsException e)
{
}
}
/**
* Check if dock is busy
* @param h Dock Id
* @return Trye if dock is locked
*/
public boolean dockBusy(int h)
{
try
{
return _docksBusy[h];
}
catch (ArrayIndexOutOfBoundsException e)
{
return false;
}
}
/**
* Broadcast one packet in both path points
* @param point1
* @param point2
* @param packet
*/
public void broadcastPacket(VehiclePathPoint point1, VehiclePathPoint point2, IClientOutgoingPacket packet)
{
broadcastPacketsToPlayers(point1, point2, packet);
}
/**
* Broadcast several packets in both path points
* @param point1
* @param point2
* @param packets
*/
public void broadcastPackets(VehiclePathPoint point1, VehiclePathPoint point2, IClientOutgoingPacket... packets)
{
broadcastPacketsToPlayers(point1, point2, packets);
}
private void broadcastPacketsToPlayers(VehiclePathPoint point1, VehiclePathPoint point2, IClientOutgoingPacket... packets)
{
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
double dx = (double) player.getX() - point1.getX();
double dy = (double) player.getY() - point1.getY();
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (IClientOutgoingPacket p : packets)
{
player.sendPacket(p);
}
}
else
{
dx = (double) player.getX() - point2.getX();
dy = (double) player.getY() - point2.getY();
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (IClientOutgoingPacket p : packets)
{
player.sendPacket(p);
}
}
}
}
}
private static class SingletonHolder
{
protected static final BoatManager _instance = new BoatManager();
}
}

View File

@@ -1,209 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.clanhall.ClanHallSiegeEngine;
import com.l2jmobius.gameserver.model.entity.clanhall.SiegableHall;
import com.l2jmobius.gameserver.model.zone.type.L2ClanHallZone;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* @author BiggBoss
*/
public final class CHSiegeManager
{
private static final Logger _log = Logger.getLogger(CHSiegeManager.class.getName());
private static final String SQL_LOAD_HALLS = "SELECT * FROM siegable_clanhall";
private final Map<Integer, SiegableHall> _siegableHalls = new HashMap<>();
protected CHSiegeManager()
{
loadClanHalls();
}
private final void loadClanHalls()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(SQL_LOAD_HALLS))
{
_siegableHalls.clear();
while (rs.next())
{
final int id = rs.getInt("clanHallId");
final StatsSet set = new StatsSet();
set.set("id", id);
set.set("name", rs.getString("name"));
set.set("ownerId", rs.getInt("ownerId"));
set.set("desc", rs.getString("desc"));
set.set("location", rs.getString("location"));
set.set("nextSiege", rs.getLong("nextSiege"));
set.set("siegeLenght", rs.getLong("siegeLenght"));
set.set("scheduleConfig", rs.getString("schedule_config"));
final SiegableHall hall = new SiegableHall(set);
_siegableHalls.put(id, hall);
ClanHallManager.addClanHall(hall);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _siegableHalls.size() + " conquerable clan halls.");
}
catch (Exception e)
{
_log.warning("CHSiegeManager: Could not load siegable clan halls!:" + e.getMessage());
}
}
public Map<Integer, SiegableHall> getConquerableHalls()
{
return _siegableHalls;
}
public SiegableHall getSiegableHall(int clanHall)
{
return getConquerableHalls().get(clanHall);
}
public final SiegableHall getNearbyClanHall(L2Character activeChar)
{
return getNearbyClanHall(activeChar.getX(), activeChar.getY(), 10000);
}
public final SiegableHall getNearbyClanHall(int x, int y, int maxDist)
{
L2ClanHallZone zone = null;
for (Map.Entry<Integer, SiegableHall> ch : _siegableHalls.entrySet())
{
zone = ch.getValue().getZone();
if ((zone != null) && (zone.getDistanceToZone(x, y) < maxDist))
{
return ch.getValue();
}
}
return null;
}
public final ClanHallSiegeEngine getSiege(L2Character character)
{
final SiegableHall hall = getNearbyClanHall(character);
return hall == null ? null : hall.getSiege();
}
public final void registerClan(L2Clan clan, SiegableHall hall, L2PcInstance player)
{
if (clan.getLevel() < Config.CHS_CLAN_MINLEVEL)
{
player.sendMessage("Only clans of level " + Config.CHS_CLAN_MINLEVEL + " or higher may register for a castle siege");
}
else if (hall.isWaitingBattle())
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_DEADLINE_TO_REGISTER_FOR_THE_SIEGE_OF_S1_HAS_PASSED);
sm.addString(hall.getName());
player.sendPacket(sm);
}
else if (hall.isInSiege())
{
player.sendPacket(SystemMessageId.THIS_IS_NOT_THE_TIME_FOR_SIEGE_REGISTRATION_AND_SO_REGISTRATION_AND_CANCELLATION_CANNOT_BE_DONE);
}
else if (hall.getOwnerId() == clan.getId())
{
player.sendPacket(SystemMessageId.CASTLE_OWNING_CLANS_ARE_AUTOMATICALLY_REGISTERED_ON_THE_DEFENDING_SIDE);
}
else if ((clan.getCastleId() != 0) || (clan.getHideoutId() != 0))
{
player.sendPacket(SystemMessageId.A_CLAN_THAT_OWNS_A_CASTLE_CANNOT_PARTICIPATE_IN_ANOTHER_SIEGE);
}
else if (hall.getSiege().checkIsAttacker(clan))
{
player.sendPacket(SystemMessageId.YOU_HAVE_ALREADY_REQUESTED_A_CASTLE_SIEGE);
}
else if (isClanParticipating(clan))
{
player.sendPacket(SystemMessageId.YOUR_APPLICATION_HAS_BEEN_DENIED_BECAUSE_YOU_HAVE_ALREADY_SUBMITTED_A_REQUEST_FOR_ANOTHER_CASTLE_SIEGE);
}
else if (hall.getSiege().getAttackers().size() >= Config.CHS_MAX_ATTACKERS)
{
player.sendPacket(SystemMessageId.NO_MORE_REGISTRATIONS_MAY_BE_ACCEPTED_FOR_THE_ATTACKER_SIDE);
}
else
{
hall.addAttacker(clan);
}
}
public final void unRegisterClan(L2Clan clan, SiegableHall hall)
{
if (!hall.isRegistering())
{
return;
}
hall.removeAttacker(clan);
}
public final boolean isClanParticipating(L2Clan clan)
{
for (SiegableHall hall : getConquerableHalls().values())
{
if ((hall.getSiege() != null) && hall.getSiege().checkIsAttacker(clan))
{
return true;
}
}
return false;
}
public final void onServerShutDown()
{
for (SiegableHall hall : getConquerableHalls().values())
{
// Rainbow springs has his own attackers table
if ((hall.getId() == 62) || (hall.getSiege() == null))
{
continue;
}
hall.getSiege().saveAttackers();
}
}
public static CHSiegeManager getInstance()
{
return SingletonHolder._instance;
}
private static final class SingletonHolder
{
protected static final CHSiegeManager _instance = new CHSiegeManager();
}
}

View File

@@ -1,325 +1,276 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.InstanceListManager;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
public final class CastleManager implements InstanceListManager
{
private static final Logger _log = Logger.getLogger(CastleManager.class.getName());
private final List<Castle> _castles = new ArrayList<>();
private final Map<Integer, Long> _castleSiegeDate = new ConcurrentHashMap<>();
private static final int _castleCirclets[] =
{
0,
6838,
6835,
6839,
6837,
6840,
6834,
6836,
8182,
8183
};
public final int findNearestCastleIndex(L2Object obj)
{
return findNearestCastleIndex(obj, Long.MAX_VALUE);
}
public final int findNearestCastleIndex(L2Object obj, long maxDistance)
{
int index = getCastleIndex(obj);
if (index < 0)
{
double distance;
Castle castle;
for (int i = 0; i < _castles.size(); i++)
{
castle = _castles.get(i);
if (castle == null)
{
continue;
}
distance = castle.getDistance(obj);
if (maxDistance > distance)
{
maxDistance = (long) distance;
index = i;
}
}
}
return index;
}
public final Castle getCastleById(int castleId)
{
for (Castle temp : _castles)
{
if (temp.getResidenceId() == castleId)
{
return temp;
}
}
return null;
}
public final Castle getCastleByOwner(L2Clan clan)
{
for (Castle temp : _castles)
{
if (temp.getOwnerId() == clan.getId())
{
return temp;
}
}
return null;
}
public final Castle getCastle(String name)
{
for (Castle temp : _castles)
{
if (temp.getName().equalsIgnoreCase(name.trim()))
{
return temp;
}
}
return null;
}
public final Castle getCastle(int x, int y, int z)
{
for (Castle temp : _castles)
{
if (temp.checkIfInZone(x, y, z))
{
return temp;
}
}
return null;
}
public final Castle getCastle(L2Object activeObject)
{
return getCastle(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getCastleIndex(int castleId)
{
Castle castle;
for (int i = 0; i < _castles.size(); i++)
{
castle = _castles.get(i);
if ((castle != null) && (castle.getResidenceId() == castleId))
{
return i;
}
}
return -1;
}
public final int getCastleIndex(L2Object activeObject)
{
return getCastleIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getCastleIndex(int x, int y, int z)
{
Castle castle;
for (int i = 0; i < _castles.size(); i++)
{
castle = _castles.get(i);
if ((castle != null) && castle.checkIfInZone(x, y, z))
{
return i;
}
}
return -1;
}
public final List<Castle> getCastles()
{
return _castles;
}
public boolean hasOwnedCastle()
{
boolean hasOwnedCastle = false;
for (Castle castle : _castles)
{
if (castle.getOwnerId() > 0)
{
hasOwnedCastle = true;
break;
}
}
return hasOwnedCastle;
}
public int getCirclet()
{
return getCircletByCastleId(1);
}
public int getCircletByCastleId(int castleId)
{
return (castleId > 0) && (castleId < 10) ? _castleCirclets[castleId] : 0;
}
// remove this castle's circlets from the clan
public void removeCirclet(L2Clan clan, int castleId)
{
for (L2ClanMember member : clan.getMembers())
{
removeCirclet(member, castleId);
}
}
public void removeCirclet(L2ClanMember member, int castleId)
{
if (member == null)
{
return;
}
final L2PcInstance player = member.getPlayerInstance();
final int circletId = getCircletByCastleId(castleId);
if (circletId == 0)
{
return;
}
// online-player circlet removal
if (player != null)
{
try
{
final L2ItemInstance circlet = player.getInventory().getItemByItemId(circletId);
if (circlet != null)
{
if (circlet.isEquipped())
{
player.getInventory().unEquipItemInSlot(circlet.getLocationSlot());
}
player.destroyItemByItemId("CastleCircletRemoval", circletId, 1, player, true);
}
return;
}
catch (NullPointerException e)
{
// continue removing offline
}
}
// else offline-player circlet removal
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM items WHERE owner_id = ? and item_id = ?"))
{
ps.setInt(1, member.getObjectId());
ps.setInt(2, circletId);
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Failed to remove castle circlets offline for player " + member.getName() + ": " + e.getMessage(), e);
}
}
@Override
public void loadInstances()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM castle ORDER BY id"))
{
while (rs.next())
{
_castles.add(new Castle(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _castles.size() + " castles");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadCastleData(): " + e.getMessage(), e);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (Castle castle : _castles)
{
castle.activateInstance();
}
}
public void registerSiegeDate(int castleId, long siegeDate)
{
_castleSiegeDate.put(castleId, siegeDate);
}
public int getSiegeDates(long siegeDate)
{
int count = 0;
for (long date : _castleSiegeDate.values())
{
if (Math.abs(date - siegeDate) < 1000)
{
count++;
}
}
return count;
}
public static CastleManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CastleManager _instance = new CastleManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.InstanceListManager;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
public final class CastleManager implements InstanceListManager
{
private static final Logger LOGGER = Logger.getLogger(CastleManager.class.getName());
private final Map<Integer, Castle> _castles = new ConcurrentSkipListMap<>();
private final Map<Integer, Long> _castleSiegeDate = new ConcurrentHashMap<>();
private static final int _castleCirclets[] =
{
0,
6838,
6835,
6839,
6837,
6840,
6834,
6836,
8182,
8183
};
public final Castle findNearestCastle(L2Object obj)
{
return findNearestCastle(obj, Long.MAX_VALUE);
}
public final Castle findNearestCastle(L2Object obj, long maxDistance)
{
Castle nearestCastle = getCastle(obj);
if (nearestCastle == null)
{
double distance;
for (Castle castle : getCastles())
{
distance = castle.getDistance(obj);
if (maxDistance > distance)
{
maxDistance = (long) distance;
nearestCastle = castle;
}
}
}
return nearestCastle;
}
public final Castle getCastleById(int castleId)
{
return _castles.get(castleId);
}
public final Castle getCastleByOwner(L2Clan clan)
{
for (Castle temp : getCastles())
{
if (temp.getOwnerId() == clan.getId())
{
return temp;
}
}
return null;
}
public final Castle getCastle(String name)
{
for (Castle temp : getCastles())
{
if (temp.getName().equalsIgnoreCase(name.trim()))
{
return temp;
}
}
return null;
}
public final Castle getCastle(int x, int y, int z)
{
for (Castle temp : getCastles())
{
if (temp.checkIfInZone(x, y, z))
{
return temp;
}
}
return null;
}
public final Castle getCastle(L2Object activeObject)
{
return getCastle(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final Collection<Castle> getCastles()
{
return _castles.values();
}
public boolean hasOwnedCastle()
{
boolean hasOwnedCastle = false;
for (Castle castle : getCastles())
{
if (castle.getOwnerId() > 0)
{
hasOwnedCastle = true;
break;
}
}
return hasOwnedCastle;
}
public int getCircletByCastleId(int castleId)
{
if ((castleId > 0) && (castleId < 10))
{
return _castleCirclets[castleId];
}
return 0;
}
// remove this castle's circlets from the clan
public void removeCirclet(L2Clan clan, int castleId)
{
for (L2ClanMember member : clan.getMembers())
{
removeCirclet(member, castleId);
}
}
public void removeCirclet(L2ClanMember member, int castleId)
{
if (member == null)
{
return;
}
final L2PcInstance player = member.getPlayerInstance();
final int circletId = getCircletByCastleId(castleId);
if (circletId != 0)
{
// online-player circlet removal
if (player != null)
{
try
{
final L2ItemInstance circlet = player.getInventory().getItemByItemId(circletId);
if (circlet != null)
{
if (circlet.isEquipped())
{
player.getInventory().unEquipItemInSlot(circlet.getLocationSlot());
}
player.destroyItemByItemId("CastleCircletRemoval", circletId, 1, player, true);
}
return;
}
catch (NullPointerException e)
{
// continue removing offline
}
}
// else offline-player circlet removal
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM items WHERE owner_id = ? and item_id = ?"))
{
ps.setInt(1, member.getObjectId());
ps.setInt(2, circletId);
ps.execute();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed to remove castle circlets offline for player " + member.getName() + ": ", e);
}
}
}
@Override
public void loadInstances()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM castle ORDER BY id"))
{
while (rs.next())
{
final int castleId = rs.getInt("id");
_castles.put(castleId, new Castle(castleId));
}
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + getCastles().size() + " castles.");
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Exception: loadCastleData():", e);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (Castle castle : getCastles())
{
castle.activateInstance();
}
}
public void registerSiegeDate(int castleId, long siegeDate)
{
_castleSiegeDate.put(castleId, siegeDate);
}
public int getSiegeDates(long siegeDate)
{
int count = 0;
for (long date : _castleSiegeDate.values())
{
if (Math.abs(date - siegeDate) < 1000)
{
count++;
}
}
return count;
}
public static CastleManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CastleManager _instance = new CastleManager();
}
}

View File

@@ -0,0 +1,438 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.enums.CategoryType;
import com.l2jmobius.gameserver.enums.CeremonyOfChaosState;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.ceremonyofchaos.CeremonyOfChaosEvent;
import com.l2jmobius.gameserver.model.ceremonyofchaos.CeremonyOfChaosMember;
import com.l2jmobius.gameserver.model.eventengine.AbstractEventManager;
import com.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import com.l2jmobius.gameserver.model.events.EventType;
import com.l2jmobius.gameserver.model.events.ListenerRegisterType;
import com.l2jmobius.gameserver.model.events.annotations.RegisterEvent;
import com.l2jmobius.gameserver.model.events.annotations.RegisterType;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogin;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout;
import com.l2jmobius.gameserver.model.events.returns.TerminateReturn;
import com.l2jmobius.gameserver.model.olympiad.OlympiadManager;
import com.l2jmobius.gameserver.model.punishment.PunishmentAffect;
import com.l2jmobius.gameserver.model.punishment.PunishmentType;
import com.l2jmobius.gameserver.model.variables.PlayerVariables;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.network.serverpackets.ceremonyofchaos.ExCuriousHouseState;
/**
* @author Sdw
*/
public class CeremonyOfChaosManager extends AbstractEventManager<CeremonyOfChaosEvent>
{
protected static final Logger LOGGER = Logger.getLogger(CeremonyOfChaosManager.class.getName());
public static final String INITIAL_BUFF_KEY = "initial_buff";
public static final String INITIAL_ITEMS_KEY = "initial_items";
public static final String MAX_PLAYERS_KEY = "max_players";
public static final String MAX_ARENAS_KEY = "max_arenas";
public static final String INSTANCE_TEMPLATES_KEY = "instance_templates";
public static final String END_BUFFS_KEYH = "end_buffs";
protected CeremonyOfChaosManager()
{
}
@Override
public void onInitialized()
{
if (getState() == null)
{
setState(CeremonyOfChaosState.SCHEDULED);
}
}
@ScheduleTarget
private void onPeriodEnd(String text)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM character_variables WHERE var = ?"))
{
ps.setString(1, PlayerVariables.CEREMONY_OF_CHAOS_PROHIBITED_PENALTIES);
ps.execute();
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Could not reset Ceremony Of Chaos penalties: " + e);
}
// Update data for online players.
L2World.getInstance().getPlayers().stream().forEach(player ->
{
player.getVariables().remove(PlayerVariables.CEREMONY_OF_CHAOS_PROHIBITED_PENALTIES);
player.getVariables().storeMe();
});
LOGGER.info(getClass().getSimpleName() + ": Ceremony of Chaos penalties have been reset.");
LOGGER.info(getClass().getSimpleName() + ": Ceremony of Chaos period has ended!");
}
@ScheduleTarget
private void onEventStart()
{
LOGGER.info(getClass().getSimpleName() + ": Ceremony of Chaos event has started!");
}
@ScheduleTarget
private void onEventEnd()
{
PunishmentManager.getInstance().stopPunishment(PunishmentAffect.CHARACTER, PunishmentType.COC_BAN);
LOGGER.info(getClass().getSimpleName() + ": Ceremony of Chaos event has ended!");
}
@ScheduleTarget
private void onRegistrationStart()
{
if (getState() != CeremonyOfChaosState.SCHEDULED)
{
return;
}
setState(CeremonyOfChaosState.REGISTRATION);
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
if (player.isOnline())
{
player.sendPacket(SystemMessageId.REGISTRATION_FOR_THE_CEREMONY_OF_CHAOS_HAS_BEGUN);
if (canRegister(player, false))
{
player.sendPacket(ExCuriousHouseState.REGISTRATION_PACKET);
}
}
}
}
@ScheduleTarget
private void onRegistrationEnd()
{
if (getState() != CeremonyOfChaosState.REGISTRATION)
{
return;
}
setState(CeremonyOfChaosState.PREPARING_FOR_TELEPORT);
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
if (player.isOnline())
{
player.sendPacket(SystemMessageId.REGISTRATION_FOR_THE_CEREMONY_OF_CHAOS_HAS_ENDED);
if (!isRegistered(player))
{
player.sendPacket(ExCuriousHouseState.IDLE_PACKET);
}
}
}
getTimers().addTimer("count_down", StatsSet.valueOf("time", 60), 60 * 1000, null, null);
}
@ScheduleTarget
private void onPrepareForFight()
{
if (getState() != CeremonyOfChaosState.PREPARING_FOR_TELEPORT)
{
return;
}
setState(CeremonyOfChaosState.PREPARING_FOR_FIGHT);
int eventId = 0;
int position = 1;
CeremonyOfChaosEvent event = null;
final List<L2PcInstance> players = getRegisteredPlayers().stream().sorted(Comparator.comparingInt(L2PcInstance::getLevel)).collect(Collectors.toList());
final int maxPlayers = getMaxPlayersInArena();
final List<Integer> templates = getVariables().getList(INSTANCE_TEMPLATES_KEY, Integer.class);
for (L2PcInstance player : players)
{
if (player.isOnline() && canRegister(player, true))
{
if ((event == null) || (event.getMembers().size() >= maxPlayers))
{
final int template = templates.get(Rnd.get(templates.size()));
event = new CeremonyOfChaosEvent(eventId++, InstanceManager.getInstance().getInstanceTemplate(template));
position = 1;
getEvents().add(event);
}
event.addMember(new CeremonyOfChaosMember(player, event, position++));
}
else
{
player.prohibiteCeremonyOfChaos();
player.sendPacket(ExCuriousHouseState.IDLE_PACKET);
}
}
// Clear previously registrated players
getRegisteredPlayers().clear();
// Prepare all event's players for start
getEvents().forEach(CeremonyOfChaosEvent::preparePlayers);
}
@ScheduleTarget
private void onStartFight()
{
if (getState() != CeremonyOfChaosState.PREPARING_FOR_FIGHT)
{
return;
}
setState(CeremonyOfChaosState.RUNNING);
getEvents().forEach(CeremonyOfChaosEvent::startFight);
}
@ScheduleTarget
private void onEndFight()
{
if (getState() != CeremonyOfChaosState.RUNNING)
{
return;
}
setState(CeremonyOfChaosState.SCHEDULED);
getEvents().forEach(CeremonyOfChaosEvent::stopFight);
getEvents().clear();
}
@Override
public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
{
switch (event)
{
case "count_down":
{
final int time = params.getInt("time", 0);
final SystemMessage countdown = SystemMessage.getSystemMessage(SystemMessageId.YOU_WILL_BE_MOVED_TO_THE_ARENA_IN_S1_SECOND_S);
countdown.addByte(time);
broadcastPacket(countdown);
// Reschedule
if (time == 60)
{
getTimers().addTimer(event, params.set("time", 10), 50 * 1000, null, null);
}
else if (time == 10)
{
getTimers().addTimer(event, params.set("time", 5), 5 * 1000, null, null);
}
else if ((time > 1) && (time <= 5))
{
getTimers().addTimer(event, params.set("time", time - 1), 1000, null, null);
}
break;
}
}
}
public final void broadcastPacket(IClientOutgoingPacket... packets)
{
getRegisteredPlayers().forEach(member -> member.sendPacket(packets));
}
@Override
public boolean canRegister(L2PcInstance player, boolean sendMessage)
{
boolean canRegister = true;
final L2Clan clan = player.getClan();
SystemMessageId sm = null;
if (player.getLevel() < 85)
{
sm = SystemMessageId.ONLY_CHARACTERS_LEVEL_85_OR_ABOVE_MAY_PARTICIPATE_IN_THE_TOURNAMENT;
canRegister = false;
}
else if (player.isFlyingMounted())
{
sm = SystemMessageId.YOU_CANNOT_PARTICIPATE_IN_THE_CEREMONY_OF_CHAOS_AS_A_FLYING_TRANSFORMED_OBJECT;
canRegister = false;
}
else if (!player.isInCategory(CategoryType.AWAKEN_GROUP))
{
sm = SystemMessageId.ONLY_CHARACTERS_WHO_HAVE_COMPLETED_THE_3RD_CLASS_TRANSFER_MAY_PARTICIPATE;
canRegister = false;
}
else if (!player.isInventoryUnder80(false) || (player.getWeightPenalty() != 0))
{
sm = SystemMessageId.UNABLE_TO_PROCESS_THIS_REQUEST_UNTIL_YOUR_INVENTORY_S_WEIGHT_AND_SLOT_COUNT_ARE_LESS_THAN_80_PERCENT_OF_CAPACITY;
canRegister = false;
}
else if ((clan == null) || (clan.getLevel() < 6))
{
sm = SystemMessageId.ONLY_CHARACTERS_WHO_ARE_A_PART_OF_A_CLAN_OF_LEVEL_6_OR_ABOVE_MAY_PARTICIPATE;
canRegister = false;
}
else if (getRegisteredPlayers().size() >= (getVariables().getInt(MAX_ARENAS_KEY, 5) * getMaxPlayersInArena()))
{
sm = SystemMessageId.THERE_ARE_TOO_MANY_CHALLENGERS_YOU_CANNOT_PARTICIPATE_NOW;
canRegister = false;
}
else if (player.isCursedWeaponEquipped() || (player.getReputation() < 0))
{
sm = SystemMessageId.WAITING_LIST_REGISTRATION_IS_NOT_ALLOWED_WHILE_THE_CURSED_SWORD_IS_BEING_USED_OR_THE_STATUS_IS_IN_A_CHAOTIC_STATE;
canRegister = false;
}
else if (player.isInDuel())
{
sm = SystemMessageId.YOU_CANNOT_REGISTER_IN_THE_WAITING_LIST_DURING_A_DUEL;
canRegister = false;
}
else if (player.isInOlympiadMode() || OlympiadManager.getInstance().isRegistered(player))
{
sm = SystemMessageId.YOU_CANNOT_REGISTER_IN_THE_WAITING_LIST_WHILE_PARTICIPATING_IN_OLYMPIAD;
canRegister = false;
}
else if (player.isOnEvent(CeremonyOfChaosEvent.class) || (player.getBlockCheckerArena() > -1)) // TODO underground coliseum and kratei checks.
{
sm = SystemMessageId.YOU_CANNOT_REGISTER_FOR_THE_WAITING_LIST_WHILE_PARTICIPATING_IN_THE_BLOCK_CHECKER_COLISEUM_OLYMPIAD_KRATEI_S_CUBE_CEREMONY_OF_CHAOS;
canRegister = false;
}
else if (player.isInInstance())
{
sm = SystemMessageId.YOU_MAY_NOT_REGISTER_WHILE_USING_THE_INSTANT_ZONE;
canRegister = false;
}
else if (player.isInSiege())
{
sm = SystemMessageId.YOU_CANNOT_REGISTER_FOR_THE_WAITING_LIST_ON_THE_BATTLEFIELD_CASTLE_SIEGE_FORTRESS_SIEGE;
canRegister = false;
}
else if (player.isInsideZone(ZoneId.SIEGE))
{
sm = SystemMessageId.YOU_CANNOT_REGISTER_IN_THE_WAITING_LIST_WHILE_BEING_INSIDE_OF_A_BATTLEGROUND_CASTLE_SIEGE_FORTRESS_SIEGE;
canRegister = false;
}
else if (player.isFlyingMounted())
{
sm = SystemMessageId.YOU_CANNOT_PARTICIPATE_IN_THE_CEREMONY_OF_CHAOS_AS_A_FLYING_TRANSFORMED_OBJECT;
canRegister = false;
}
else if (player.isFishing())
{
sm = SystemMessageId.YOU_CANNOT_PARTICIPATE_IN_THE_CEREMONY_OF_CHAOS_WHILE_FISHING;
canRegister = false;
}
else if (player.isCeremonyOfChaosProhibited())
{
canRegister = false;
}
// TODO : One player can take part in 16 matches per day.
if ((sm != null) && sendMessage)
{
player.sendPacket(sm);
}
return canRegister;
}
@RegisterEvent(EventType.ON_PLAYER_BYPASS)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
private TerminateReturn OnPlayerBypass(OnPlayerBypass event)
{
final L2PcInstance player = event.getActiveChar();
if (player == null)
{
return null;
}
if (event.getCommand().equalsIgnoreCase("pledgegame?command=apply"))
{
if (registerPlayer(player))
{
player.sendPacket(SystemMessageId.YOU_ARE_NOW_ON_THE_WAITING_LIST_YOU_WILL_AUTOMATICALLY_BE_TELEPORTED_WHEN_THE_TOURNAMENT_STARTS_AND_WILL_BE_REMOVED_FROM_THE_WAITING_LIST_IF_YOU_LOG_OUT_IF_YOU_CANCEL_REGISTRATION_WITHIN_THE_LAST_MINUTE_OF_ENTERING_THE_ARENA_AFTER_SIGNING_UP_30_TIMES_OR_MORE_OR_FORFEIT_AFTER_ENTERING_THE_ARENA_30_TIMES_OR_MORE_DURING_A_CYCLE_YOU_BECOME_INELIGIBLE_FOR_PARTICIPATION_IN_THE_CEREMONY_OF_CHAOS_UNTIL_THE_NEXT_CYCLE_ALL_THE_BUFFS_EXCEPT_THE_VITALITY_BUFF_WILL_BE_REMOVED_ONCE_YOU_ENTER_THE_ARENAS);
player.sendPacket(SystemMessageId.EXCEPT_THE_VITALITY_BUFF_ALL_BUFFS_INCLUDING_ART_OF_SEDUCTION_WILL_BE_DELETED);
player.sendPacket(ExCuriousHouseState.PREPARE_PACKET);
}
return new TerminateReturn(true, false, false);
}
return null;
}
@RegisterEvent(EventType.ON_PLAYER_LOGIN)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
private void OnPlayerLogin(OnPlayerLogin event)
{
if (getState() == CeremonyOfChaosState.REGISTRATION)
{
final L2PcInstance player = event.getActiveChar();
if (canRegister(player, false))
{
player.sendPacket(ExCuriousHouseState.REGISTRATION_PACKET);
}
}
}
@RegisterEvent(EventType.ON_PLAYER_LOGOUT)
@RegisterType(ListenerRegisterType.GLOBAL_PLAYERS)
private void OnPlayerLogout(OnPlayerLogout event)
{
if (getState() == CeremonyOfChaosState.REGISTRATION)
{
final L2PcInstance player = event.getActiveChar();
if (getRegisteredPlayers().contains(player))
{
getRegisteredPlayers().remove(player);
}
}
}
// player leave clan
public int getMaxPlayersInArena()
{
return getVariables().getInt(MAX_PLAYERS_KEY, 18);
}
public static CeremonyOfChaosManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CeremonyOfChaosManager _instance = new CeremonyOfChaosManager();
}
}

View File

@@ -1,409 +1,411 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.clan.entry.PledgeApplicantInfo;
import com.l2jmobius.gameserver.model.clan.entry.PledgeRecruitInfo;
import com.l2jmobius.gameserver.model.clan.entry.PledgeWaitingInfo;
import com.l2jmobius.gameserver.util.Util;
/**
* @author Sdw
*/
public class ClanEntryManager
{
protected static final Logger _log = Logger.getLogger(ClanEntryManager.class.getName());
private static final Map<Integer, PledgeWaitingInfo> _waitingList = new ConcurrentHashMap<>();
private static final Map<Integer, PledgeRecruitInfo> _clanList = new ConcurrentHashMap<>();
private static final Map<Integer, Map<Integer, PledgeApplicantInfo>> _applicantList = new ConcurrentHashMap<>();
private static final Map<Integer, ScheduledFuture<?>> _clanLocked = new ConcurrentHashMap<>();
private static final Map<Integer, ScheduledFuture<?>> _playerLocked = new ConcurrentHashMap<>();
private static final String INSERT_APPLICANT = "INSERT INTO pledge_applicant VALUES (?, ?, ?, ?)";
private static final String DELETE_APPLICANT = "DELETE FROM pledge_applicant WHERE charId = ? AND clanId = ?";
private static final String INSERT_WAITING_LIST = "INSERT INTO pledge_waiting_list VALUES (?, ?)";
private static final String DELETE_WAITING_LIST = "DELETE FROM pledge_waiting_list WHERE char_id = ?";
private static final String INSERT_CLAN_RECRUIT = "INSERT INTO pledge_recruit VALUES (?, ?, ?, ?)";
private static final String UPDATE_CLAN_RECRUIT = "UPDATE pledge_recruit SET karma = ?, information = ?, detailed_information = ? WHERE clan_id = ?";
private static final String DELETE_CLAN_RECRUIT = "DELETE FROM pledge_recruit WHERE clan_id = ?";
//@formatter:off
private static final List<Comparator<PledgeWaitingInfo>> PLAYER_COMPARATOR = Arrays.asList(
null,
Comparator.comparing(PledgeWaitingInfo::getPlayerName),
Comparator.comparingInt(PledgeWaitingInfo::getKarma),
Comparator.comparingInt(PledgeWaitingInfo::getPlayerLvl),
Comparator.comparingInt(PledgeWaitingInfo::getPlayerClassId));
//@formatter:on
//@formatter:off
private static final List<Comparator<PledgeRecruitInfo>> CLAN_COMPARATOR = Arrays.asList(
null,
Comparator.comparing(PledgeRecruitInfo::getClanName),
Comparator.comparing(PledgeRecruitInfo::getClanLeaderName),
Comparator.comparingInt(PledgeRecruitInfo::getClanLevel),
Comparator.comparingInt(PledgeRecruitInfo::getKarma));
//@formatter:on
private static final long LOCK_TIME = TimeUnit.MINUTES.toMillis(5);
protected ClanEntryManager()
{
load();
}
private final void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM pledge_recruit"))
{
while (rs.next())
{
_clanList.put(rs.getInt("clan_id"), new PledgeRecruitInfo(rs.getInt("clan_id"), rs.getInt("karma"), rs.getString("information"), rs.getString("detailed_information")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _clanList.size() + " clan entry");
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Exception: ClanEntryManager.load(): " + e.getMessage());
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT a.char_id, a.karma, b.base_class, b.level, b.char_name FROM pledge_waiting_list as a LEFT JOIN characters as b ON a.char_id = b.charId"))
{
while (rs.next())
{
_waitingList.put(rs.getInt("char_id"), new PledgeWaitingInfo(rs.getInt("char_id"), rs.getInt("level"), rs.getInt("karma"), rs.getInt("base_class"), rs.getString("char_name")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _waitingList.size() + " player in waiting list");
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Exception: ClanEntryManager.load(): " + e.getMessage());
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT a.charId, a.clanId, a.karma, a.message, b.base_class, b.level, b.char_name FROM pledge_applicant as a LEFT JOIN characters as b ON a.charId = b.charId"))
{
while (rs.next())
{
_applicantList.computeIfAbsent(rs.getInt("clanId"), k -> new ConcurrentHashMap<>()).put(rs.getInt("charId"), new PledgeApplicantInfo(rs.getInt("charId"), rs.getString("char_name"), rs.getInt("level"), rs.getInt("karma"), rs.getInt("clanId"), rs.getString("message")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _applicantList.size() + " player application");
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Exception: ClanEntryManager.load(): " + e.getMessage());
}
}
public Map<Integer, PledgeWaitingInfo> getWaitingList()
{
return _waitingList;
}
public Map<Integer, PledgeRecruitInfo> getClanList()
{
return _clanList;
}
public Map<Integer, Map<Integer, PledgeApplicantInfo>> getApplicantList()
{
return _applicantList;
}
public Map<Integer, PledgeApplicantInfo> getApplicantListForClan(int clanId)
{
return _applicantList.getOrDefault(clanId, Collections.emptyMap());
}
public PledgeApplicantInfo getPlayerApplication(int clanId, int playerId)
{
return _applicantList.getOrDefault(clanId, Collections.emptyMap()).get(playerId);
}
public boolean removePlayerApplication(int clanId, int playerId)
{
final Map<Integer, PledgeApplicantInfo> clanApplicantList = _applicantList.get(clanId);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_APPLICANT))
{
statement.setInt(1, playerId);
statement.setInt(2, clanId);
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
return (clanApplicantList != null) && (clanApplicantList.remove(playerId) != null);
}
public boolean addPlayerApplicationToClan(int clanId, PledgeApplicantInfo info)
{
if (_playerLocked.containsKey(info.getPlayerId()))
{
return false;
}
_applicantList.computeIfAbsent(clanId, k -> new ConcurrentHashMap<>()).put(info.getPlayerId(), info);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(INSERT_APPLICANT))
{
statement.setInt(1, info.getPlayerId());
statement.setInt(2, info.getRequestClanId());
statement.setInt(3, info.getKarma());
statement.setString(4, info.getMessage());
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
return true;
}
public OptionalInt getClanIdForPlayerApplication(int playerId)
{
return _applicantList.entrySet().stream().filter(e -> e.getValue().containsKey(playerId)).mapToInt(e -> e.getKey()).findFirst();
}
public boolean addToWaitingList(int playerId, PledgeWaitingInfo info)
{
if (_playerLocked.containsKey(playerId))
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(INSERT_WAITING_LIST))
{
statement.setInt(1, info.getPlayerId());
statement.setInt(2, info.getKarma());
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
return _waitingList.put(playerId, info) != null;
}
public boolean removeFromWaitingList(int playerId)
{
if (!_waitingList.containsKey(playerId))
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_WAITING_LIST))
{
statement.setInt(1, playerId);
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
_waitingList.remove(playerId);
lockPlayer(playerId);
return true;
}
public boolean addToClanList(int clanId, PledgeRecruitInfo info)
{
if (_clanList.containsKey(clanId) || _clanLocked.containsKey(clanId))
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(INSERT_CLAN_RECRUIT))
{
statement.setInt(1, info.getClanId());
statement.setInt(2, info.getKarma());
statement.setString(3, info.getInformation());
statement.setString(4, info.getDetailedInformation());
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
return _clanList.put(clanId, info) != null;
}
public boolean updateClanList(int clanId, PledgeRecruitInfo info)
{
if (!_clanList.containsKey(clanId) || _clanLocked.containsKey(clanId))
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(UPDATE_CLAN_RECRUIT))
{
statement.setInt(1, info.getKarma());
statement.setString(2, info.getInformation());
statement.setString(3, info.getDetailedInformation());
statement.setInt(4, info.getClanId());
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
return _clanList.replace(clanId, info) != null;
}
public boolean removeFromClanList(int clanId)
{
if (!_clanList.containsKey(clanId))
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_CLAN_RECRUIT))
{
statement.setInt(1, clanId);
statement.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
_clanList.remove(clanId);
lockClan(clanId);
return true;
}
public List<PledgeWaitingInfo> getSortedWaitingList(int levelMin, int levelMax, int role, int sortBy, boolean descending)
{
sortBy = Util.constrain(sortBy, 1, PLAYER_COMPARATOR.size() - 1);
// TODO: Handle Role
//@formatter:off
return _waitingList.values().stream()
.filter(p -> ((p.getPlayerLvl() >= levelMin) && (p.getPlayerLvl() <= levelMax)))
.sorted(descending ? PLAYER_COMPARATOR.get(sortBy).reversed() : PLAYER_COMPARATOR.get(sortBy))
.collect(Collectors.toList());
//@formatter:on
}
public List<PledgeWaitingInfo> queryWaitingListByName(String name)
{
return _waitingList.values().stream().filter(p -> p.getPlayerName().toLowerCase().contains(name)).collect(Collectors.toList());
}
public List<PledgeRecruitInfo> getSortedClanListByName(String query, int type)
{
return type == 1 ? _clanList.values().stream().filter(p -> p.getClanName().toLowerCase().contains(query)).collect(Collectors.toList()) : _clanList.values().stream().filter(p -> p.getClanLeaderName().toLowerCase().contains(query)).collect(Collectors.toList());
}
public PledgeRecruitInfo getClanById(int clanId)
{
return _clanList.get(clanId);
}
public boolean isClanRegistred(int clanId)
{
return _clanList.get(clanId) != null;
}
public boolean isPlayerRegistred(int playerId)
{
return _waitingList.get(playerId) != null;
}
public List<PledgeRecruitInfo> getUnSortedClanList()
{
return _clanList.values().stream().collect(Collectors.toList());
}
public List<PledgeRecruitInfo> getSortedClanList(int clanLevel, int karma, int sortBy, boolean descending)
{
sortBy = Util.constrain(sortBy, 1, CLAN_COMPARATOR.size() - 1);
//@formatter:off
return _clanList.values().stream()
.filter(p -> (((clanLevel < 0) && (karma >= 0) && (karma != p.getKarma())) || ((clanLevel >= 0) && (karma < 0) && (clanLevel != p.getClanLevel())) || ((clanLevel >= 0) && (karma >= 0) && ((clanLevel != p.getClanLevel()) || (karma != p.getKarma())))))
.sorted(descending ? CLAN_COMPARATOR.get(sortBy).reversed() : CLAN_COMPARATOR.get(sortBy))
.collect(Collectors.toList());
//@formatter:on
}
public long getPlayerLockTime(int playerId)
{
return _playerLocked.get(playerId) == null ? 0 : _playerLocked.get(playerId).getDelay(TimeUnit.MINUTES);
}
public long getClanLockTime(int playerId)
{
return _clanLocked.get(playerId) == null ? 0 : _clanLocked.get(playerId).getDelay(TimeUnit.MINUTES);
}
private static void lockPlayer(int playerId)
{
_playerLocked.put(playerId, ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
_playerLocked.remove(playerId);
}, LOCK_TIME));
}
private static void lockClan(int clanId)
{
_clanLocked.put(clanId, ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
_clanLocked.remove(clanId);
}, LOCK_TIME));
}
public static ClanEntryManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClanEntryManager _instance = new ClanEntryManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.OptionalInt;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.clan.entry.PledgeApplicantInfo;
import com.l2jmobius.gameserver.model.clan.entry.PledgeRecruitInfo;
import com.l2jmobius.gameserver.model.clan.entry.PledgeWaitingInfo;
/**
* @author Sdw
*/
public class ClanEntryManager
{
protected static final Logger LOGGER = Logger.getLogger(ClanEntryManager.class.getName());
private static final Map<Integer, PledgeWaitingInfo> _waitingList = new ConcurrentHashMap<>();
private static final Map<Integer, PledgeRecruitInfo> _clanList = new ConcurrentHashMap<>();
private static final Map<Integer, Map<Integer, PledgeApplicantInfo>> _applicantList = new ConcurrentHashMap<>();
private static final Map<Integer, ScheduledFuture<?>> _clanLocked = new ConcurrentHashMap<>();
private static final Map<Integer, ScheduledFuture<?>> _playerLocked = new ConcurrentHashMap<>();
private static final String INSERT_APPLICANT = "INSERT INTO pledge_applicant VALUES (?, ?, ?, ?)";
private static final String DELETE_APPLICANT = "DELETE FROM pledge_applicant WHERE charId = ? AND clanId = ?";
private static final String INSERT_WAITING_LIST = "INSERT INTO pledge_waiting_list VALUES (?, ?)";
private static final String DELETE_WAITING_LIST = "DELETE FROM pledge_waiting_list WHERE char_id = ?";
private static final String INSERT_CLAN_RECRUIT = "INSERT INTO pledge_recruit VALUES (?, ?, ?, ?)";
private static final String UPDATE_CLAN_RECRUIT = "UPDATE pledge_recruit SET karma = ?, information = ?, detailed_information = ? WHERE clan_id = ?";
private static final String DELETE_CLAN_RECRUIT = "DELETE FROM pledge_recruit WHERE clan_id = ?";
//@formatter:off
private static final List<Comparator<PledgeWaitingInfo>> PLAYER_COMPARATOR = Arrays.asList(
null,
Comparator.comparing(PledgeWaitingInfo::getPlayerName),
Comparator.comparingInt(PledgeWaitingInfo::getKarma),
Comparator.comparingInt(PledgeWaitingInfo::getPlayerLvl),
Comparator.comparingInt(PledgeWaitingInfo::getPlayerClassId));
//@formatter:on
//@formatter:off
private static final List<Comparator<PledgeRecruitInfo>> CLAN_COMPARATOR = Arrays.asList(
null,
Comparator.comparing(PledgeRecruitInfo::getClanName),
Comparator.comparing(PledgeRecruitInfo::getClanLeaderName),
Comparator.comparingInt(PledgeRecruitInfo::getClanLevel),
Comparator.comparingInt(PledgeRecruitInfo::getKarma));
//@formatter:on
private static final long LOCK_TIME = TimeUnit.MINUTES.toMillis(5);
protected ClanEntryManager()
{
load();
}
private void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM pledge_recruit"))
{
while (rs.next())
{
_clanList.put(rs.getInt("clan_id"), new PledgeRecruitInfo(rs.getInt("clan_id"), rs.getInt("karma"), rs.getString("information"), rs.getString("detailed_information")));
}
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _clanList.size() + " clan entry");
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed to load: ", e);
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT a.char_id, a.karma, b.base_class, b.level, b.char_name FROM pledge_waiting_list as a LEFT JOIN characters as b ON a.char_id = b.charId"))
{
while (rs.next())
{
_waitingList.put(rs.getInt("char_id"), new PledgeWaitingInfo(rs.getInt("char_id"), rs.getInt("level"), rs.getInt("karma"), rs.getInt("base_class"), rs.getString("char_name")));
}
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _waitingList.size() + " player in waiting list");
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed to load: ", e);
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT a.charId, a.clanId, a.karma, a.message, b.base_class, b.level, b.char_name FROM pledge_applicant as a LEFT JOIN characters as b ON a.charId = b.charId"))
{
while (rs.next())
{
_applicantList.computeIfAbsent(rs.getInt("clanId"), k -> new ConcurrentHashMap<>()).put(rs.getInt("charId"), new PledgeApplicantInfo(rs.getInt("charId"), rs.getString("char_name"), rs.getInt("level"), rs.getInt("karma"), rs.getInt("clanId"), rs.getString("message")));
}
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _applicantList.size() + " player application");
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed to load: ", e);
}
}
public Map<Integer, PledgeWaitingInfo> getWaitingList()
{
return _waitingList;
}
public Map<Integer, PledgeRecruitInfo> getClanList()
{
return _clanList;
}
public Map<Integer, Map<Integer, PledgeApplicantInfo>> getApplicantList()
{
return _applicantList;
}
public Map<Integer, PledgeApplicantInfo> getApplicantListForClan(int clanId)
{
return _applicantList.getOrDefault(clanId, Collections.emptyMap());
}
public PledgeApplicantInfo getPlayerApplication(int clanId, int playerId)
{
return _applicantList.getOrDefault(clanId, Collections.emptyMap()).get(playerId);
}
public boolean removePlayerApplication(int clanId, int playerId)
{
final Map<Integer, PledgeApplicantInfo> clanApplicantList = _applicantList.get(clanId);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_APPLICANT))
{
statement.setInt(1, playerId);
statement.setInt(2, clanId);
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
return (clanApplicantList != null) && (clanApplicantList.remove(playerId) != null);
}
public boolean addPlayerApplicationToClan(int clanId, PledgeApplicantInfo info)
{
if (!_playerLocked.containsKey(info.getPlayerId()))
{
_applicantList.computeIfAbsent(clanId, k -> new ConcurrentHashMap<>()).put(info.getPlayerId(), info);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(INSERT_APPLICANT))
{
statement.setInt(1, info.getPlayerId());
statement.setInt(2, info.getRequestClanId());
statement.setInt(3, info.getKarma());
statement.setString(4, info.getMessage());
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
return true;
}
return false;
}
public OptionalInt getClanIdForPlayerApplication(int playerId)
{
return _applicantList.entrySet().stream().filter(e -> e.getValue().containsKey(playerId)).mapToInt(e -> e.getKey()).findFirst();
}
public boolean addToWaitingList(int playerId, PledgeWaitingInfo info)
{
if (!_playerLocked.containsKey(playerId))
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(INSERT_WAITING_LIST))
{
statement.setInt(1, info.getPlayerId());
statement.setInt(2, info.getKarma());
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
return _waitingList.put(playerId, info) != null;
}
return false;
}
public boolean removeFromWaitingList(int playerId)
{
if (_waitingList.containsKey(playerId))
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_WAITING_LIST))
{
statement.setInt(1, playerId);
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
_waitingList.remove(playerId);
lockPlayer(playerId);
return true;
}
return false;
}
public boolean addToClanList(int clanId, PledgeRecruitInfo info)
{
if (!_clanList.containsKey(clanId) && !_clanLocked.containsKey(clanId))
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(INSERT_CLAN_RECRUIT))
{
statement.setInt(1, info.getClanId());
statement.setInt(2, info.getKarma());
statement.setString(3, info.getInformation());
statement.setString(4, info.getDetailedInformation());
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
return _clanList.put(clanId, info) != null;
}
return false;
}
public boolean updateClanList(int clanId, PledgeRecruitInfo info)
{
if (_clanList.containsKey(clanId) && !_clanLocked.containsKey(clanId))
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(UPDATE_CLAN_RECRUIT))
{
statement.setInt(1, info.getKarma());
statement.setString(2, info.getInformation());
statement.setString(3, info.getDetailedInformation());
statement.setInt(4, info.getClanId());
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
return _clanList.replace(clanId, info) != null;
}
return false;
}
public boolean removeFromClanList(int clanId)
{
if (_clanList.containsKey(clanId))
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_CLAN_RECRUIT))
{
statement.setInt(1, clanId);
statement.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
_clanList.remove(clanId);
lockClan(clanId);
return true;
}
return false;
}
public List<PledgeWaitingInfo> getSortedWaitingList(int levelMin, int levelMax, int role, int sortBy, boolean descending)
{
sortBy = CommonUtil.constrain(sortBy, 1, PLAYER_COMPARATOR.size() - 1);
// TODO: Handle Role
//@formatter:off
return _waitingList.values().stream()
.filter(p -> ((p.getPlayerLvl() >= levelMin) && (p.getPlayerLvl() <= levelMax)))
.sorted(descending ? PLAYER_COMPARATOR.get(sortBy).reversed() : PLAYER_COMPARATOR.get(sortBy))
.collect(Collectors.toList());
//@formatter:on
}
public List<PledgeWaitingInfo> queryWaitingListByName(String name)
{
return _waitingList.values().stream().filter(p -> p.getPlayerName().toLowerCase().contains(name)).collect(Collectors.toList());
}
public List<PledgeRecruitInfo> getSortedClanListByName(String query, int type)
{
return type == 1 ? _clanList.values().stream().filter(p -> p.getClanName().toLowerCase().contains(query)).collect(Collectors.toList()) : _clanList.values().stream().filter(p -> p.getClanLeaderName().toLowerCase().contains(query)).collect(Collectors.toList());
}
public PledgeRecruitInfo getClanById(int clanId)
{
return _clanList.get(clanId);
}
public boolean isClanRegistred(int clanId)
{
return _clanList.get(clanId) != null;
}
public boolean isPlayerRegistred(int playerId)
{
return _waitingList.get(playerId) != null;
}
public List<PledgeRecruitInfo> getUnSortedClanList()
{
return _clanList.values().stream().collect(Collectors.toList());
}
public List<PledgeRecruitInfo> getSortedClanList(int clanLevel, int karma, int sortBy, boolean descending)
{
sortBy = CommonUtil.constrain(sortBy, 1, CLAN_COMPARATOR.size() - 1);
//@formatter:off
return _clanList.values().stream()
.filter((p -> (((clanLevel < 0) && (karma >= 0) && (karma != p.getKarma())) || ((clanLevel >= 0) && (karma < 0) && (clanLevel != p.getClanLevel())) || ((clanLevel >= 0) && (karma >= 0) && ((clanLevel != p.getClanLevel()) || (karma != p.getKarma()))))))
.sorted(descending ? CLAN_COMPARATOR.get(sortBy).reversed() : CLAN_COMPARATOR.get(sortBy))
.collect(Collectors.toList());
//@formatter:on
}
public long getPlayerLockTime(int playerId)
{
return _playerLocked.get(playerId) == null ? 0 : _playerLocked.get(playerId).getDelay(TimeUnit.MINUTES);
}
public long getClanLockTime(int playerId)
{
return _clanLocked.get(playerId) == null ? 0 : _clanLocked.get(playerId).getDelay(TimeUnit.MINUTES);
}
private static void lockPlayer(int playerId)
{
_playerLocked.put(playerId, ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
_playerLocked.remove(playerId);
}, LOCK_TIME));
}
private static void lockClan(int clanId)
{
_clanLocked.put(clanId, ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
_clanLocked.remove(clanId);
}, LOCK_TIME));
}
public static ClanEntryManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClanEntryManager _instance = new ClanEntryManager();
}
}

View File

@@ -1,184 +1,101 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.entity.Auction;
/**
* Zoey76: TODO: Rewrite it and unhardcode it.
*/
public final class ClanHallAuctionManager
{
protected static final Logger _log = Logger.getLogger(ClanHallAuctionManager.class.getName());
private final List<Auction> _auctions = new ArrayList<>();
private static final String[] ITEM_INIT_DATA =
{
"(22, 0, 'NPC', 'NPC Clan', 'ClanHall', 22, 0, 'Moonstone Hall', 1, 20000000, 0, 1073037600000)",
"(23, 0, 'NPC', 'NPC Clan', 'ClanHall', 23, 0, 'Onyx Hall', 1, 20000000, 0, 1073037600000)",
"(24, 0, 'NPC', 'NPC Clan', 'ClanHall', 24, 0, 'Topaz Hall', 1, 20000000, 0, 1073037600000)",
"(25, 0, 'NPC', 'NPC Clan', 'ClanHall', 25, 0, 'Ruby Hall', 1, 20000000, 0, 1073037600000)",
"(26, 0, 'NPC', 'NPC Clan', 'ClanHall', 26, 0, 'Crystal Hall', 1, 20000000, 0, 1073037600000)",
"(27, 0, 'NPC', 'NPC Clan', 'ClanHall', 27, 0, 'Onyx Hall', 1, 20000000, 0, 1073037600000)",
"(28, 0, 'NPC', 'NPC Clan', 'ClanHall', 28, 0, 'Sapphire Hall', 1, 20000000, 0, 1073037600000)",
"(29, 0, 'NPC', 'NPC Clan', 'ClanHall', 29, 0, 'Moonstone Hall', 1, 20000000, 0, 1073037600000)",
"(30, 0, 'NPC', 'NPC Clan', 'ClanHall', 30, 0, 'Emerald Hall', 1, 20000000, 0, 1073037600000)",
"(31, 0, 'NPC', 'NPC Clan', 'ClanHall', 31, 0, 'The Atramental Barracks', 1, 8000000, 0, 1073037600000)",
"(32, 0, 'NPC', 'NPC Clan', 'ClanHall', 32, 0, 'The Scarlet Barracks', 1, 8000000, 0, 1073037600000)",
"(33, 0, 'NPC', 'NPC Clan', 'ClanHall', 33, 0, 'The Viridian Barracks', 1, 8000000, 0, 1073037600000)",
"(36, 0, 'NPC', 'NPC Clan', 'ClanHall', 36, 0, 'The Golden Chamber', 1, 50000000, 0, 1106827200000)",
"(37, 0, 'NPC', 'NPC Clan', 'ClanHall', 37, 0, 'The Silver Chamber', 1, 50000000, 0, 1106827200000)",
"(38, 0, 'NPC', 'NPC Clan', 'ClanHall', 38, 0, 'The Mithril Chamber', 1, 50000000, 0, 1106827200000)",
"(39, 0, 'NPC', 'NPC Clan', 'ClanHall', 39, 0, 'Silver Manor', 1, 50000000, 0, 1106827200000)",
"(40, 0, 'NPC', 'NPC Clan', 'ClanHall', 40, 0, 'Gold Manor', 1, 50000000, 0, 1106827200000)",
"(41, 0, 'NPC', 'NPC Clan', 'ClanHall', 41, 0, 'The Bronze Chamber', 1, 50000000, 0, 1106827200000)",
"(42, 0, 'NPC', 'NPC Clan', 'ClanHall', 42, 0, 'The Golden Chamber', 1, 50000000, 0, 1106827200000)",
"(43, 0, 'NPC', 'NPC Clan', 'ClanHall', 43, 0, 'The Silver Chamber', 1, 50000000, 0, 1106827200000)",
"(44, 0, 'NPC', 'NPC Clan', 'ClanHall', 44, 0, 'The Mithril Chamber', 1, 50000000, 0, 1106827200000)",
"(45, 0, 'NPC', 'NPC Clan', 'ClanHall', 45, 0, 'The Bronze Chamber', 1, 50000000, 0, 1106827200000)",
"(46, 0, 'NPC', 'NPC Clan', 'ClanHall', 46, 0, 'Silver Manor', 1, 50000000, 0, 1106827200000)",
"(47, 0, 'NPC', 'NPC Clan', 'ClanHall', 47, 0, 'Moonstone Hall', 1, 50000000, 0, 1106827200000)",
"(48, 0, 'NPC', 'NPC Clan', 'ClanHall', 48, 0, 'Onyx Hall', 1, 50000000, 0, 1106827200000)",
"(49, 0, 'NPC', 'NPC Clan', 'ClanHall', 49, 0, 'Emerald Hall', 1, 50000000, 0, 1106827200000)",
"(50, 0, 'NPC', 'NPC Clan', 'ClanHall', 50, 0, 'Sapphire Hall', 1, 50000000, 0, 1106827200000)",
"(51, 0, 'NPC', 'NPC Clan', 'ClanHall', 51, 0, 'Mont Chamber', 1, 50000000, 0, 1106827200000)",
"(52, 0, 'NPC', 'NPC Clan', 'ClanHall', 52, 0, 'Astaire Chamber', 1, 50000000, 0, 1106827200000)",
"(53, 0, 'NPC', 'NPC Clan', 'ClanHall', 53, 0, 'Aria Chamber', 1, 50000000, 0, 1106827200000)",
"(54, 0, 'NPC', 'NPC Clan', 'ClanHall', 54, 0, 'Yiana Chamber', 1, 50000000, 0, 1106827200000)",
"(55, 0, 'NPC', 'NPC Clan', 'ClanHall', 55, 0, 'Roien Chamber', 1, 50000000, 0, 1106827200000)",
"(56, 0, 'NPC', 'NPC Clan', 'ClanHall', 56, 0, 'Luna Chamber', 1, 50000000, 0, 1106827200000)",
"(57, 0, 'NPC', 'NPC Clan', 'ClanHall', 57, 0, 'Traban Chamber', 1, 50000000, 0, 1106827200000)",
"(58, 0, 'NPC', 'NPC Clan', 'ClanHall', 58, 0, 'Eisen Hall', 1, 20000000, 0, 1106827200000)",
"(59, 0, 'NPC', 'NPC Clan', 'ClanHall', 59, 0, 'Heavy Metal Hall', 1, 20000000, 0, 1106827200000)",
"(60, 0, 'NPC', 'NPC Clan', 'ClanHall', 60, 0, 'Molten Ore Hall', 1, 20000000, 0, 1106827200000)",
"(61, 0, 'NPC', 'NPC Clan', 'ClanHall', 61, 0, 'Titan Hall', 1, 20000000, 0, 1106827200000)"
};
// @formatter:off
private static final int[] ItemInitDataId =
{
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
};
// @formatter:on
protected ClanHallAuctionManager()
{
load();
}
public void reload()
{
_auctions.clear();
load();
}
private final void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM auction ORDER BY id"))
{
while (rs.next())
{
_auctions.add(new Auction(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _auctions.size() + " auction(s)");
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Exception: AuctionManager.load(): " + e.getMessage(), e);
}
}
public final Auction getAuction(int auctionId)
{
final int index = getAuctionIndex(auctionId);
return index >= 0 ? _auctions.get(index) : null;
}
public final int getAuctionIndex(int auctionId)
{
Auction auction;
for (int i = 0; i < _auctions.size(); i++)
{
auction = _auctions.get(i);
if ((auction != null) && (auction.getId() == auctionId))
{
return i;
}
}
return -1;
}
public final List<Auction> getAuctions()
{
return _auctions;
}
/**
* Init Clan NPC aution
* @param id
*/
public void initNPC(int id)
{
int i;
for (i = 0; i < ItemInitDataId.length; i++)
{
if (ItemInitDataId[i] == id)
{
break;
}
}
if ((i >= ItemInitDataId.length) || (ItemInitDataId[i] != id))
{
_log.warning(getClass().getSimpleName() + ": Clan Hall auction not found for Id :" + id);
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement())
{
s.executeUpdate("INSERT INTO `auction` VALUES " + ITEM_INIT_DATA[i]);
_auctions.add(new Auction(id));
_log.info(getClass().getSimpleName() + ": Created auction for ClanHall: " + id);
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Exception: Auction.initNPC(): " + e.getMessage(), e);
}
}
public static ClanHallAuctionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClanHallAuctionManager _instance = new ClanHallAuctionManager();
}
}
/*
* 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.instancemanager;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.data.xml.impl.ClanHallData;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.clanhallauction.ClanHallAuction;
import com.l2jmobius.gameserver.model.eventengine.AbstractEvent;
import com.l2jmobius.gameserver.model.eventengine.AbstractEventManager;
import com.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
/**
* @author Sdw
*/
public class ClanHallAuctionManager extends AbstractEventManager<AbstractEvent<?>>
{
private static final Logger LOGGER = Logger.getLogger(ClanHallAuctionManager.class.getName());
private static final Map<Integer, ClanHallAuction> AUCTIONS = new HashMap<>();
protected ClanHallAuctionManager()
{
}
@ScheduleTarget
private void onEventStart()
{
LOGGER.info(getClass().getSimpleName() + ": Clan Hall Auction has started!");
AUCTIONS.clear();
//@formatter:off
ClanHallData.getInstance().getFreeAuctionableHall()
.forEach(c -> AUCTIONS.put(c.getResidenceId(), new ClanHallAuction(c.getResidenceId())));
//@formatter:on
}
@ScheduleTarget
private void onEventEnd()
{
AUCTIONS.values().forEach(ClanHallAuction::finalizeAuctions);
AUCTIONS.clear();
LOGGER.info(getClass().getSimpleName() + ": Clan Hall Auction has ended!");
}
@Override
public void onInitialized()
{
}
public ClanHallAuction getClanHallAuctionById(int clanHallId)
{
return AUCTIONS.get(clanHallId);
}
public ClanHallAuction getClanHallAuctionByClan(L2Clan clan)
{
//@formatter:off
return AUCTIONS.values().stream()
.filter(a -> a.getBids().containsKey(clan.getId()))
.findFirst()
.orElse(null);
//@formatter:on
}
public boolean checkForClanBid(int clanHallId, L2Clan clan)
{
//@formatter:off
return AUCTIONS.entrySet().stream()
.filter(a -> a.getKey() != clanHallId)
.anyMatch(a -> a.getValue().getBids().containsKey(clan.getId()));
//@formatter:on
}
public static final ClanHallAuctionManager getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final ClanHallAuctionManager INSTANCE = new ClanHallAuctionManager();
}
}

View File

@@ -1,306 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.sql.impl.ClanTable;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.model.entity.clanhall.AuctionableHall;
import com.l2jmobius.gameserver.model.entity.clanhall.SiegableHall;
import com.l2jmobius.gameserver.model.zone.type.L2ClanHallZone;
/**
* @author Steuf
*/
public final class ClanHallManager
{
protected static final Logger _log = Logger.getLogger(ClanHallManager.class.getName());
private final Map<Integer, AuctionableHall> _clanHall = new ConcurrentHashMap<>();
private final Map<Integer, AuctionableHall> _freeClanHall = new ConcurrentHashMap<>();
private final Map<Integer, AuctionableHall> _allAuctionableClanHalls = new HashMap<>();
private static Map<Integer, ClanHall> _allClanHalls = new HashMap<>();
private boolean _loaded = false;
public boolean loaded()
{
return _loaded;
}
protected ClanHallManager()
{
load();
}
/** Load All Clan Hall */
private final void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM clanhall ORDER BY id"))
{
int id, ownerId, lease;
while (rs.next())
{
final StatsSet set = new StatsSet();
id = rs.getInt("id");
ownerId = rs.getInt("ownerId");
lease = rs.getInt("lease");
set.set("id", id);
set.set("name", rs.getString("name"));
set.set("ownerId", ownerId);
set.set("lease", lease);
set.set("desc", rs.getString("desc"));
set.set("location", rs.getString("location"));
set.set("paidUntil", rs.getLong("paidUntil"));
set.set("grade", rs.getInt("Grade"));
set.set("paid", rs.getBoolean("paid"));
final AuctionableHall ch = new AuctionableHall(set);
_allAuctionableClanHalls.put(id, ch);
addClanHall(ch);
if (ch.getOwnerId() > 0)
{
_clanHall.put(id, ch);
continue;
}
_freeClanHall.put(id, ch);
if ((ClanHallAuctionManager.getInstance().getAuction(id) == null) && (lease > 0))
{
ClanHallAuctionManager.getInstance().initNPC(id);
}
}
_log.info(getClass().getSimpleName() + ": Loaded: " + getClanHalls().size() + " clan halls");
_log.info(getClass().getSimpleName() + ": Loaded: " + getFreeClanHalls().size() + " free clan halls");
_loaded = true;
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: ClanHallManager.load(): " + e.getMessage(), e);
}
}
public static Map<Integer, ClanHall> getAllClanHalls()
{
return _allClanHalls;
}
/**
* @return all FreeClanHalls
*/
public final Map<Integer, AuctionableHall> getFreeClanHalls()
{
return _freeClanHall;
}
/**
* @return all ClanHalls that have owner
*/
public final Map<Integer, AuctionableHall> getClanHalls()
{
return _clanHall;
}
/**
* @return all ClanHalls
*/
public final Map<Integer, AuctionableHall> getAllAuctionableClanHalls()
{
return _allAuctionableClanHalls;
}
public static void addClanHall(ClanHall hall)
{
_allClanHalls.put(hall.getId(), hall);
}
/**
* @param chId
* @return true is free ClanHall
*/
public final boolean isFree(int chId)
{
return _freeClanHall.containsKey(chId);
}
/**
* Free a ClanHall
* @param chId
*/
public final synchronized void setFree(int chId)
{
_freeClanHall.put(chId, _clanHall.get(chId));
ClanTable.getInstance().getClan(_freeClanHall.get(chId).getOwnerId()).setHideoutId(0);
_freeClanHall.get(chId).free();
_clanHall.remove(chId);
}
/**
* Set ClanHallOwner
* @param chId
* @param clan
*/
public final synchronized void setOwner(int chId, L2Clan clan)
{
if (!_clanHall.containsKey(chId))
{
_clanHall.put(chId, _freeClanHall.get(chId));
_freeClanHall.remove(chId);
}
else
{
_clanHall.get(chId).free();
}
ClanTable.getInstance().getClan(clan.getId()).setHideoutId(chId);
_clanHall.get(chId).setOwner(clan);
}
/**
* @param clanHallId
* @return Clan Hall by Id
*/
public final ClanHall getClanHallById(int clanHallId)
{
return _allClanHalls.get(clanHallId);
}
public final AuctionableHall getAuctionableHallById(int clanHallId)
{
return _allAuctionableClanHalls.get(clanHallId);
}
/**
* @param x
* @param y
* @param z
* @return Clan Hall by x,y,z
*/
public final ClanHall getClanHall(int x, int y, int z)
{
for (ClanHall temp : _allClanHalls.values())
{
if (temp.checkIfInZone(x, y, z))
{
return temp;
}
}
return null;
}
public final ClanHall getClanHall(L2Object activeObject)
{
return getClanHall(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final AuctionableHall getNearbyClanHall(int x, int y, int maxDist)
{
L2ClanHallZone zone = null;
for (Map.Entry<Integer, AuctionableHall> ch : _clanHall.entrySet())
{
zone = ch.getValue().getZone();
if ((zone != null) && (zone.getDistanceToZone(x, y) < maxDist))
{
return ch.getValue();
}
}
for (Map.Entry<Integer, AuctionableHall> ch : _freeClanHall.entrySet())
{
zone = ch.getValue().getZone();
if ((zone != null) && (zone.getDistanceToZone(x, y) < maxDist))
{
return ch.getValue();
}
}
return null;
}
public final ClanHall getNearbyAbstractHall(int x, int y, int maxDist)
{
L2ClanHallZone zone = null;
for (Map.Entry<Integer, ClanHall> ch : _allClanHalls.entrySet())
{
zone = ch.getValue().getZone();
if ((zone != null) && (zone.getDistanceToZone(x, y) < maxDist))
{
return ch.getValue();
}
}
return null;
}
/**
* @param clan
* @return Clan Hall by Owner
*/
public final AuctionableHall getClanHallByOwner(L2Clan clan)
{
for (Map.Entry<Integer, AuctionableHall> ch : _clanHall.entrySet())
{
if (clan.getId() == ch.getValue().getOwnerId())
{
return ch.getValue();
}
}
return null;
}
public final ClanHall getAbstractHallByOwner(L2Clan clan)
{
// Separate loops to avoid iterating over free clan halls
for (Map.Entry<Integer, AuctionableHall> ch : _clanHall.entrySet())
{
if (clan.getId() == ch.getValue().getOwnerId())
{
return ch.getValue();
}
}
for (Map.Entry<Integer, SiegableHall> ch : CHSiegeManager.getInstance().getConquerableHalls().entrySet())
{
if (clan.getId() == ch.getValue().getOwnerId())
{
return ch.getValue();
}
}
return null;
}
public static ClanHallManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClanHallManager _instance = new ClanHallManager();
}
}

View File

@@ -83,21 +83,13 @@ public final class CommissionManager
{
try (PreparedStatement ps = con.prepareStatement(SELECT_ALL_ITEMS))
{
ps.setString(1, ItemLocation.COMMISSION.toString());
ps.setString(1, ItemLocation.COMMISSION.name());
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
final int itemOwnerId = rs.getInt("owner_id");
final int itemObjectId = rs.getInt("object_id");
final L2ItemInstance itemInstance = L2ItemInstance.restoreFromDb(itemOwnerId, rs);
if (itemInstance == null)
{
_log.warning(getClass().getSimpleName() + ": Failed loading item instance with item object id " + itemObjectId + " and owner id " + itemOwnerId + ".");
continue;
}
itemInstances.put(itemObjectId, itemInstance);
final L2ItemInstance itemInstance = new L2ItemInstance(rs);
itemInstances.put(itemInstance.getObjectId(), itemInstance);
}
}
}
@@ -236,7 +228,7 @@ public final class CommissionManager
return;
}
final long registrationFee = (long) Math.max(MIN_REGISTRATION_AND_SALE_FEE, totalPrice * REGISTRATION_FEE_PER_DAY * durationInDays);
final long registrationFee = (long) Math.max(MIN_REGISTRATION_AND_SALE_FEE, (totalPrice * REGISTRATION_FEE_PER_DAY) * durationInDays);
if (!player.getInventory().reduceAdena("Commission Registration Fee", registrationFee, player, null))
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_ADENA_TO_REGISTER_THE_ITEM);
@@ -306,7 +298,7 @@ public final class CommissionManager
return;
}
if ((player.getInventory().getSize(false) >= (player.getInventoryLimit() * 0.8)) || (player.getWeightPenalty() >= 3))
if (!player.isInventoryUnder80(false) || (player.getWeightPenalty() >= 3))
{
player.sendPacket(SystemMessageId.IF_THE_WEIGHT_IS_80_OR_MORE_AND_THE_INVENTORY_NUMBER_IS_90_OR_MORE_PURCHASE_CANCELLATION_IS_NOT_POSSIBLE);
player.sendPacket(SystemMessageId.CANCELLATION_OF_SALE_HAS_FAILED_BECAUSE_REQUIREMENTS_ARE_NOT_MET);
@@ -357,7 +349,7 @@ public final class CommissionManager
return;
}
if ((player.getInventory().getSize(false) >= (player.getInventoryLimit() * 0.8)) || (player.getWeightPenalty() >= 3))
if (!player.isInventoryUnder80(false) || (player.getWeightPenalty() >= 3))
{
player.sendPacket(SystemMessageId.IF_THE_WEIGHT_IS_80_OR_MORE_AND_THE_INVENTORY_NUMBER_IS_90_OR_MORE_PURCHASE_CANCELLATION_IS_NOT_POSSIBLE);
player.sendPacket(ExResponseCommissionBuyItem.FAILED);
@@ -382,7 +374,7 @@ public final class CommissionManager
if (deleteItemFromDB(commissionId))
{
final long saleFee = (long) Math.max(MIN_REGISTRATION_AND_SALE_FEE, totalPrice * SALE_FEE_PER_DAY * commissionItem.getDurationInDays());
final long saleFee = (long) Math.max(MIN_REGISTRATION_AND_SALE_FEE, (totalPrice * SALE_FEE_PER_DAY) * commissionItem.getDurationInDays());
final Message mail = new Message(itemInstance.getOwnerId(), itemInstance, MailType.COMMISSION_ITEM_SOLD);
final Mail attachement = mail.createAttachments();
@@ -430,7 +422,8 @@ public final class CommissionManager
{
if ((_commissionItems.remove(commissionItem.getCommissionId()) != null) && deleteItemFromDB(commissionItem.getCommissionId()))
{
MailManager.getInstance().sendMessage(new Message(commissionItem.getItemInstance().getOwnerId(), commissionItem.getItemInstance(), MailType.COMMISSION_ITEM_RETURNED));
final Message mail = new Message(commissionItem.getItemInstance().getOwnerId(), commissionItem.getItemInstance(), MailType.COMMISSION_ITEM_RETURNED);
MailManager.getInstance().sendMessage(mail);
}
}
@@ -444,6 +437,15 @@ public final class CommissionManager
return _commissionItems.get(commissionId);
}
/**
* @param objectId
* @return {@code true} if player with the objectId has commission items, {@code false} otherwise
*/
public boolean hasCommissionItems(int objectId)
{
return _commissionItems.values().stream().anyMatch(item -> item.getItemInstance().getObjectId() == objectId);
}
/**
* Checks if the player is allowed to interact with commission manager.
* @param player the player

View File

@@ -1,148 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Couple;
/**
* @author evill33t
*/
public final class CoupleManager
{
private static final Logger _log = Logger.getLogger(CoupleManager.class.getName());
private final List<Couple> _couples = new CopyOnWriteArrayList<>();
protected CoupleManager()
{
load();
}
public void reload()
{
_couples.clear();
load();
}
private final void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement ps = con.createStatement();
ResultSet rs = ps.executeQuery("SELECT id FROM mods_wedding ORDER BY id"))
{
while (rs.next())
{
getCouples().add(new Couple(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + getCouples().size() + " couples(s)");
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: CoupleManager.load(): " + e.getMessage(), e);
}
}
public final Couple getCouple(int coupleId)
{
final int index = getCoupleIndex(coupleId);
return index >= 0 ? getCouples().get(index) : null;
}
public void createCouple(L2PcInstance player1, L2PcInstance player2)
{
if ((player1 == null) || (player2 == null) || (player1.getPartnerId() != 0) || (player2.getPartnerId() != 0))
{
return;
}
final int player1id = player1.getObjectId();
final int player2id = player2.getObjectId();
final Couple couple = new Couple(player1, player2);
getCouples().add(couple);
player1.setPartnerId(player2id);
player2.setPartnerId(player1id);
player1.setCoupleId(couple.getId());
player2.setCoupleId(couple.getId());
}
public void deleteCouple(int coupleId)
{
final int index = getCoupleIndex(coupleId);
final Couple couple = getCouples().get(index);
if (couple == null)
{
return;
}
final L2PcInstance player1 = L2World.getInstance().getPlayer(couple.getPlayer1Id());
final L2PcInstance player2 = L2World.getInstance().getPlayer(couple.getPlayer2Id());
if (player1 != null)
{
player1.setPartnerId(0);
player1.setMarried(false);
player1.setCoupleId(0);
}
if (player2 != null)
{
player2.setPartnerId(0);
player2.setMarried(false);
player2.setCoupleId(0);
}
couple.divorce();
getCouples().remove(index);
}
public final int getCoupleIndex(int coupleId)
{
int i = 0;
for (Couple temp : getCouples())
{
if ((temp != null) && (temp.getId() == coupleId))
{
return i;
}
i++;
}
return -1;
}
public final List<Couple> getCouples()
{
return _couples;
}
public static CoupleManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CoupleManager _instance = new CoupleManager();
}
}

View File

@@ -1,424 +1,402 @@
/*
* 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.instancemanager;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.CursedWeapon;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2FeedableBeastInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2FortCommanderInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2GuardInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Broadcast;
/**
* UnAfraid: TODO: Rewrite with DocumentParser
* @author Micht
*/
public final class CursedWeaponsManager
{
private static final Logger _log = Logger.getLogger(CursedWeaponsManager.class.getName());
private Map<Integer, CursedWeapon> _cursedWeapons;
protected CursedWeaponsManager()
{
init();
}
private void init()
{
_cursedWeapons = new HashMap<>();
if (!Config.ALLOW_CURSED_WEAPONS)
{
return;
}
load();
restore();
controlPlayers();
_log.info(getClass().getSimpleName() + ": Loaded : " + _cursedWeapons.size() + " cursed weapon(s).");
}
public final void reload()
{
init();
}
private final void load()
{
try
{
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
final File file = new File(Config.DATAPACK_ROOT + "/CursedWeapons.xml");
if (!file.exists())
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't find " + file.getName());
return;
}
for (Node n = factory.newDocumentBuilder().parse(file).getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
final int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
final int skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
final String name = attrs.getNamedItem("name").getNodeValue();
final CursedWeapon cw = new CursedWeapon(id, skillId, name);
int val;
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("dropRate".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDropRate(val);
}
else if ("duration".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDuration(val);
}
else if ("durationLost".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDurationLost(val);
}
else if ("disapearChance".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDisapearChance(val);
}
else if ("stageKills".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setStageKills(val);
}
}
// Store cursed weapon
_cursedWeapons.put(id, cw);
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error parsing cursed weapons file.", e);
return;
}
}
private final void restore()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT itemId, charId, playerKarma, playerPkKills, nbKills, endTime FROM cursed_weapons"))
{
// Retrieve the L2PcInstance from the characters table of the database
CursedWeapon cw;
while (rs.next())
{
cw = _cursedWeapons.get(rs.getInt("itemId"));
cw.setPlayerId(rs.getInt("charId"));
cw.setPlayerKarma(rs.getInt("playerKarma"));
cw.setPlayerPkKills(rs.getInt("playerPkKills"));
cw.setNbKills(rs.getInt("nbKills"));
cw.setEndTime(rs.getLong("endTime"));
cw.reActivate();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not restore CursedWeapons data: " + e.getMessage(), e);
}
}
private final void controlPlayers()
{
// TODO: See comments below...
// This entire for loop should NOT be necessary, since it is already handled by
// CursedWeapon.endOfLife(). However, if we indeed *need* to duplicate it for safety,
// then we'd better make sure that it FULLY cleans up inactive cursed weapons!
// Undesired effects result otherwise, such as player with no zariche but with karma
// or a lost-child entry in the cursed weapons table, without a corresponding one in items...
// Retrieve the L2PcInstance from the characters table of the database
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?"))
{
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated())
{
continue;
}
// Do an item check to be sure that the cursed weapon isn't hold by someone
final int itemId = cw.getItemId();
ps.setInt(1, itemId);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
// A player has the cursed weapon in his inventory ...
final int playerId = rset.getInt("owner_id");
_log.info("PROBLEM : Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
// Delete the item
try (PreparedStatement delete = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?"))
{
delete.setInt(1, playerId);
delete.setInt(2, itemId);
if (delete.executeUpdate() != 1)
{
_log.warning("Error while deleting cursed weapon " + itemId + " from userId " + playerId);
}
}
// Restore the player's old karma and pk count
try (PreparedStatement update = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE charId=?"))
{
update.setInt(1, cw.getPlayerKarma());
update.setInt(2, cw.getPlayerPkKills());
update.setInt(3, playerId);
if (update.executeUpdate() != 1)
{
_log.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
}
}
// clean up the cursed weapons table.
removeFromDb(itemId);
}
}
ps.clearParameters();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not check CursedWeapons data: " + e.getMessage(), e);
}
}
public synchronized void checkDrop(L2Attackable attackable, L2PcInstance player)
{
if ((attackable instanceof L2DefenderInstance) || (attackable instanceof L2GuardInstance) || (attackable instanceof L2GrandBossInstance) || (attackable instanceof L2FeedableBeastInstance) || (attackable instanceof L2FortCommanderInstance))
{
return;
}
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActive())
{
continue;
}
if (cw.checkDrop(attackable, player))
{
break;
}
}
}
public void activate(L2PcInstance player, L2ItemInstance item)
{
final CursedWeapon cw = _cursedWeapons.get(item.getId());
if (player.isCursedWeaponEquipped()) // cannot own 2 cursed swords
{
final CursedWeapon cw2 = _cursedWeapons.get(player.getCursedWeaponEquippedId());
// TODO: give the bonus level in a more appropriate manner.
// The following code adds "_stageKills" levels. This will also show in the char status.
// I do not have enough info to know if the bonus should be shown in the pk count, or if it
// should be a full "_stageKills" bonus or just the remaining from the current count till the of the current stage...
// This code is a TEMP fix, so that the cursed weapon's bonus level can be observed with as little change in the code as possible, until proper info arises.
cw2.setNbKills(cw2.getStageKills() - 1);
cw2.increaseKills();
// erase the newly obtained cursed weapon
cw.setPlayer(player); // NECESSARY in order to find which inventory the weapon is in!
cw.endOfLife(); // expire the weapon and clean up.
}
else
{
cw.activate(player, item);
}
}
public void drop(int itemId, L2Character killer)
{
_cursedWeapons.get(itemId).dropIt(killer);
}
public void increaseKills(int itemId)
{
_cursedWeapons.get(itemId).increaseKills();
}
public int getLevel(int itemId)
{
return _cursedWeapons.get(itemId).getLevel();
}
public static void announce(SystemMessage sm)
{
Broadcast.toAllOnlinePlayers(sm);
}
public void checkPlayer(L2PcInstance player)
{
if (player == null)
{
return;
}
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated() && (player.getObjectId() == cw.getPlayerId()))
{
cw.setPlayer(player);
cw.setItem(player.getInventory().getItemByItemId(cw.getItemId()));
cw.giveSkill();
player.setCursedWeaponEquippedId(cw.getItemId());
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_HAS_S2_MINUTE_S_OF_USAGE_TIME_REMAINING);
sm.addString(cw.getName());
// sm.addItemName(cw.getItemId());
sm.addInt((int) ((cw.getEndTime() - System.currentTimeMillis()) / 60000));
player.sendPacket(sm);
}
}
}
public int checkOwnsWeaponId(int ownerId)
{
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated() && (ownerId == cw.getPlayerId()))
{
return cw.getItemId();
}
}
return -1;
}
public static void removeFromDb(int itemId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?"))
{
ps.setInt(1, itemId);
ps.executeUpdate();
}
catch (SQLException e)
{
_log.log(Level.SEVERE, "CursedWeaponsManager: Failed to remove data: " + e.getMessage(), e);
}
}
public void saveData()
{
for (CursedWeapon cw : _cursedWeapons.values())
{
cw.saveData();
}
}
public boolean isCursed(int itemId)
{
return _cursedWeapons.containsKey(itemId);
}
public Collection<CursedWeapon> getCursedWeapons()
{
return _cursedWeapons.values();
}
public Set<Integer> getCursedWeaponsIds()
{
return _cursedWeapons.keySet();
}
public CursedWeapon getCursedWeapon(int itemId)
{
return _cursedWeapons.get(itemId);
}
public void givePassive(int itemId)
{
try
{
_cursedWeapons.get(itemId).giveSkill();
}
catch (Exception e)
{
/***/
}
}
public static CursedWeaponsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CursedWeaponsManager _instance = new CursedWeaponsManager();
}
}
/*
* 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.instancemanager;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.CursedWeapon;
import com.l2jmobius.gameserver.model.actor.L2Attackable;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2FeedableBeastInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2FortCommanderInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2GuardInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.Broadcast;
/**
* UnAfraid: TODO: Rewrite with DocumentParser
* @author Micht
*/
public final class CursedWeaponsManager implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(CursedWeaponsManager.class.getName());
private final Map<Integer, CursedWeapon> _cursedWeapons = new HashMap<>();
protected CursedWeaponsManager()
{
load();
}
@Override
public void load()
{
if (!Config.ALLOW_CURSED_WEAPONS)
{
return;
}
parseDatapackFile("data/CursedWeapons.xml");
restore();
controlPlayers();
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _cursedWeapons.size() + " cursed weapon(s).");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
final int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
final int skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
final String name = attrs.getNamedItem("name").getNodeValue();
final CursedWeapon cw = new CursedWeapon(id, skillId, name);
int val;
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("dropRate".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDropRate(val);
}
else if ("duration".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDuration(val);
}
else if ("durationLost".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDurationLost(val);
}
else if ("disapearChance".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setDisapearChance(val);
}
else if ("stageKills".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
val = Integer.parseInt(attrs.getNamedItem("val").getNodeValue());
cw.setStageKills(val);
}
}
// Store cursed weapon
_cursedWeapons.put(id, cw);
}
}
}
}
}
private void restore()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT itemId, charId, playerReputation, playerPkKills, nbKills, endTime FROM cursed_weapons"))
{
// Retrieve the L2PcInstance from the characters table of the database
CursedWeapon cw;
while (rs.next())
{
cw = _cursedWeapons.get(rs.getInt("itemId"));
cw.setPlayerId(rs.getInt("charId"));
cw.setPlayerReputation(rs.getInt("playerReputation"));
cw.setPlayerPkKills(rs.getInt("playerPkKills"));
cw.setNbKills(rs.getInt("nbKills"));
cw.setEndTime(rs.getLong("endTime"));
cw.reActivate();
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not restore CursedWeapons data: ", e);
}
}
private void controlPlayers()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?"))
{
// TODO: See comments below...
// This entire for loop should NOT be necessary, since it is already handled by
// CursedWeapon.endOfLife(). However, if we indeed *need* to duplicate it for safety,
// then we'd better make sure that it FULLY cleans up inactive cursed weapons!
// Undesired effects result otherwise, such as player with no zariche but with karma
// or a lost-child entry in the cursed weapons table, without a corresponding one in items...
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated())
{
continue;
}
// Do an item check to be sure that the cursed weapon isn't hold by someone
final int itemId = cw.getItemId();
ps.setInt(1, itemId);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
// A player has the cursed weapon in his inventory ...
final int playerId = rset.getInt("owner_id");
LOGGER.info("PROBLEM : Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
// Delete the item
try (PreparedStatement delete = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?"))
{
delete.setInt(1, playerId);
delete.setInt(2, itemId);
if (delete.executeUpdate() != 1)
{
LOGGER.warning("Error while deleting cursed weapon " + itemId + " from userId " + playerId);
}
}
// Restore the player's old karma and pk count
try (PreparedStatement update = con.prepareStatement("UPDATE characters SET reputation=?, pkkills=? WHERE charId=?"))
{
update.setInt(1, cw.getPlayerReputation());
update.setInt(2, cw.getPlayerPkKills());
update.setInt(3, playerId);
if (update.executeUpdate() != 1)
{
LOGGER.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
}
}
// clean up the cursed weapons table.
removeFromDb(itemId);
}
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Could not check CursedWeapons data: ", e);
}
}
public synchronized void checkDrop(L2Attackable attackable, L2PcInstance player)
{
if ((attackable instanceof L2DefenderInstance) || (attackable instanceof L2GuardInstance) || (attackable instanceof L2GrandBossInstance) || (attackable instanceof L2FeedableBeastInstance) || (attackable instanceof L2FortCommanderInstance))
{
return;
}
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActive())
{
continue;
}
if (cw.checkDrop(attackable, player))
{
break;
}
}
}
public void activate(L2PcInstance player, L2ItemInstance item)
{
final CursedWeapon cw = _cursedWeapons.get(item.getId());
if (player.isCursedWeaponEquipped()) // cannot own 2 cursed swords
{
final CursedWeapon cw2 = _cursedWeapons.get(player.getCursedWeaponEquippedId());
// TODO: give the bonus level in a more appropriate manner.
// The following code adds "_stageKills" levels. This will also show in the char status.
// I do not have enough info to know if the bonus should be shown in the pk count, or if it
// should be a full "_stageKills" bonus or just the remaining from the current count till the of the current stage...
// This code is a TEMP fix, so that the cursed weapon's bonus level can be observed with as little change in the code as possible, until proper info arises.
cw2.setNbKills(cw2.getStageKills() - 1);
cw2.increaseKills();
// erase the newly obtained cursed weapon
cw.setPlayer(player); // NECESSARY in order to find which inventory the weapon is in!
cw.endOfLife(); // expire the weapon and clean up.
}
else
{
cw.activate(player, item);
}
}
public void drop(int itemId, L2Character killer)
{
final CursedWeapon cw = _cursedWeapons.get(itemId);
cw.dropIt(killer);
}
public void increaseKills(int itemId)
{
final CursedWeapon cw = _cursedWeapons.get(itemId);
cw.increaseKills();
}
public int getLevel(int itemId)
{
final CursedWeapon cw = _cursedWeapons.get(itemId);
return cw.getLevel();
}
public static void announce(SystemMessage sm)
{
Broadcast.toAllOnlinePlayers(sm);
}
public void checkPlayer(L2PcInstance player)
{
if (player == null)
{
return;
}
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated() && (player.getObjectId() == cw.getPlayerId()))
{
cw.setPlayer(player);
cw.setItem(player.getInventory().getItemByItemId(cw.getItemId()));
cw.giveSkill();
player.setCursedWeaponEquippedId(cw.getItemId());
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_HAS_S2_MINUTE_S_OF_USAGE_TIME_REMAINING);
sm.addString(cw.getName());
// sm.addItemName(cw.getItemId());
sm.addInt((int) ((cw.getEndTime() - System.currentTimeMillis()) / 60000));
player.sendPacket(sm);
}
}
}
public int checkOwnsWeaponId(int ownerId)
{
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated() && (ownerId == cw.getPlayerId()))
{
return cw.getItemId();
}
}
return -1;
}
public static void removeFromDb(int itemId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?"))
{
ps.setInt(1, itemId);
ps.executeUpdate();
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "Failed to remove data: " + e.getMessage(), e);
}
}
public void saveData()
{
for (CursedWeapon cw : _cursedWeapons.values())
{
cw.saveData();
}
}
public boolean isCursed(int itemId)
{
return _cursedWeapons.containsKey(itemId);
}
public Collection<CursedWeapon> getCursedWeapons()
{
return _cursedWeapons.values();
}
public Set<Integer> getCursedWeaponsIds()
{
return _cursedWeapons.keySet();
}
public CursedWeapon getCursedWeapon(int itemId)
{
return _cursedWeapons.get(itemId);
}
public void givePassive(int itemId)
{
try
{
_cursedWeapons.get(itemId).giveSkill();
}
catch (Exception e)
{
/***/
}
}
public static CursedWeaponsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CursedWeaponsManager _instance = new CursedWeaponsManager();
}
}

View File

@@ -0,0 +1,645 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.data.xml.impl.SpawnsData;
import com.l2jmobius.gameserver.datatables.SpawnTable;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.spawns.NpcSpawnTemplate;
import com.l2jmobius.gameserver.util.Util;
/**
* Database spawn manager.
* @author godson, UnAfraid
*/
public class DBSpawnManager
{
private static final Logger LOGGER = Logger.getLogger(DBSpawnManager.class.getName());
protected final Map<Integer, L2Npc> _npcs = new ConcurrentHashMap<>();
protected final Map<Integer, L2Spawn> _spawns = new ConcurrentHashMap<>();
protected final Map<Integer, StatsSet> _storedInfo = new ConcurrentHashMap<>();
protected final Map<Integer, ScheduledFuture<?>> _schedules = new ConcurrentHashMap<>();
public static enum DBStatusType
{
ALIVE,
DEAD,
UNDEFINED
}
/**
* Instantiates a new raid npc spawn manager.
*/
protected DBSpawnManager()
{
load();
}
/**
* Load.
*/
public void load()
{
_npcs.clear();
_spawns.clear();
_storedInfo.clear();
_schedules.clear();
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM npc_respawns");
ResultSet rset = statement.executeQuery())
{
while (rset.next())
{
final L2NpcTemplate template = getValidTemplate(rset.getInt("id"));
if (template != null)
{
final L2Spawn spawn = new L2Spawn(template);
spawn.setX(rset.getInt("x"));
spawn.setY(rset.getInt("y"));
spawn.setZ(rset.getInt("z"));
spawn.setAmount(1);
spawn.setHeading(rset.getInt("heading"));
final List<NpcSpawnTemplate> spawns = SpawnsData.getInstance().getSpawns(npc -> (npc.getId() == template.getId()) && npc.hasDBSave());
if (spawns.isEmpty())
{
LOGGER.warning(getClass().getSimpleName() + ": Couldn't find spawn declaration for npc: " + template.getId() + " - " + template.getName());
deleteSpawn(spawn, true);
continue;
}
else if (spawns.size() > 1)
{
LOGGER.warning(getClass().getSimpleName() + ": Found multiple database spawns for npc: " + template.getId() + " - " + template.getName() + " " + spawns);
continue;
}
final NpcSpawnTemplate spawnTemplate = spawns.get(0);
spawn.setSpawnTemplate(spawnTemplate);
int respawn = 0, respawnRandom = 0;
if (spawnTemplate.getRespawnTime() != null)
{
respawn = (int) spawnTemplate.getRespawnTime().getSeconds();
}
if (spawnTemplate.getRespawnTimeRandom() != null)
{
respawnRandom = (int) spawnTemplate.getRespawnTimeRandom().getSeconds();
}
if (respawn > 0)
{
spawn.setRespawnDelay(respawn, respawnRandom);
spawn.startRespawn();
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Found database spawns without respawn for npc: " + template.getId() + " - " + template.getName() + " " + spawnTemplate);
continue;
}
addNewSpawn(spawn, rset.getLong("respawnTime"), rset.getDouble("currentHp"), rset.getDouble("currentMp"), false);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Could not load npc #" + rset.getInt("id") + " from DB");
}
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _npcs.size() + " Instances");
LOGGER.info(getClass().getSimpleName() + ": Scheduled " + _schedules.size() + " Instances");
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Couldnt load npc_respawns table", e);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing DBSpawnManager: ", e);
}
}
private class SpawnSchedule implements Runnable
{
private final Logger LOGGER = Logger.getLogger(SpawnSchedule.class.getName());
private final int _npcId;
/**
* Instantiates a new spawn schedule.
* @param npcId the npc id
*/
public SpawnSchedule(int npcId)
{
_npcId = npcId;
}
@Override
public void run()
{
final L2Npc npc = _spawns.get(_npcId).doSpawn();
if (npc != null)
{
npc.setDBStatus(DBStatusType.ALIVE);
final StatsSet info = new StatsSet();
info.set("currentHP", npc.getCurrentHp());
info.set("currentMP", npc.getCurrentMp());
info.set("respawnTime", 0L);
_storedInfo.put(_npcId, info);
_npcs.put(_npcId, npc);
LOGGER.info(getClass().getSimpleName() + ": Spawning NPC " + npc.getName());
}
_schedules.remove(_npcId);
}
}
/**
* Update status.
* @param npc the npc
* @param isNpcDead the is npc dead
*/
public void updateStatus(L2Npc npc, boolean isNpcDead)
{
final StatsSet info = _storedInfo.get(npc.getId());
if (info == null)
{
return;
}
if (isNpcDead)
{
npc.setDBStatus(DBStatusType.DEAD);
final int respawnMinDelay = (int) (npc.getSpawn().getRespawnMinDelay() * Config.RAID_MIN_RESPAWN_MULTIPLIER);
final int respawnMaxDelay = (int) (npc.getSpawn().getRespawnMaxDelay() * Config.RAID_MAX_RESPAWN_MULTIPLIER);
final int respawnDelay = Rnd.get(respawnMinDelay, respawnMaxDelay);
final long respawnTime = System.currentTimeMillis() + respawnDelay;
info.set("currentHP", npc.getMaxHp());
info.set("currentMP", npc.getMaxMp());
info.set("respawnTime", respawnTime);
if (!_schedules.containsKey(npc.getId()) && ((respawnMinDelay > 0) || (respawnMaxDelay > 0)))
{
LOGGER.info(getClass().getSimpleName() + ": Updated " + npc.getName() + " respawn time to " + Util.formatDate(new Date(respawnTime), "dd.MM.yyyy HH:mm"));
_schedules.put(npc.getId(), ThreadPoolManager.getInstance().scheduleGeneral(new SpawnSchedule(npc.getId()), respawnDelay));
updateDb();
}
}
else
{
npc.setDBStatus(DBStatusType.ALIVE);
info.set("currentHP", npc.getCurrentHp());
info.set("currentMP", npc.getCurrentMp());
info.set("respawnTime", 0L);
}
_storedInfo.put(npc.getId(), info);
}
/**
* Adds the new spawn.
* @param spawn the spawn dat
* @param respawnTime the respawn time
* @param currentHP the current hp
* @param currentMP the current mp
* @param storeInDb the store in db
*/
public void addNewSpawn(L2Spawn spawn, long respawnTime, double currentHP, double currentMP, boolean storeInDb)
{
if (spawn == null)
{
return;
}
if (_spawns.containsKey(spawn.getId()))
{
return;
}
final int npcId = spawn.getId();
final long time = System.currentTimeMillis();
SpawnTable.getInstance().addNewSpawn(spawn, false);
if ((respawnTime == 0L) || (time > respawnTime))
{
final L2Npc npc = spawn.doSpawn();
if (npc != null)
{
npc.setCurrentHp(currentHP);
npc.setCurrentMp(currentMP);
npc.setDBStatus(DBStatusType.ALIVE);
_npcs.put(npcId, npc);
final StatsSet info = new StatsSet();
info.set("currentHP", currentHP);
info.set("currentMP", currentMP);
info.set("respawnTime", 0L);
_storedInfo.put(npcId, info);
}
}
else
{
final long spawnTime = respawnTime - System.currentTimeMillis();
_schedules.put(npcId, ThreadPoolManager.getInstance().scheduleGeneral(new SpawnSchedule(npcId), spawnTime));
}
_spawns.put(npcId, spawn);
if (storeInDb)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO npc_respawns (id, x, y, z, heading, respawnTime, currentHp, currentMp) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"))
{
statement.setInt(1, spawn.getId());
statement.setInt(2, spawn.getX());
statement.setInt(3, spawn.getY());
statement.setInt(4, spawn.getZ());
statement.setInt(5, spawn.getHeading());
statement.setLong(6, respawnTime);
statement.setDouble(7, currentHP);
statement.setDouble(8, currentMP);
statement.execute();
}
catch (Exception e)
{
// problem with storing spawn
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not store npc #" + npcId + " in the DB: ", e);
}
}
}
public void addNewSpawn(L2Spawn spawn, boolean storeInDb)
{
if (spawn == null)
{
return;
}
final int npcId = spawn.getId();
if (_spawns.containsKey(npcId))
{
return;
}
SpawnTable.getInstance().addNewSpawn(spawn, false);
final L2Npc npc = spawn.doSpawn();
if (npc == null)
{
throw new NullPointerException();
}
npc.setDBStatus(DBStatusType.ALIVE);
final StatsSet info = new StatsSet();
info.set("currentHP", npc.getMaxHp());
info.set("currentMP", npc.getMaxMp());
info.set("respawnTime", 0L);
_npcs.put(npcId, npc);
_storedInfo.put(npcId, info);
_spawns.put(npcId, spawn);
if (storeInDb)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO npc_respawns (id, x, y, z, heading, respawnTime, currentHp, currentMp) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"))
{
statement.setInt(1, spawn.getId());
statement.setInt(2, spawn.getX());
statement.setInt(3, spawn.getY());
statement.setInt(4, spawn.getZ());
statement.setInt(5, spawn.getHeading());
statement.setLong(6, 0);
statement.setDouble(7, npc.getMaxHp());
statement.setDouble(8, npc.getMaxMp());
statement.execute();
}
catch (Exception e)
{
// problem with storing spawn
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not store npc #" + npcId + " in the DB: ", e);
}
}
}
/**
* Delete spawn.
* @param spawn the spawn dat
* @param updateDb the update db
*/
public void deleteSpawn(L2Spawn spawn, boolean updateDb)
{
if (spawn == null)
{
return;
}
final int npcId = spawn.getId();
if (!_spawns.containsKey(npcId))
{
return;
}
SpawnTable.getInstance().deleteSpawn(spawn, false);
_spawns.remove(npcId);
if (_npcs.containsKey(npcId))
{
_npcs.remove(npcId);
}
if (_schedules.containsKey(npcId))
{
final ScheduledFuture<?> f = _schedules.remove(npcId);
f.cancel(true);
}
if (_storedInfo.containsKey(npcId))
{
_storedInfo.remove(npcId);
}
if (updateDb)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM npc_respawns WHERE id = ?"))
{
ps.setInt(1, npcId);
ps.execute();
}
catch (Exception e)
{
// problem with deleting spawn
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not remove npc #" + npcId + " from DB: ", e);
}
}
}
/**
* Update database.
*/
private void updateDb()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("UPDATE npc_respawns SET respawnTime = ?, currentHP = ?, currentMP = ? WHERE id = ?"))
{
for (Integer npcId : _storedInfo.keySet())
{
if (npcId == null)
{
continue;
}
final L2Npc npc = _npcs.get(npcId);
if (npc == null)
{
continue;
}
if (npc.getDBStatus().equals(DBStatusType.ALIVE))
{
updateStatus(npc, false);
}
final StatsSet info = _storedInfo.get(npcId);
if (info == null)
{
continue;
}
try
{
statement.setLong(1, info.getLong("respawnTime"));
statement.setDouble(2, info.getDouble("currentHP"));
statement.setDouble(3, info.getDouble("currentMP"));
statement.setInt(4, npcId);
statement.executeUpdate();
statement.clearParameters();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Couldnt update npc_respawns table ", e);
}
}
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": SQL error while updating database spawn to database: ", e);
}
}
/**
* Gets the all npc status.
* @return the all npc status
*/
public String[] getAllNpcsStatus()
{
final String[] msg = new String[(_npcs == null) ? 0 : _npcs.size()];
if (_npcs == null)
{
msg[0] = "None";
return msg;
}
int index = 0;
for (int i : _npcs.keySet())
{
final L2Npc npc = _npcs.get(i);
msg[index++] = npc.getName() + ": " + npc.getDBStatus().name();
}
return msg;
}
/**
* Gets the npc status.
* @param npcId the npc id
* @return the raid npc status
*/
public String getNpcsStatus(int npcId)
{
String msg = "NPC Status..." + Config.EOL;
if (_npcs == null)
{
msg += "None";
return msg;
}
if (_npcs.containsKey(npcId))
{
final L2Npc npc = _npcs.get(npcId);
msg += npc.getName() + ": " + npc.getDBStatus().name();
}
return msg;
}
/**
* Gets the raid npc status id.
* @param npcId the npc id
* @return the raid npc status id
*/
public DBStatusType getNpcStatusId(int npcId)
{
if (_npcs.containsKey(npcId))
{
return _npcs.get(npcId).getDBStatus();
}
else if (_schedules.containsKey(npcId))
{
return DBStatusType.DEAD;
}
else
{
return DBStatusType.UNDEFINED;
}
}
/**
* Gets the valid template.
* @param npcId the npc id
* @return the valid template
*/
public L2NpcTemplate getValidTemplate(int npcId)
{
return NpcData.getInstance().getTemplate(npcId);
}
/**
* Notify spawn night npc.
* @param npc the npc
*/
public void notifySpawnNightNpc(L2Npc npc)
{
final StatsSet info = new StatsSet();
info.set("currentHP", npc.getCurrentHp());
info.set("currentMP", npc.getCurrentMp());
info.set("respawnTime", 0L);
npc.setDBStatus(DBStatusType.ALIVE);
_storedInfo.put(npc.getId(), info);
_npcs.put(npc.getId(), npc);
}
/**
* Checks if the npc is defined.
* @param npcId the npc id
* @return {@code true} if is defined
*/
public boolean isDefined(int npcId)
{
return _spawns.containsKey(npcId);
}
/**
* Gets the npcs.
* @return the npcs
*/
public Map<Integer, L2Npc> getNpcs()
{
return _npcs;
}
/**
* Gets the spawns.
* @return the spawns
*/
public Map<Integer, L2Spawn> getSpawns()
{
return _spawns;
}
/**
* Gets the stored info.
* @return the stored info
*/
public Map<Integer, StatsSet> getStoredInfo()
{
return _storedInfo;
}
/**
* Saves and clears the raid npces status, including all schedules.
*/
public void cleanUp()
{
updateDb();
_npcs.clear();
if (_schedules != null)
{
for (Integer npcId : _schedules.keySet())
{
final ScheduledFuture<?> f = _schedules.get(npcId);
f.cancel(true);
}
_schedules.clear();
}
_storedInfo.clear();
_spawns.clear();
}
/**
* Gets the single instance of DBSpawnManager.
* @return single instance of DBSpawnManager
*/
public static DBSpawnManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final DBSpawnManager _instance = new DBSpawnManager();
}
}

View File

@@ -0,0 +1,259 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.sql.impl.ClanTable;
import com.l2jmobius.gameserver.data.xml.impl.OneDayRewardData;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.OneDayRewardDataHolder;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.stat.PcStat;
import com.l2jmobius.gameserver.model.base.SubClass;
import com.l2jmobius.gameserver.model.eventengine.AbstractEvent;
import com.l2jmobius.gameserver.model.eventengine.AbstractEventManager;
import com.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.olympiad.Olympiad;
import com.l2jmobius.gameserver.model.variables.PlayerVariables;
import com.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import com.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
/**
* @author UnAfraid
*/
public class DailyTaskManager extends AbstractEventManager<AbstractEvent<?>>
{
private static final Logger LOGGER = Logger.getLogger(DailyTaskManager.class.getName());
protected DailyTaskManager()
{
}
@Override
public void onInitialized()
{
}
@ScheduleTarget
private void onReset()
{
resetClanBonus();
resetExtendDrop();
resetDailySkills();
resetWorldChatPoints();
resetOneDayReward();
resetRecommends();
}
@ScheduleTarget
private void onSave()
{
GlobalVariablesManager.getInstance().storeMe();
if (Olympiad.getInstance().inCompPeriod())
{
Olympiad.getInstance().saveOlympiadStatus();
LOGGER.info("Olympiad System: Data updated.");
}
}
@ScheduleTarget
private void onClanLeaderApply()
{
for (L2Clan clan : ClanTable.getInstance().getClans())
{
if (clan.getNewLeaderId() != 0)
{
final L2ClanMember member = clan.getClanMember(clan.getNewLeaderId());
if (member == null)
{
continue;
}
clan.setNewLeader(member);
}
}
LOGGER.info("Clan leaders has been updated");
}
@ScheduleTarget
private void onVitalityReset()
{
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
player.setVitalityPoints(PcStat.MAX_VITALITY_POINTS, false);
for (SubClass subclass : player.getSubClasses().values())
{
subclass.setVitalityPoints(PcStat.MAX_VITALITY_POINTS);
}
}
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement st = con.prepareStatement("UPDATE character_subclasses SET vitality_points = ?"))
{
st.setInt(1, PcStat.MAX_VITALITY_POINTS);
st.execute();
}
try (PreparedStatement st = con.prepareStatement("UPDATE characters SET vitality_points = ?"))
{
st.setInt(1, PcStat.MAX_VITALITY_POINTS);
st.execute();
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Error while updating vitality", e);
}
LOGGER.info("Vitality resetted");
}
private void resetClanBonus()
{
ClanTable.getInstance().getClans().forEach(L2Clan::resetClanBonus);
LOGGER.info("Daily clan bonus has been resetted.");
}
private void resetExtendDrop()
{
// Update data for offline players.
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM character_variables WHERE var = ?"))
{
ps.setString(1, PlayerVariables.EXTEND_DROP);
ps.execute();
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Could not reset extend drop : ", e);
}
// Update data for online players.
L2World.getInstance().getPlayers().stream().forEach(player ->
{
player.getVariables().set(PlayerVariables.EXTEND_DROP, "");
player.getVariables().storeMe();
});
LOGGER.info("Daily world chat points has been resetted.");
}
private void resetDailySkills()
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
final List<SkillHolder> dailySkills = getVariables().getList("reset_skills", SkillHolder.class, Collections.emptyList());
for (SkillHolder skill : dailySkills)
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM character_skills_save WHERE skill_id=?;"))
{
ps.setInt(1, skill.getSkillId());
ps.execute();
}
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Could not reset daily skill reuse: ", e);
}
LOGGER.info("Daily skill reuse cleaned.");
}
private void resetWorldChatPoints()
{
// Update data for offline players.
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE character_variables SET val = ? WHERE var = ?"))
{
ps.setInt(1, Config.WORLD_CHAT_POINTS_PER_DAY);
ps.setString(2, PlayerVariables.WORLD_CHAT_VARIABLE_NAME);
ps.executeUpdate();
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Could not reset daily world chat points: ", e);
}
// Update data for online players.
L2World.getInstance().getPlayers().stream().forEach(player ->
{
player.setWorldChatPoints(Config.WORLD_CHAT_POINTS_PER_DAY);
player.sendPacket(new ExWorldChatCnt(player));
player.getVariables().storeMe();
});
LOGGER.info("Daily world chat points has been resetted.");
}
private void resetRecommends()
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement ps = con.prepareStatement("UPDATE character_reco_bonus SET rec_left = ?, rec_have = 0 WHERE rec_have <= 20"))
{
ps.setInt(1, 0); // Rec left = 0
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("UPDATE character_reco_bonus SET rec_left = ?, rec_have = GREATEST(rec_have - 20,0) WHERE rec_have > 20"))
{
ps.setInt(1, 0); // Rec left = 0
ps.execute();
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Could not reset Recommendations System: ", e);
}
L2World.getInstance().getPlayers().stream().forEach(player ->
{
player.setRecomLeft(0);
player.setRecomHave(player.getRecomHave() - 20);
player.sendPacket(new ExVoteSystemInfo(player));
player.broadcastUserInfo();
});
}
private void resetOneDayReward()
{
OneDayRewardData.getInstance().getOneDayRewardData().forEach(OneDayRewardDataHolder::reset);
}
public static DailyTaskManager getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final DailyTaskManager INSTANCE = new DailyTaskManager();
}
}

View File

@@ -1,264 +0,0 @@
/*
* 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.instancemanager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.GameTimeController;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2RaidBossInstance;
/**
* @author godson
*/
public final class DayNightSpawnManager
{
private static Logger _log = Logger.getLogger(DayNightSpawnManager.class.getName());
private final List<L2Spawn> _dayCreatures = new ArrayList<>();
private final List<L2Spawn> _nightCreatures = new ArrayList<>();
private final Map<L2Spawn, L2RaidBossInstance> _bosses = new ConcurrentHashMap<>();
// private static int _currentState; // 0 = Day, 1 = Night
public static DayNightSpawnManager getInstance()
{
return SingletonHolder._instance;
}
protected DayNightSpawnManager()
{
// Prevent external initialization.
}
public void addDayCreature(L2Spawn spawnDat)
{
_dayCreatures.add(spawnDat);
}
public void addNightCreature(L2Spawn spawnDat)
{
_nightCreatures.add(spawnDat);
}
/**
* Spawn Day Creatures, and Unspawn Night Creatures
*/
public void spawnDayCreatures()
{
spawnCreatures(_nightCreatures, _dayCreatures, "night", "day");
}
/**
* Spawn Night Creatures, and Unspawn Day Creatures
*/
public void spawnNightCreatures()
{
spawnCreatures(_dayCreatures, _nightCreatures, "day", "night");
}
/**
* Manage Spawn/Respawn
* @param unSpawnCreatures List with spawns must be unspawned
* @param spawnCreatures List with spawns must be spawned
* @param UnspawnLogInfo String for log info for unspawned L2NpcInstance
* @param SpawnLogInfo String for log info for spawned L2NpcInstance
*/
private void spawnCreatures(List<L2Spawn> unSpawnCreatures, List<L2Spawn> spawnCreatures, String UnspawnLogInfo, String SpawnLogInfo)
{
try
{
if (!unSpawnCreatures.isEmpty())
{
int i = 0;
for (L2Spawn spawn : unSpawnCreatures)
{
if (spawn == null)
{
continue;
}
spawn.stopRespawn();
final L2Npc last = spawn.getLastSpawn();
if (last != null)
{
last.deleteMe();
i++;
}
}
_log.info("DayNightSpawnManager: Removed " + i + " " + UnspawnLogInfo + " creatures");
}
int i = 0;
for (L2Spawn spawnDat : spawnCreatures)
{
if (spawnDat == null)
{
continue;
}
spawnDat.startRespawn();
spawnDat.doSpawn();
i++;
}
_log.info("DayNightSpawnManager: Spawned " + i + " " + SpawnLogInfo + " creatures");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while spawning creatures: " + e.getMessage(), e);
}
}
private void changeMode(int mode)
{
if (_nightCreatures.isEmpty() && _dayCreatures.isEmpty() && _bosses.isEmpty())
{
return;
}
switch (mode)
{
case 0:
{
spawnDayCreatures();
specialNightBoss(0);
break;
}
case 1:
{
spawnNightCreatures();
specialNightBoss(1);
break;
}
default:
{
_log.warning("DayNightSpawnManager: Wrong mode sent");
break;
}
}
}
public DayNightSpawnManager trim()
{
((ArrayList<?>) _nightCreatures).trimToSize();
((ArrayList<?>) _dayCreatures).trimToSize();
return this;
}
public void notifyChangeMode()
{
try
{
changeMode(GameTimeController.getInstance().isNight() ? 1 : 0);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while notifyChangeMode(): " + e.getMessage(), e);
}
}
public void cleanUp()
{
_nightCreatures.clear();
_dayCreatures.clear();
_bosses.clear();
}
private void specialNightBoss(int mode)
{
try
{
L2RaidBossInstance boss;
for (L2Spawn spawn : _bosses.keySet())
{
boss = _bosses.get(spawn);
if ((boss == null) && (mode == 1))
{
boss = (L2RaidBossInstance) spawn.doSpawn();
RaidBossSpawnManager.getInstance().notifySpawnNightBoss(boss);
_bosses.put(spawn, boss);
continue;
}
if ((boss == null) && (mode == 0))
{
continue;
}
if ((boss != null) && (boss.getId() == 25328) && boss.getRaidStatus().equals(RaidBossSpawnManager.StatusEnum.ALIVE))
{
handleHellmans(boss, mode);
}
return;
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while specialNoghtBoss(): " + e.getMessage(), e);
}
}
private void handleHellmans(L2RaidBossInstance boss, int mode)
{
switch (mode)
{
case 0:
{
boss.deleteMe();
_log.info(getClass().getSimpleName() + ": Deleting Hellman raidboss");
break;
}
case 1:
{
if (!boss.isVisible())
{
boss.spawnMe();
}
_log.info(getClass().getSimpleName() + ": Spawning Hellman raidboss");
break;
}
}
}
public L2RaidBossInstance handleBoss(L2Spawn spawnDat)
{
if (_bosses.containsKey(spawnDat))
{
return _bosses.get(spawnDat);
}
if (GameTimeController.getInstance().isNight())
{
final L2RaidBossInstance raidboss = (L2RaidBossInstance) spawnDat.doSpawn();
_bosses.put(spawnDat, raidboss);
return raidboss;
}
return null;
}
private static class SingletonHolder
{
protected static final DayNightSpawnManager _instance = new DayNightSpawnManager();
}
}

View File

@@ -1,248 +1,235 @@
/*
* 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.instancemanager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class DuelManager
{
private final Map<Integer, Duel> _duels = new ConcurrentHashMap<>();
private final AtomicInteger _currentDuelId = new AtomicInteger();
protected DuelManager()
{
}
public Duel getDuel(int duelId)
{
return _duels.get(duelId);
}
public void addDuel(L2PcInstance playerA, L2PcInstance playerB, boolean partyDuel)
{
if ((playerA == null) || (playerB == null))
{
return;
}
// return if a player has PvPFlag
final String engagedInPvP = "The duel was canceled because a duelist engaged in PvP combat.";
if (partyDuel)
{
boolean playerInPvP = false;
for (L2PcInstance temp : playerA.getParty().getMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
if (!playerInPvP)
{
for (L2PcInstance temp : playerB.getParty().getMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
}
// A player has PvP flag
if (playerInPvP)
{
for (L2PcInstance temp : playerA.getParty().getMembers())
{
temp.sendMessage(engagedInPvP);
}
for (L2PcInstance temp : playerB.getParty().getMembers())
{
temp.sendMessage(engagedInPvP);
}
return;
}
}
else if ((playerA.getPvpFlag() != 0) || (playerB.getPvpFlag() != 0))
{
playerA.sendMessage(engagedInPvP);
playerB.sendMessage(engagedInPvP);
return;
}
final int duelId = _currentDuelId.incrementAndGet();
_duels.put(duelId, new Duel(playerA, playerB, partyDuel, duelId));
}
public void removeDuel(Duel duel)
{
_duels.remove(duel.getId());
}
public void doSurrender(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
getDuel(player.getDuelId()).doSurrender(player);
}
/**
* Updates player states.
* @param player - the dying player
*/
public void onPlayerDefeat(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onPlayerDefeat(player);
}
}
/**
* Registers a buff which will be removed if the duel ends
* @param player
* @param buff
*/
public void onBuff(L2PcInstance player, Skill buff)
{
if ((player == null) || !player.isInDuel() || (buff == null))
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onBuff(player, buff);
}
}
/**
* Broadcasts a packet to the team opposing the given player.
* @param player
* @param packet
*/
public void broadcastToOppositTeam(L2PcInstance player, L2GameServerPacket packet)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel == null)
{
return;
}
if (duel.getTeamA().contains(player))
{
duel.broadcastToTeam2(packet);
}
else
{
duel.broadcastToTeam1(packet);
}
}
/**
* Checks if this player might join / start a duel.<br>
* @param player
* @param target
* @param partyDuel
* @return true if the player might join/start a duel.
*/
public static boolean canDuel(L2PcInstance player, L2PcInstance target, boolean partyDuel)
{
SystemMessageId reason = null;
if (target.isInCombat() || target.isJailed())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_ENGAGED_IN_BATTLE;
}
else if (target.isTransformed())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_POLYMORPHED;
}
else if (target.isDead() || target.isAlikeDead() || (target.getCurrentHp() < (target.getMaxHp() / 2)) || (target.getCurrentMp() < (target.getMaxMp() / 2)))
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_S_HP_OR_MP_IS_BELOW_50;
}
else if (target.isInDuel())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_ALREADY_ENGAGED_IN_A_DUEL;
}
else if (target.isInOlympiadMode())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_PARTICIPATING_IN_THE_OLYMPIAD_OR_THE_CEREMONY_OF_CHAOS;
}
else if (target.isCursedWeaponEquipped())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_IN_A_CHAOTIC_OR_PURPLE_STATE;
}
else if (target.getPrivateStoreType() != PrivateStoreType.NONE)
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_ENGAGED_IN_A_PRIVATE_STORE_OR_MANUFACTURE;
}
else if (target.isMounted() || target.isInBoat())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_RIDING_A_BOAT_FENRIR_OR_STRIDER;
}
else if (target.isFishing())
{
reason = SystemMessageId.C1_CANNOT_DUEL_BECAUSE_C1_IS_CURRENTLY_FISHING;
}
else if ((!partyDuel && target.isInsideZone(ZoneId.PEACE)) || target.isInsideZone(ZoneId.PVP) || target.isInsideZone(ZoneId.SIEGE))
{
reason = SystemMessageId.C1_CANNOT_MAKE_A_CHALLENGE_TO_A_DUEL_BECAUSE_C1_IS_CURRENTLY_IN_A_DUEL_PROHIBITED_AREA_PEACEFUL_ZONE_BATTLE_ZONE_NEAR_WATER_RESTART_PROHIBITED_AREA;
}
if (reason != null)
{
final SystemMessage msg = SystemMessage.getSystemMessage(reason);
msg.addString(target.getName());
player.sendPacket(msg);
return false;
}
return true;
}
public static DuelManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final DuelManager _instance = new DuelManager();
}
/*
* 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.instancemanager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Duel;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
public final class DuelManager
{
private static final int[] ARENAS =
{
147, // OlympiadGrassyArena.xml
148, // OlympiadThreeBridgesArena.xml
149, // OlympiadHerossVestigesArena.xml
150, // OlympiadOrbisArena.xml
};
private final Map<Integer, Duel> _duels = new ConcurrentHashMap<>();
private final AtomicInteger _currentDuelId = new AtomicInteger();
protected DuelManager()
{
}
public Duel getDuel(int duelId)
{
return _duels.get(duelId);
}
public void addDuel(L2PcInstance playerA, L2PcInstance playerB, int partyDuel)
{
if ((playerA == null) || (playerB == null))
{
return;
}
// return if a player has PvPFlag
final String engagedInPvP = "The duel was canceled because a duelist engaged in PvP combat.";
if (partyDuel == 1)
{
boolean playerInPvP = false;
for (L2PcInstance temp : playerA.getParty().getMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
if (!playerInPvP)
{
for (L2PcInstance temp : playerB.getParty().getMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
}
// A player has PvP flag
if (playerInPvP)
{
for (L2PcInstance temp : playerA.getParty().getMembers())
{
temp.sendMessage(engagedInPvP);
}
for (L2PcInstance temp : playerB.getParty().getMembers())
{
temp.sendMessage(engagedInPvP);
}
return;
}
}
else
{
if ((playerA.getPvpFlag() != 0) || (playerB.getPvpFlag() != 0))
{
playerA.sendMessage(engagedInPvP);
playerB.sendMessage(engagedInPvP);
return;
}
}
final int duelId = _currentDuelId.incrementAndGet();
_duels.put(duelId, new Duel(playerA, playerB, partyDuel, duelId));
}
public void removeDuel(Duel duel)
{
_duels.remove(duel.getId());
}
public void doSurrender(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
duel.doSurrender(player);
}
/**
* Updates player states.
* @param player - the dying player
*/
public void onPlayerDefeat(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onPlayerDefeat(player);
}
}
/**
* Registers a buff which will be removed if the duel ends
* @param player
* @param buff
*/
public void onBuff(L2PcInstance player, Skill buff)
{
if ((player == null) || !player.isInDuel() || (buff == null))
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onBuff(player, buff);
}
}
/**
* Removes player from duel.
* @param player - the removed player
*/
public void onRemoveFromParty(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onRemoveFromParty(player);
}
}
/**
* Broadcasts a packet to the team opposing the given player.
* @param player
* @param packet
*/
public void broadcastToOppositTeam(L2PcInstance player, IClientOutgoingPacket packet)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel == null)
{
return;
}
if ((duel.getPlayerA() == null) || (duel.getPlayerB() == null))
{
return;
}
if (duel.getPlayerA() == player)
{
duel.broadcastToTeam2(packet);
}
else if (duel.getPlayerB() == player)
{
duel.broadcastToTeam1(packet);
}
else if (duel.isPartyDuel())
{
if ((duel.getPlayerA().getParty() != null) && duel.getPlayerA().getParty().getMembers().contains(player))
{
duel.broadcastToTeam2(packet);
}
else if ((duel.getPlayerB().getParty() != null) && duel.getPlayerB().getParty().getMembers().contains(player))
{
duel.broadcastToTeam1(packet);
}
}
}
/**
* Gets new a random Olympiad Stadium instance name.
* @return an instance name
*/
public int getDuelArena()
{
return ARENAS[Rnd.get(ARENAS.length)];
}
public static DuelManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final DuelManager _instance = new DuelManager();
}
}

View File

@@ -1,530 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.util.Rnd;
/**
* @author n0nam3
* @date 08/08/2010 15:11
*/
public class FishingChampionshipManager
{
protected static final Logger _log = Logger.getLogger(FishingChampionshipManager.class.getName());
private static final String INSERT = "INSERT INTO fishing_championship(player_name,fish_length,rewarded) VALUES (?,?,?)";
private static final String DELETE = "DELETE FROM fishing_championship";
private static final String SELECT = "SELECT `player_name`, `fish_length`, `rewarded` FROM fishing_championship";
private static final FishingChampionshipManager _instance = new FishingChampionshipManager();
public static FishingChampionshipManager getInstance()
{
return _instance;
}
protected long _enddate = 0;
protected final List<String> _playersName = new ArrayList<>();
protected final List<String> _fishLength = new ArrayList<>();
protected final List<String> _winPlayersName = new ArrayList<>();
protected final List<String> _winFishLength = new ArrayList<>();
protected final List<Fisher> _tmpPlayers = new ArrayList<>();
protected final List<Fisher> _winPlayers = new ArrayList<>();
protected double _minFishLength = 0;
protected boolean _needRefresh = true;
private FishingChampionshipManager()
{
restoreData();
refreshWinResult();
recalculateMinLength();
if (_enddate <= System.currentTimeMillis())
{
_enddate = System.currentTimeMillis();
new finishChamp().run();
}
else
{
ThreadPoolManager.getInstance().scheduleGeneral(new finishChamp(), _enddate - System.currentTimeMillis());
}
}
protected void setEndOfChamp()
{
final Calendar finishtime = Calendar.getInstance();
finishtime.setTimeInMillis(_enddate);
finishtime.set(Calendar.MINUTE, 0);
finishtime.set(Calendar.SECOND, 0);
finishtime.add(Calendar.DAY_OF_MONTH, 6);
finishtime.set(Calendar.DAY_OF_WEEK, 3);
finishtime.set(Calendar.HOUR_OF_DAY, 19);
_enddate = finishtime.getTimeInMillis();
}
private void restoreData()
{
_enddate = GlobalVariablesManager.getInstance().getLong("fishChampionshipEnd", 0);
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
final PreparedStatement statement = con.prepareStatement(SELECT);
final ResultSet rs = statement.executeQuery();
while (rs.next())
{
final int rewarded = rs.getInt("rewarded");
if (rewarded == 0)
{
_tmpPlayers.add(new Fisher(rs.getString("player_name"), rs.getDouble("fish_length"), 0));
}
else if (rewarded > 0)
{
_winPlayers.add(new Fisher(rs.getString("player_name"), rs.getDouble("fish_length"), rewarded));
}
}
rs.close();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "FishingChampionshipManager: can't restore fishing championship info: " + e.getMessage(), e);
}
}
public synchronized void newFish(L2PcInstance pl, int lureId)
{
if (!Config.ALT_FISH_CHAMPIONSHIP_ENABLED)
{
return;
}
double len = Rnd.get(60, 89) + (Rnd.get(0, 1000) / 1000.);
if ((lureId >= 8484) && (lureId <= 8486))
{
len += Rnd.get(0, 3000) / 1000.;
}
pl.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CAUGHT_A_FISH_S1_IN_LENGTH).addString(String.valueOf(len)));
if (_tmpPlayers.size() < 5)
{
for (Fisher fisher : _tmpPlayers)
{
if (fisher.getName().equalsIgnoreCase(pl.getName()))
{
if (fisher.getLength() < len)
{
fisher.setLength(len);
pl.sendPacket(SystemMessageId.BECAUSE_OF_THE_SIZE_OF_FISH_CAUGHT_YOU_WILL_BE_REGISTERED_IN_THE_RANKING);
recalculateMinLength();
}
return;
}
}
_tmpPlayers.add(new Fisher(pl.getName(), len, 0));
pl.sendPacket(SystemMessageId.BECAUSE_OF_THE_SIZE_OF_FISH_CAUGHT_YOU_WILL_BE_REGISTERED_IN_THE_RANKING);
recalculateMinLength();
}
else if (_minFishLength < len)
{
for (Fisher fisher : _tmpPlayers)
{
if (fisher.getName().equalsIgnoreCase(pl.getName()))
{
if (fisher.getLength() < len)
{
fisher.setLength(len);
pl.sendPacket(SystemMessageId.BECAUSE_OF_THE_SIZE_OF_FISH_CAUGHT_YOU_WILL_BE_REGISTERED_IN_THE_RANKING);
recalculateMinLength();
}
return;
}
}
Fisher minFisher = null;
double minLen = 99999.;
for (Fisher fisher : _tmpPlayers)
{
if (fisher.getLength() < minLen)
{
minFisher = fisher;
minLen = minFisher.getLength();
}
}
_tmpPlayers.remove(minFisher);
_tmpPlayers.add(new Fisher(pl.getName(), len, 0));
pl.sendPacket(SystemMessageId.BECAUSE_OF_THE_SIZE_OF_FISH_CAUGHT_YOU_WILL_BE_REGISTERED_IN_THE_RANKING);
recalculateMinLength();
}
}
private void recalculateMinLength()
{
double minLen = 99999.;
for (Fisher fisher : _tmpPlayers)
{
if (fisher.getLength() < minLen)
{
minLen = fisher.getLength();
}
}
_minFishLength = minLen;
}
public long getTimeRemaining()
{
return (_enddate - System.currentTimeMillis()) / 60000;
}
public String getWinnerName(int par)
{
return _winPlayersName.size() >= par ? _winPlayersName.get(par - 1) : "None";
}
public String getCurrentName(int par)
{
return _playersName.size() >= par ? _playersName.get(par - 1) : "None";
}
public String getFishLength(int par)
{
return _winFishLength.size() >= par ? _winFishLength.get(par - 1) : "0";
}
public String getCurrentFishLength(int par)
{
return _fishLength.size() >= par ? _fishLength.get(par - 1) : "0";
}
public boolean isWinner(String playerName)
{
for (String name : _winPlayersName)
{
if (name.equals(playerName))
{
return true;
}
}
return false;
}
public void getReward(L2PcInstance pl)
{
for (Fisher fisher : _winPlayers)
{
if (fisher.getName().equalsIgnoreCase(pl.getName()) && (fisher.getRewardType() != 2))
{
int rewardCnt = 0;
for (int x = 0; x < _winPlayersName.size(); x++)
{
if (_winPlayersName.get(x).equalsIgnoreCase(pl.getName()))
{
switch (x)
{
case 0:
{
rewardCnt = Config.ALT_FISH_CHAMPIONSHIP_REWARD_1;
break;
}
case 1:
{
rewardCnt = Config.ALT_FISH_CHAMPIONSHIP_REWARD_2;
break;
}
case 2:
{
rewardCnt = Config.ALT_FISH_CHAMPIONSHIP_REWARD_3;
break;
}
case 3:
{
rewardCnt = Config.ALT_FISH_CHAMPIONSHIP_REWARD_4;
break;
}
case 4:
{
rewardCnt = Config.ALT_FISH_CHAMPIONSHIP_REWARD_5;
break;
}
}
}
}
fisher.setRewardType(2);
if (rewardCnt > 0)
{
pl.addItem("fishing_reward", Config.ALT_FISH_CHAMPIONSHIP_REWARD_ITEM, rewardCnt, null, true);
final NpcHtmlMessage html = new NpcHtmlMessage();
html.setFile(pl.getHtmlPrefix(), "html/fisherman/championship/fish_event_reward001.htm");
pl.sendPacket(html);
}
}
}
}
public void showMidResult(L2PcInstance pl)
{
final NpcHtmlMessage html = new NpcHtmlMessage();
if (_needRefresh)
{
html.setFile(pl.getHtmlPrefix(), "html/fisherman/championship/fish_event003.htm");
pl.sendPacket(html);
refreshResult();
ThreadPoolManager.getInstance().scheduleGeneral(new needRefresh(), 60000);
return;
}
html.setFile(pl.getHtmlPrefix(), "html/fisherman/championship/fish_event002.htm");
String str = null;
for (int x = 1; x <= 5; x++)
{
str += "<tr><td width=70 align=center>" + x + "</td>";
str += "<td width=110 align=center>" + getCurrentName(x) + "</td>";
str += "<td width=80 align=center>" + getCurrentFishLength(x) + "</td></tr>";
}
html.replace("%TABLE%", str);
html.replace("%prizeItem%", ItemTable.getInstance().getTemplate(Config.ALT_FISH_CHAMPIONSHIP_REWARD_ITEM).getName());
html.replace("%prizeFirst%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_1));
html.replace("%prizeTwo%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_2));
html.replace("%prizeThree%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_3));
html.replace("%prizeFour%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_4));
html.replace("%prizeFive%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_5));
pl.sendPacket(html);
}
public void showChampScreen(L2PcInstance pl, L2NpcInstance npc)
{
final NpcHtmlMessage html = new NpcHtmlMessage();
html.setFile(pl.getHtmlPrefix(), "html/fisherman/championship/fish_event001.htm");
String str = null;
for (int x = 1; x <= 5; x++)
{
str += "<tr><td width=70 align=center>" + x + "</td>";
str += "<td width=110 align=center>" + getWinnerName(x) + "</td>";
str += "<td width=80 align=center>" + getFishLength(x) + "</td></tr>";
}
html.replace("%TABLE%", str);
html.replace("%prizeItem%", ItemTable.getInstance().getTemplate(Config.ALT_FISH_CHAMPIONSHIP_REWARD_ITEM).getName());
html.replace("%prizeFirst%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_1));
html.replace("%prizeTwo%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_2));
html.replace("%prizeThree%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_3));
html.replace("%prizeFour%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_4));
html.replace("%prizeFive%", String.valueOf(Config.ALT_FISH_CHAMPIONSHIP_REWARD_5));
html.replace("%refresh%", String.valueOf(getTimeRemaining()));
html.replace("%objectId%", String.valueOf(npc.getObjectId()));
pl.sendPacket(html);
}
public void shutdown()
{
GlobalVariablesManager.getInstance().set("fishChampionshipEnd", _enddate);
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
PreparedStatement statement = con.prepareStatement(DELETE);
statement.execute();
statement.close();
for (Fisher fisher : _winPlayers)
{
statement = con.prepareStatement(INSERT);
statement.setString(1, fisher.getName());
statement.setDouble(2, fisher.getLength());
statement.setInt(3, fisher.getRewardType());
statement.execute();
statement.close();
}
for (Fisher fisher : _tmpPlayers)
{
statement = con.prepareStatement(INSERT);
statement.setString(1, fisher.getName());
statement.setDouble(2, fisher.getLength());
statement.setInt(3, 0);
statement.execute();
statement.close();
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "FishingChampionshipManager: can't update infos: " + e.getMessage(), e);
}
}
private synchronized void refreshResult()
{
_needRefresh = false;
_playersName.clear();
_fishLength.clear();
Fisher fisher1;
Fisher fisher2;
for (int x = 0; x <= (_tmpPlayers.size() - 1); x++)
{
for (int y = 0; y <= (_tmpPlayers.size() - 2); y++)
{
fisher1 = _tmpPlayers.get(y);
fisher2 = _tmpPlayers.get(y + 1);
if (fisher1.getLength() < fisher2.getLength())
{
_tmpPlayers.set(y, fisher2);
_tmpPlayers.set(y + 1, fisher1);
}
}
}
for (int x = 0; x <= (_tmpPlayers.size() - 1); x++)
{
_playersName.add(_tmpPlayers.get(x).getName());
_fishLength.add(String.valueOf(_tmpPlayers.get(x).getLength()));
}
}
protected void refreshWinResult()
{
_winPlayersName.clear();
_winFishLength.clear();
Fisher fisher1;
Fisher fisher2;
for (int x = 0; x <= (_winPlayers.size() - 1); x++)
{
for (int y = 0; y <= (_winPlayers.size() - 2); y++)
{
fisher1 = _winPlayers.get(y);
fisher2 = _winPlayers.get(y + 1);
if (fisher1.getLength() < fisher2.getLength())
{
_winPlayers.set(y, fisher2);
_winPlayers.set(y + 1, fisher1);
}
}
}
for (int x = 0; x <= (_winPlayers.size() - 1); x++)
{
_winPlayersName.add(_winPlayers.get(x).getName());
_winFishLength.add(String.valueOf(_winPlayers.get(x).getLength()));
}
}
private class finishChamp implements Runnable
{
protected finishChamp()
{
// Do nothing
}
@Override
public void run()
{
_winPlayers.clear();
for (Fisher fisher : _tmpPlayers)
{
fisher.setRewardType(1);
_winPlayers.add(fisher);
}
_tmpPlayers.clear();
refreshWinResult();
setEndOfChamp();
shutdown();
_log.info("FishingChampionshipManager : new event period start.");
ThreadPoolManager.getInstance().scheduleGeneral(new finishChamp(), _enddate - System.currentTimeMillis());
}
}
private class needRefresh implements Runnable
{
protected needRefresh()
{
// Do nothing
}
@Override
public void run()
{
_needRefresh = true;
}
}
private class Fisher
{
private double _length;
private final String _name;
private int _reward;
public Fisher(String name, double length, int rewardType)
{
_name = name;
_length = length;
_reward = rewardType;
}
public void setLength(double value)
{
_length = value;
}
public void setRewardType(int value)
{
_reward = value;
}
public String getName()
{
return _name;
}
public int getRewardType()
{
return _reward;
}
public double getLength()
{
return _length;
}
}
}

View File

@@ -1,207 +1,169 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.InstanceListManager;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.entity.Fort;
public final class FortManager implements InstanceListManager
{
protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
private final List<Fort> _forts = new ArrayList<>();
public final int findNearestFortIndex(L2Object obj)
{
return findNearestFortIndex(obj, Long.MAX_VALUE);
}
public final int findNearestFortIndex(L2Object obj, long maxDistance)
{
int index = getFortIndex(obj);
if (index < 0)
{
double distance;
Fort fort;
for (int i = 0; i < _forts.size(); i++)
{
fort = _forts.get(i);
if (fort == null)
{
continue;
}
distance = fort.getDistance(obj);
if (maxDistance > distance)
{
maxDistance = (long) distance;
index = i;
}
}
}
return index;
}
public final Fort getFortById(int fortId)
{
for (Fort f : _forts)
{
if (f.getResidenceId() == fortId)
{
return f;
}
}
return null;
}
public final Fort getFortByOwner(L2Clan clan)
{
for (Fort f : _forts)
{
if (f.getOwnerClan() == clan)
{
return f;
}
}
return null;
}
public final Fort getFort(String name)
{
for (Fort f : _forts)
{
if (f.getName().equalsIgnoreCase(name.trim()))
{
return f;
}
}
return null;
}
public final Fort getFort(int x, int y, int z)
{
for (Fort f : _forts)
{
if (f.checkIfInZone(x, y, z))
{
return f;
}
}
return null;
}
public final Fort getFort(L2Object activeObject)
{
return getFort(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getFortIndex(int fortId)
{
Fort fort;
for (int i = 0; i < _forts.size(); i++)
{
fort = _forts.get(i);
if ((fort != null) && (fort.getResidenceId() == fortId))
{
return i;
}
}
return -1;
}
public final int getFortIndex(L2Object activeObject)
{
return getFortIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getFortIndex(int x, int y, int z)
{
Fort fort;
for (int i = 0; i < _forts.size(); i++)
{
fort = _forts.get(i);
if ((fort != null) && fort.checkIfInZone(x, y, z))
{
return i;
}
}
return -1;
}
public final List<Fort> getForts()
{
return _forts;
}
@Override
public void loadInstances()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM fort ORDER BY id"))
{
while (rs.next())
{
_forts.add(new Fort(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _forts.size() + " fortress");
for (Fort fort : _forts)
{
fort.getSiege().getSiegeGuardManager().loadSiegeGuard();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortData(): " + e.getMessage(), e);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (Fort fort : _forts)
{
fort.activateInstance();
}
}
public static FortManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final FortManager _instance = new FortManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.InstanceListManager;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.entity.Fort;
public final class FortManager implements InstanceListManager
{
protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
private final Map<Integer, Fort> _forts = new ConcurrentSkipListMap<>();
public final Fort findNearestFort(L2Object obj)
{
return findNearestFort(obj, Long.MAX_VALUE);
}
public final Fort findNearestFort(L2Object obj, long maxDistance)
{
Fort nearestFort = getFort(obj);
if (nearestFort == null)
{
for (Fort fort : getForts())
{
final double distance = fort.getDistance(obj);
if (maxDistance > distance)
{
maxDistance = (long) distance;
nearestFort = fort;
}
}
}
return nearestFort;
}
public final Fort getFortById(int fortId)
{
for (Fort f : getForts())
{
if (f.getResidenceId() == fortId)
{
return f;
}
}
return null;
}
public final Fort getFortByOwner(L2Clan clan)
{
for (Fort f : getForts())
{
if (f.getOwnerClan() == clan)
{
return f;
}
}
return null;
}
public final Fort getFort(String name)
{
for (Fort f : getForts())
{
if (f.getName().equalsIgnoreCase(name.trim()))
{
return f;
}
}
return null;
}
public final Fort getFort(int x, int y, int z)
{
for (Fort f : getForts())
{
if (f.checkIfInZone(x, y, z))
{
return f;
}
}
return null;
}
public final Fort getFort(L2Object activeObject)
{
return getFort(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final Collection<Fort> getForts()
{
return _forts.values();
}
@Override
public void loadInstances()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM fort ORDER BY id"))
{
while (rs.next())
{
final int fortId = rs.getInt("id");
_forts.put(fortId, new Fort(fortId));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + getForts().size() + " fortress");
for (Fort fort : getForts())
{
fort.getSiege().loadSiegeGuard();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortData(): " + e.getMessage(), e);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (Fort fort : getForts())
{
fort.activateInstance();
}
}
public static FortManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final FortManager _instance = new FortManager();
}
}

View File

@@ -1,146 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.entity.Fort;
public final class FortSiegeGuardManager
{
private static final Logger _log = Logger.getLogger(FortSiegeGuardManager.class.getName());
private final Fort _fort;
private final Map<Integer, List<L2Spawn>> _siegeGuards = new HashMap<>();
public FortSiegeGuardManager(Fort fort)
{
_fort = fort;
}
/**
* Spawn guards.
*/
public void spawnSiegeGuard()
{
try
{
final List<L2Spawn> monsterList = _siegeGuards.get(getFort().getResidenceId());
if (monsterList != null)
{
for (L2Spawn spawnDat : monsterList)
{
spawnDat.doSpawn();
if (spawnDat.getRespawnDelay() == 0)
{
spawnDat.stopRespawn();
}
else
{
spawnDat.startRespawn();
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error spawning siege guards for fort " + getFort().getName() + ":" + e.getMessage(), e);
}
}
/**
* Unspawn guards.
*/
public void unspawnSiegeGuard()
{
try
{
final List<L2Spawn> monsterList = _siegeGuards.get(getFort().getResidenceId());
if (monsterList != null)
{
for (L2Spawn spawnDat : monsterList)
{
spawnDat.stopRespawn();
if (spawnDat.getLastSpawn() != null)
{
spawnDat.getLastSpawn().doDie(spawnDat.getLastSpawn());
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error unspawning siege guards for fort " + getFort().getName() + ":" + e.getMessage(), e);
}
}
/**
* Load guards.
*/
void loadSiegeGuard()
{
_siegeGuards.clear();
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT npcId, x, y, z, heading, respawnDelay FROM fort_siege_guards WHERE fortId = ?"))
{
final int fortId = getFort().getResidenceId();
ps.setInt(1, fortId);
try (ResultSet rs = ps.executeQuery())
{
final List<L2Spawn> siegeGuardSpawns = new ArrayList<>();
while (rs.next())
{
final L2Spawn spawn = new L2Spawn(rs.getInt("npcId"));
spawn.setAmount(1);
spawn.setX(rs.getInt("x"));
spawn.setY(rs.getInt("y"));
spawn.setZ(rs.getInt("z"));
spawn.setHeading(rs.getInt("heading"));
spawn.setRespawnDelay(rs.getInt("respawnDelay"));
spawn.setLocationId(0);
siegeGuardSpawns.add(spawn);
}
_siegeGuards.put(fortId, siegeGuardSpawns);
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error loading siege guard for fort " + getFort().getName() + ": " + e.getMessage(), e);
}
}
public final Fort getFort()
{
return _fort;
}
public final Map<Integer, List<L2Spawn>> getSiegeGuardSpawn()
{
return _siegeGuards;
}
}

View File

@@ -1,333 +1,359 @@
/*
* 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.instancemanager;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.CombatFlag;
import com.l2jmobius.gameserver.model.FortSiegeSpawn;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.entity.FortSiege;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.CommonSkill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class FortSiegeManager
{
private static final Logger _log = Logger.getLogger(FortSiegeManager.class.getName());
private int _attackerMaxClans = 500; // Max number of clans
// Fort Siege settings
private Map<Integer, List<FortSiegeSpawn>> _commanderSpawnList;
private Map<Integer, List<CombatFlag>> _flagList;
private boolean _justToTerritory = true; // Changeable in fortsiege.properties
private int _flagMaxCount = 1; // Changeable in fortsiege.properties
private int _siegeClanMinLevel = 4; // Changeable in fortsiege.properties
private int _siegeLength = 60; // Time in minute. Changeable in fortsiege.properties
private int _countDownLength = 10; // Time in minute. Changeable in fortsiege.properties
private int _suspiciousMerchantRespawnDelay = 180; // Time in minute. Changeable in fortsiege.properties
private final List<FortSiege> _sieges = new ArrayList<>();
protected FortSiegeManager()
{
load();
}
public final void addSiegeSkills(L2PcInstance character)
{
character.addSkill(CommonSkill.SEAL_OF_RULER.getSkill(), false);
character.addSkill(CommonSkill.BUILD_HEADQUARTERS.getSkill(), false);
}
/**
* @param clan The L2Clan of the player
* @param fortid
* @return true if the clan is registered or owner of a fort
*/
public final boolean checkIsRegistered(L2Clan clan, int fortid)
{
if (clan == null)
{
return false;
}
boolean register = false;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT clan_id FROM fortsiege_clans where clan_id=? and fort_id=?"))
{
ps.setInt(1, clan.getId());
ps.setInt(2, fortid);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
register = true;
break;
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: checkIsRegistered(): " + e.getMessage(), e);
}
return register;
}
public final void removeSiegeSkills(L2PcInstance character)
{
character.removeSkill(CommonSkill.SEAL_OF_RULER.getSkill());
character.removeSkill(CommonSkill.BUILD_HEADQUARTERS.getSkill());
}
private final void load()
{
final Properties siegeSettings = new Properties();
final File file = new File(Config.FORTSIEGE_CONFIGURATION_FILE);
try (InputStream is = new FileInputStream(file))
{
siegeSettings.load(is);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while loading Fort Siege Manager settings!", e);
}
// Siege setting
_justToTerritory = Boolean.parseBoolean(siegeSettings.getProperty("JustToTerritory", "true"));
_attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
_flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
_siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "4"));
_siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "60"));
_countDownLength = Integer.decode(siegeSettings.getProperty("CountDownLength", "10"));
_suspiciousMerchantRespawnDelay = Integer.decode(siegeSettings.getProperty("SuspiciousMerchantRespawnDelay", "180"));
// Siege spawns settings
_commanderSpawnList = new ConcurrentHashMap<>();
_flagList = new ConcurrentHashMap<>();
for (Fort fort : FortManager.getInstance().getForts())
{
final List<FortSiegeSpawn> commanderSpawns = new ArrayList<>();
final List<CombatFlag> flagSpawns = new ArrayList<>();
for (int i = 1; i < 5; i++)
{
final String _spawnParams = siegeSettings.getProperty(fort.getName().replace(" ", "") + "Commander" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
final StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
commanderSpawns.add(new FortSiegeSpawn(fort.getResidenceId(), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), i));
}
catch (Exception e)
{
_log.warning("Error while loading commander(s) for " + fort.getName() + " fort.");
}
}
_commanderSpawnList.put(fort.getResidenceId(), commanderSpawns);
for (int i = 1; i < 4; i++)
{
final String _spawnParams = siegeSettings.getProperty(fort.getName().replace(" ", "") + "Flag" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
final StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
flagSpawns.add(new CombatFlag(fort.getResidenceId(), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), 0, Integer.parseInt(st.nextToken())));
}
catch (Exception e)
{
_log.warning("Error while loading flag(s) for " + fort.getName() + " fort.");
}
}
_flagList.put(fort.getResidenceId(), flagSpawns);
}
}
public final List<FortSiegeSpawn> getCommanderSpawnList(int _fortId)
{
return _commanderSpawnList.get(_fortId);
}
public final List<CombatFlag> getFlagList(int _fortId)
{
return _flagList.get(_fortId);
}
public final int getAttackerMaxClans()
{
return _attackerMaxClans;
}
public final int getFlagMaxCount()
{
return _flagMaxCount;
}
public final boolean canRegisterJustTerritory()
{
return _justToTerritory;
}
public final int getSuspiciousMerchantRespawnDelay()
{
return _suspiciousMerchantRespawnDelay;
}
public final FortSiege getSiege(L2Object activeObject)
{
return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final FortSiege getSiege(int x, int y, int z)
{
for (Fort fort : FortManager.getInstance().getForts())
{
if (fort.getSiege().checkIfInZone(x, y, z))
{
return fort.getSiege();
}
}
return null;
}
public final int getSiegeClanMinLevel()
{
return _siegeClanMinLevel;
}
public final int getSiegeLength()
{
return _siegeLength;
}
public final int getCountDownLength()
{
return _countDownLength;
}
public final List<FortSiege> getSieges()
{
return _sieges;
}
public final void addSiege(FortSiege fortSiege)
{
_sieges.add(fortSiege);
}
public boolean isCombat(int itemId)
{
return itemId == 9819;
}
public boolean activateCombatFlag(L2PcInstance player, L2ItemInstance item)
{
if (!checkIfCanPickup(player))
{
return false;
}
final Fort fort = FortManager.getInstance().getFort(player);
final List<CombatFlag> fcf = _flagList.get(fort.getResidenceId());
for (CombatFlag cf : fcf)
{
if (cf.getCombatFlagInstance() == item)
{
cf.activate(player, item);
}
}
return true;
}
public boolean checkIfCanPickup(L2PcInstance player)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_OF_S1_HAS_FINISHED);
sm.addItemName(9819);
// Cannot own 2 combat flag
if (player.isCombatFlagEquipped())
{
player.sendPacket(sm);
return false;
}
// here check if is siege is in progress
// here check if is siege is attacker
final Fort fort = FortManager.getInstance().getFort(player);
if ((fort != null) && (fort.getResidenceId() > 0) && fort.getSiege().isInProgress() && (fort.getSiege().getAttackerClan(player.getClan()) != null))
{
return true;
}
player.sendPacket(sm);
return false;
}
public void dropCombatFlag(L2PcInstance player, int fortId)
{
final Fort fort = FortManager.getInstance().getFortById(fortId);
for (CombatFlag cf : _flagList.get(fort.getResidenceId()))
{
if (cf.getPlayerObjectId() == player.getObjectId())
{
cf.dropIt();
if (fort.getSiege().isInProgress())
{
cf.spawnMe();
}
}
}
}
public static FortSiegeManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final FortSiegeManager _instance = new FortSiegeManager();
}
}
/*
* 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.instancemanager;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.CombatFlag;
import com.l2jmobius.gameserver.model.FortSiegeSpawn;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.entity.FortSiege;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.CommonSkill;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
public final class FortSiegeManager
{
private static final Logger _log = Logger.getLogger(FortSiegeManager.class.getName());
private int _attackerMaxClans = 500; // Max number of clans
// Fort Siege settings
private Map<Integer, List<FortSiegeSpawn>> _commanderSpawnList;
private Map<Integer, List<CombatFlag>> _flagList;
private boolean _justToTerritory = true; // Changeable in fortsiege.properties
private int _flagMaxCount = 1; // Changeable in fortsiege.properties
private int _siegeClanMinLevel = 4; // Changeable in fortsiege.properties
private int _siegeLength = 60; // Time in minute. Changeable in fortsiege.properties
private int _countDownLength = 10; // Time in minute. Changeable in fortsiege.properties
private int _suspiciousMerchantRespawnDelay = 180; // Time in minute. Changeable in fortsiege.properties
private List<FortSiege> _sieges;
protected FortSiegeManager()
{
load();
}
public final void addSiegeSkills(L2PcInstance character)
{
character.addSkill(CommonSkill.SEAL_OF_RULER.getSkill(), false);
character.addSkill(CommonSkill.BUILD_HEADQUARTERS.getSkill(), false);
}
/**
* @param clan The L2Clan of the player
* @param fortid
* @return true if the clan is registered or owner of a fort
*/
public final boolean checkIsRegistered(L2Clan clan, int fortid)
{
if (clan == null)
{
return false;
}
boolean register = false;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT clan_id FROM fortsiege_clans where clan_id=? and fort_id=?"))
{
ps.setInt(1, clan.getId());
ps.setInt(2, fortid);
try (ResultSet rs = ps.executeQuery())
{
if (rs.next())
{
register = true;
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: checkIsRegistered(): " + e.getMessage(), e);
}
return register;
}
public final void removeSiegeSkills(L2PcInstance character)
{
character.removeSkill(CommonSkill.SEAL_OF_RULER.getSkill());
character.removeSkill(CommonSkill.BUILD_HEADQUARTERS.getSkill());
}
private void load()
{
final Properties siegeSettings = new Properties();
final File file = new File(Config.FORTSIEGE_CONFIGURATION_FILE);
try (InputStream is = new FileInputStream(file))
{
siegeSettings.load(is);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while loading Fort Siege Manager settings!", e);
}
// Siege setting
_justToTerritory = Boolean.parseBoolean(siegeSettings.getProperty("JustToTerritory", "true"));
_attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
_flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
_siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "4"));
_siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "60"));
_countDownLength = Integer.decode(siegeSettings.getProperty("CountDownLength", "10"));
_suspiciousMerchantRespawnDelay = Integer.decode(siegeSettings.getProperty("SuspiciousMerchantRespawnDelay", "180"));
// Siege spawns settings
_commanderSpawnList = new ConcurrentHashMap<>();
_flagList = new ConcurrentHashMap<>();
for (Fort fort : FortManager.getInstance().getForts())
{
final List<FortSiegeSpawn> _commanderSpawns = new CopyOnWriteArrayList<>();
final List<CombatFlag> _flagSpawns = new CopyOnWriteArrayList<>();
for (int i = 1; i < 5; i++)
{
final String _spawnParams = siegeSettings.getProperty(fort.getName().replace(" ", "") + "Commander" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
final StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int heading = Integer.parseInt(st.nextToken());
final int npc_id = Integer.parseInt(st.nextToken());
_commanderSpawns.add(new FortSiegeSpawn(fort.getResidenceId(), x, y, z, heading, npc_id, i));
}
catch (Exception e)
{
_log.warning("Error while loading commander(s) for " + fort.getName() + " fort.");
}
}
_commanderSpawnList.put(fort.getResidenceId(), _commanderSpawns);
for (int i = 1; i < 4; i++)
{
final String _spawnParams = siegeSettings.getProperty(fort.getName().replace(" ", "") + "Flag" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
final StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int flag_id = Integer.parseInt(st.nextToken());
_flagSpawns.add(new CombatFlag(fort.getResidenceId(), x, y, z, 0, flag_id));
}
catch (Exception e)
{
_log.warning("Error while loading flag(s) for " + fort.getName() + " fort.");
}
}
_flagList.put(fort.getResidenceId(), _flagSpawns);
}
}
public final List<FortSiegeSpawn> getCommanderSpawnList(int _fortId)
{
return _commanderSpawnList.get(_fortId);
}
public final List<CombatFlag> getFlagList(int _fortId)
{
return _flagList.get(_fortId);
}
public final int getAttackerMaxClans()
{
return _attackerMaxClans;
}
public final int getFlagMaxCount()
{
return _flagMaxCount;
}
public final boolean canRegisterJustTerritory()
{
return _justToTerritory;
}
public final int getSuspiciousMerchantRespawnDelay()
{
return _suspiciousMerchantRespawnDelay;
}
public final FortSiege getSiege(L2Object activeObject)
{
return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final FortSiege getSiege(int x, int y, int z)
{
for (Fort fort : FortManager.getInstance().getForts())
{
if (fort.getSiege().checkIfInZone(x, y, z))
{
return fort.getSiege();
}
}
return null;
}
public final int getSiegeClanMinLevel()
{
return _siegeClanMinLevel;
}
public final int getSiegeLength()
{
return _siegeLength;
}
public final int getCountDownLength()
{
return _countDownLength;
}
public final List<FortSiege> getSieges()
{
if (_sieges == null)
{
_sieges = new CopyOnWriteArrayList<>();
}
return _sieges;
}
public final void addSiege(FortSiege fortSiege)
{
getSieges().add(fortSiege);
}
public boolean isCombat(int itemId)
{
return (itemId == 9819);
}
public boolean activateCombatFlag(L2PcInstance player, L2ItemInstance item)
{
if (!checkIfCanPickup(player))
{
return false;
}
final Fort fort = FortManager.getInstance().getFort(player);
final List<CombatFlag> fcf = _flagList.get(fort.getResidenceId());
for (CombatFlag cf : fcf)
{
if (cf.getCombatFlagInstance() == item)
{
cf.activate(player, item);
}
}
return true;
}
public boolean checkIfCanPickup(L2PcInstance player)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_FORTRESS_BATTLE_OF_S1_HAS_FINISHED);
sm.addItemName(9819);
// Cannot own 2 combat flag
if (player.isCombatFlagEquipped())
{
player.sendPacket(sm);
return false;
}
// here check if is siege is in progress
// here check if is siege is attacker
final Fort fort = FortManager.getInstance().getFort(player);
if ((fort == null) || (fort.getResidenceId() <= 0))
{
player.sendPacket(sm);
return false;
}
else if (!fort.getSiege().isInProgress())
{
player.sendPacket(sm);
return false;
}
else if (fort.getSiege().getAttackerClan(player.getClan()) == null)
{
player.sendPacket(sm);
return false;
}
return true;
}
public void dropCombatFlag(L2PcInstance player, int fortId)
{
final Fort fort = FortManager.getInstance().getFortById(fortId);
final List<CombatFlag> fcf = _flagList.get(fort.getResidenceId());
for (CombatFlag cf : fcf)
{
if (cf.getPlayerObjectId() == player.getObjectId())
{
cf.dropIt();
if (fort.getSiege().isInProgress())
{
cf.spawnMe();
}
}
}
}
public static FortSiegeManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final FortSiegeManager _instance = new FortSiegeManager();
}
}

View File

@@ -1,142 +1,142 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.variables.AbstractVariables;
/**
* Global Variables Manager.
* @author xban1x
*/
public final class GlobalVariablesManager extends AbstractVariables
{
private static final Logger _log = Logger.getLogger(GlobalVariablesManager.class.getName());
// SQL Queries.
private static final String SELECT_QUERY = "SELECT * FROM global_variables";
private static final String DELETE_QUERY = "DELETE FROM global_variables";
private static final String INSERT_QUERY = "INSERT INTO global_variables (var, value) VALUES (?, ?)";
protected GlobalVariablesManager()
{
restoreMe();
}
@Override
public boolean restoreMe()
{
// Restore previous variables.
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement st = con.createStatement();
ResultSet rset = st.executeQuery(SELECT_QUERY))
{
while (rset.next())
{
set(rset.getString("var"), rset.getString("value"));
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't restore global variables");
return false;
}
finally
{
compareAndSetChanges(true, false);
}
_log.log(Level.INFO, getClass().getSimpleName() + ": Loaded " + getSet().size() + " variables.");
return true;
}
@Override
public boolean storeMe()
{
// No changes, nothing to store.
if (!hasChanges())
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement del = con.createStatement();
PreparedStatement st = con.prepareStatement(INSERT_QUERY))
{
// Clear previous entries.
del.execute(DELETE_QUERY);
// Insert all variables.
for (Entry<String, Object> entry : getSet().entrySet())
{
st.setString(1, entry.getKey());
st.setString(2, String.valueOf(entry.getValue()));
st.addBatch();
}
st.executeBatch();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't save global variables to database.", e);
return false;
}
finally
{
compareAndSetChanges(true, false);
}
_log.log(Level.INFO, getClass().getSimpleName() + ": Stored " + getSet().size() + " variables.");
return true;
}
@Override
public boolean deleteMe()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement del = con.createStatement())
{
del.execute(DELETE_QUERY);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't delete global variables to database.", e);
return false;
}
return true;
}
/**
* Gets the single instance of {@code GlobalVariablesManager}.
* @return single instance of {@code GlobalVariablesManager}
*/
public static GlobalVariablesManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GlobalVariablesManager _instance = new GlobalVariablesManager();
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.variables.AbstractVariables;
/**
* Global Variables Manager.
* @author xban1x
*/
public final class GlobalVariablesManager extends AbstractVariables
{
private static final Logger LOGGER = Logger.getLogger(GlobalVariablesManager.class.getName());
// SQL Queries.
private static final String SELECT_QUERY = "SELECT * FROM global_variables";
private static final String DELETE_QUERY = "DELETE FROM global_variables";
private static final String INSERT_QUERY = "INSERT INTO global_variables (var, value) VALUES (?, ?)";
protected GlobalVariablesManager()
{
restoreMe();
}
@Override
public boolean restoreMe()
{
// Restore previous variables.
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement st = con.createStatement();
ResultSet rset = st.executeQuery(SELECT_QUERY))
{
while (rset.next())
{
set(rset.getString("var"), rset.getString("value"));
}
}
catch (SQLException e)
{
LOGGER.warning(getClass().getSimpleName() + ": Couldn't restore global variables");
return false;
}
finally
{
compareAndSetChanges(true, false);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + getSet().size() + " variables.");
return true;
}
@Override
public boolean storeMe()
{
// No changes, nothing to store.
if (!hasChanges())
{
return false;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement del = con.createStatement();
PreparedStatement st = con.prepareStatement(INSERT_QUERY))
{
// Clear previous entries.
del.execute(DELETE_QUERY);
// Insert all variables.
for (Entry<String, Object> entry : getSet().entrySet())
{
st.setString(1, entry.getKey());
st.setString(2, String.valueOf(entry.getValue()));
st.addBatch();
}
st.executeBatch();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't save global variables to database.", e);
return false;
}
finally
{
compareAndSetChanges(true, false);
}
LOGGER.info(getClass().getSimpleName() + ": Stored " + getSet().size() + " variables.");
return true;
}
@Override
public boolean deleteMe()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement del = con.createStatement())
{
del.execute(DELETE_QUERY);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't delete global variables to database.", e);
return false;
}
return true;
}
/**
* Gets the single instance of {@code GlobalVariablesManager}.
* @return single instance of {@code GlobalVariablesManager}
*/
public static GlobalVariablesManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GlobalVariablesManager _instance = new GlobalVariablesManager();
}
}

View File

@@ -1,240 +1,215 @@
/*
* 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.instancemanager;
import java.util.Calendar;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.instancemanager.tasks.UpdateSoDStateTask;
import com.l2jmobius.gameserver.model.quest.Quest;
public final class GraciaSeedsManager
{
private static final Logger _log = Logger.getLogger(GraciaSeedsManager.class.getName());
public static String ENERGY_SEEDS = "EnergySeeds";
private static final byte SOITYPE = 2;
private static final byte SOATYPE = 3;
// Seed of Destruction
private static final byte SODTYPE = 1;
private int _SoDTiatKilled = 0;
private int _SoDState = 1;
private final Calendar _SoDLastStateChangeDate;
protected GraciaSeedsManager()
{
_SoDLastStateChangeDate = Calendar.getInstance();
loadData();
handleSodStages();
}
public void saveData(byte seedType)
{
switch (seedType)
{
case SODTYPE:
{
// Seed of Destruction
GlobalVariablesManager.getInstance().set("SoDState", _SoDState);
GlobalVariablesManager.getInstance().set("SoDTiatKilled", _SoDTiatKilled);
GlobalVariablesManager.getInstance().set("SoDLSCDate", _SoDLastStateChangeDate.getTimeInMillis());
break;
}
case SOITYPE:
{
// Seed of Infinity
break;
}
case SOATYPE:
{
// Seed of Annihilation
break;
}
default:
{
_log.warning(getClass().getSimpleName() + ": Unknown SeedType in SaveData: " + seedType);
break;
}
}
}
public void loadData()
{
// Seed of Destruction variables
if (GlobalVariablesManager.getInstance().hasVariable("SoDState"))
{
_SoDState = GlobalVariablesManager.getInstance().getInt("SoDState");
_SoDTiatKilled = GlobalVariablesManager.getInstance().getInt("SoDTiatKilled");
_SoDLastStateChangeDate.setTimeInMillis(GlobalVariablesManager.getInstance().getLong("SoDLSCDate"));
}
else
{
// save Initial values
saveData(SODTYPE);
}
}
private void handleSodStages()
{
switch (_SoDState)
{
case 1:
{
// do nothing, players should kill Tiat a few times
break;
}
case 2:
{
// Conquest Complete state, if too much time is passed than change to defense state
final long timePast = System.currentTimeMillis() - _SoDLastStateChangeDate.getTimeInMillis();
if (timePast >= Config.SOD_STAGE_2_LENGTH)
{
// change to Attack state because Defend statet is not implemented
setSoDState(1, true);
}
else
{
ThreadPoolManager.getInstance().scheduleEffect(new UpdateSoDStateTask(), Config.SOD_STAGE_2_LENGTH - timePast);
}
break;
}
case 3:
{
// not implemented
setSoDState(1, true);
break;
}
default:
{
_log.warning(getClass().getSimpleName() + ": Unknown Seed of Destruction state(" + _SoDState + ")! ");
}
}
}
public void updateSodState()
{
final Quest quest = QuestManager.getInstance().getQuest(ENERGY_SEEDS);
if (quest != null)
{
quest.notifyEvent("StopSoDAi", null, null);
}
else
{
_log.warning(getClass().getSimpleName() + ": missing EnergySeeds Quest!");
}
}
public void increaseSoDTiatKilled()
{
if (_SoDState != 1)
{
return;
}
_SoDTiatKilled++;
if (_SoDTiatKilled >= Config.SOD_TIAT_KILL_COUNT)
{
setSoDState(2, false);
}
saveData(SODTYPE);
final Quest esQuest = QuestManager.getInstance().getQuest(ENERGY_SEEDS);
if (esQuest != null)
{
esQuest.notifyEvent("StartSoDAi", null, null);
}
else
{
_log.warning(getClass().getSimpleName() + ": missing EnergySeeds Quest!");
}
}
public int getSoDTiatKilled()
{
return _SoDTiatKilled;
}
public void setSoDState(int value, boolean doSave)
{
_log.info(getClass().getSimpleName() + ": New Seed of Destruction state -> " + value + ".");
_SoDLastStateChangeDate.setTimeInMillis(System.currentTimeMillis());
_SoDState = value;
// reset number of Tiat kills
if (_SoDState == 1)
{
_SoDTiatKilled = 0;
}
handleSodStages();
if (doSave)
{
saveData(SODTYPE);
}
}
public long getSoDTimeForNextStateChange()
{
switch (_SoDState)
{
case 1:
{
return -1;
}
case 2:
{
return (_SoDLastStateChangeDate.getTimeInMillis() + Config.SOD_STAGE_2_LENGTH) - System.currentTimeMillis();
}
case 3:
{
// not implemented yet
return -1;
}
default:
{
// this should not happen!
return -1;
}
}
}
public Calendar getSoDLastStateChangeDate()
{
return _SoDLastStateChangeDate;
}
public int getSoDState()
{
return _SoDState;
}
/**
* Gets the single instance of {@code GraciaSeedsManager}.
* @return single instance of {@code GraciaSeedsManager}
*/
public static GraciaSeedsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GraciaSeedsManager _instance = new GraciaSeedsManager();
}
/*
* 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.instancemanager;
import java.util.Calendar;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.instancemanager.tasks.UpdateSoDStateTask;
import com.l2jmobius.gameserver.model.quest.Quest;
public final class GraciaSeedsManager
{
private static final Logger _log = Logger.getLogger(GraciaSeedsManager.class.getName());
public static String ENERGY_SEEDS = "EnergySeeds";
private static final byte SOITYPE = 2;
private static final byte SOATYPE = 3;
// Seed of Destruction
private static final byte SODTYPE = 1;
private int _SoDTiatKilled = 0;
private int _SoDState = 1;
private final Calendar _SoDLastStateChangeDate;
protected GraciaSeedsManager()
{
_SoDLastStateChangeDate = Calendar.getInstance();
loadData();
handleSodStages();
}
public void saveData(byte seedType)
{
switch (seedType)
{
case SODTYPE:
// Seed of Destruction
GlobalVariablesManager.getInstance().set("SoDState", _SoDState);
GlobalVariablesManager.getInstance().set("SoDTiatKilled", _SoDTiatKilled);
GlobalVariablesManager.getInstance().set("SoDLSCDate", _SoDLastStateChangeDate.getTimeInMillis());
break;
case SOITYPE:
// Seed of Infinity
break;
case SOATYPE:
// Seed of Annihilation
break;
default:
_log.warning(getClass().getSimpleName() + ": Unknown SeedType in SaveData: " + seedType);
break;
}
}
public void loadData()
{
// Seed of Destruction variables
if (GlobalVariablesManager.getInstance().hasVariable("SoDState"))
{
_SoDState = GlobalVariablesManager.getInstance().getInt("SoDState");
_SoDTiatKilled = GlobalVariablesManager.getInstance().getInt("SoDTiatKilled");
_SoDLastStateChangeDate.setTimeInMillis(GlobalVariablesManager.getInstance().getLong("SoDLSCDate"));
}
else
{
// save Initial values
saveData(SODTYPE);
}
}
private void handleSodStages()
{
switch (_SoDState)
{
case 1:
// do nothing, players should kill Tiat a few times
break;
case 2:
// Conquest Complete state, if too much time is passed than change to defense state
final long timePast = System.currentTimeMillis() - _SoDLastStateChangeDate.getTimeInMillis();
if (timePast >= Config.SOD_STAGE_2_LENGTH)
{
// change to Attack state because Defend statet is not implemented
setSoDState(1, true);
}
else
{
ThreadPoolManager.getInstance().scheduleEffect(new UpdateSoDStateTask(), Config.SOD_STAGE_2_LENGTH - timePast);
}
break;
case 3:
// not implemented
setSoDState(1, true);
break;
default:
_log.warning(getClass().getSimpleName() + ": Unknown Seed of Destruction state(" + _SoDState + ")! ");
}
}
public void updateSodState()
{
final Quest quest = QuestManager.getInstance().getQuest(ENERGY_SEEDS);
if (quest == null)
{
_log.warning(getClass().getSimpleName() + ": missing EnergySeeds Quest!");
}
else
{
quest.notifyEvent("StopSoDAi", null, null);
}
}
public void increaseSoDTiatKilled()
{
if (_SoDState == 1)
{
_SoDTiatKilled++;
if (_SoDTiatKilled >= Config.SOD_TIAT_KILL_COUNT)
{
setSoDState(2, false);
}
saveData(SODTYPE);
final Quest esQuest = QuestManager.getInstance().getQuest(ENERGY_SEEDS);
if (esQuest == null)
{
_log.warning(getClass().getSimpleName() + ": missing EnergySeeds Quest!");
}
else
{
esQuest.notifyEvent("StartSoDAi", null, null);
}
}
}
public int getSoDTiatKilled()
{
return _SoDTiatKilled;
}
public void setSoDState(int value, boolean doSave)
{
_log.info(getClass().getSimpleName() + ": New Seed of Destruction state -> " + value + ".");
_SoDLastStateChangeDate.setTimeInMillis(System.currentTimeMillis());
_SoDState = value;
// reset number of Tiat kills
if (_SoDState == 1)
{
_SoDTiatKilled = 0;
}
handleSodStages();
if (doSave)
{
saveData(SODTYPE);
}
}
public long getSoDTimeForNextStateChange()
{
switch (_SoDState)
{
case 1:
return -1;
case 2:
return ((_SoDLastStateChangeDate.getTimeInMillis() + Config.SOD_STAGE_2_LENGTH) - System.currentTimeMillis());
case 3:
// not implemented yet
return -1;
default:
// this should not happen!
return -1;
}
}
public Calendar getSoDLastStateChangeDate()
{
return _SoDLastStateChangeDate;
}
public int getSoDState()
{
return _SoDState;
}
/**
* Gets the single instance of {@code GraciaSeedsManager}.
* @return single instance of {@code GraciaSeedsManager}
*/
public static GraciaSeedsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GraciaSeedsManager _instance = new GraciaSeedsManager();
}
}

View File

@@ -1,384 +1,268 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.instancemanager.tasks.GrandBossManagerStoreTask;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.interfaces.IStorable;
import com.l2jmobius.gameserver.model.zone.type.L2BossZone;
/**
* Grand Boss manager.
* @author DaRkRaGe Revised by Emperorc
*/
public final class GrandBossManager implements IStorable
{
// SQL queries
private static final String DELETE_GRAND_BOSS_LIST = "DELETE FROM grandboss_list";
private static final String INSERT_GRAND_BOSS_LIST = "INSERT INTO grandboss_list (player_id,zone) VALUES (?,?)";
private static final String UPDATE_GRAND_BOSS_DATA = "UPDATE grandboss_data set loc_x = ?, loc_y = ?, loc_z = ?, heading = ?, respawn_time = ?, currentHP = ?, currentMP = ?, status = ? where boss_id = ?";
private static final String UPDATE_GRAND_BOSS_DATA2 = "UPDATE grandboss_data set status = ? where boss_id = ?";
protected static Logger _log = Logger.getLogger(GrandBossManager.class.getName());
protected static final Map<Integer, L2GrandBossInstance> BOSSES = new ConcurrentHashMap<>();
protected static Map<Integer, StatsSet> _storedInfo = new HashMap<>();
private final Map<Integer, Integer> _bossStatus = new ConcurrentHashMap<>();
private final Map<Integer, L2BossZone> _zones = new ConcurrentHashMap<>();
protected GrandBossManager()
{
init();
}
private void init()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * from grandboss_data ORDER BY boss_id"))
{
while (rs.next())
{
// Read all info from DB, and store it for AI to read and decide what to do
// faster than accessing DB in real time
final StatsSet info = new StatsSet();
final int bossId = rs.getInt("boss_id");
info.set("loc_x", rs.getInt("loc_x"));
info.set("loc_y", rs.getInt("loc_y"));
info.set("loc_z", rs.getInt("loc_z"));
info.set("heading", rs.getInt("heading"));
info.set("respawn_time", rs.getLong("respawn_time"));
final double HP = rs.getDouble("currentHP"); // jython doesn't recognize doubles
final int true_HP = (int) HP; // so use java's ability to type cast
info.set("currentHP", true_HP); // to convert double to int
final double MP = rs.getDouble("currentMP");
final int true_MP = (int) MP;
info.set("currentMP", true_MP);
final int status = rs.getInt("status");
_bossStatus.put(bossId, status);
_storedInfo.put(bossId, info);
_log.info(getClass().getSimpleName() + ": " + NpcData.getInstance().getTemplate(bossId).getName() + "(" + bossId + ") status is " + status + ".");
if (status > 0)
{
_log.info(getClass().getSimpleName() + ": Next spawn date of " + NpcData.getInstance().getTemplate(bossId).getName() + " is " + new Date(info.getLong("respawn_time")) + ".");
}
}
_log.info(getClass().getSimpleName() + ": Loaded " + _storedInfo.size() + " Instances");
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not load grandboss_data table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while initializing GrandBossManager: " + e.getMessage(), e);
}
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new GrandBossManagerStoreTask(), 5 * 60 * 1000, 5 * 60 * 1000);
}
/**
* Zone Functions
*/
public void initZones()
{
final Map<Integer, List<Integer>> zones = new HashMap<>();
for (Integer zoneId : _zones.keySet())
{
zones.put(zoneId, new ArrayList<>());
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * from grandboss_list ORDER BY player_id"))
{
while (rs.next())
{
zones.get(rs.getInt("zone")).add(rs.getInt("player_id"));
}
_log.info(getClass().getSimpleName() + ": Initialized " + _zones.size() + " Grand Boss Zones");
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not load grandboss_list table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while initializing GrandBoss zones: " + e.getMessage(), e);
}
for (Entry<Integer, L2BossZone> e : _zones.entrySet())
{
e.getValue().setAllowedPlayers(zones.get(e.getKey()));
}
zones.clear();
}
public void addZone(L2BossZone zone)
{
_zones.put(zone.getId(), zone);
}
public L2BossZone getZone(int zoneId)
{
return _zones.get(zoneId);
}
public L2BossZone getZone(L2Character character)
{
return _zones.values().stream().filter(z -> z.isCharacterInZone(character)).findFirst().orElse(null);
}
public L2BossZone getZone(Location loc)
{
return getZone(loc.getX(), loc.getY(), loc.getZ());
}
public L2BossZone getZone(int x, int y, int z)
{
return _zones.values().stream().filter(zone -> zone.isInsideZone(x, y, z)).findFirst().orElse(null);
}
public boolean checkIfInZone(String zoneType, L2Object obj)
{
final L2BossZone temp = getZone(obj.getX(), obj.getY(), obj.getZ());
return (temp != null) && temp.getName().equalsIgnoreCase(zoneType);
}
public boolean checkIfInZone(L2PcInstance player)
{
return (player != null) && (getZone(player.getX(), player.getY(), player.getZ()) != null);
}
public int getBossStatus(int bossId)
{
return _bossStatus.get(bossId);
}
public void setBossStatus(int bossId, int status)
{
_bossStatus.put(bossId, status);
_log.info(getClass().getSimpleName() + ": Updated " + NpcData.getInstance().getTemplate(bossId).getName() + "(" + bossId + ") status to " + status);
updateDb(bossId, true);
}
/**
* Adds a L2GrandBossInstance to the list of bosses.
* @param boss
*/
public void addBoss(L2GrandBossInstance boss)
{
if (boss != null)
{
BOSSES.put(boss.getId(), boss);
}
}
public L2GrandBossInstance getBoss(int bossId)
{
return BOSSES.get(bossId);
}
public StatsSet getStatsSet(int bossId)
{
return _storedInfo.get(bossId);
}
public void setStatsSet(int bossId, StatsSet info)
{
_storedInfo.put(bossId, info);
updateDb(bossId, false);
}
@Override
public boolean storeMe()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement())
{
s.executeUpdate(DELETE_GRAND_BOSS_LIST);
try (PreparedStatement insert = con.prepareStatement(INSERT_GRAND_BOSS_LIST))
{
for (Entry<Integer, L2BossZone> e : _zones.entrySet())
{
final List<Integer> list = e.getValue().getAllowedPlayers();
if ((list == null) || list.isEmpty())
{
continue;
}
for (Integer player : list)
{
insert.setInt(1, player);
insert.setInt(2, e.getKey());
insert.executeUpdate();
insert.clearParameters();
}
}
}
for (Entry<Integer, StatsSet> e : _storedInfo.entrySet())
{
final L2GrandBossInstance boss = BOSSES.get(e.getKey());
final StatsSet info = e.getValue();
if ((boss == null) || (info == null))
{
try (PreparedStatement update = con.prepareStatement(UPDATE_GRAND_BOSS_DATA2))
{
update.setInt(1, _bossStatus.get(e.getKey()));
update.setInt(2, e.getKey());
update.executeUpdate();
update.clearParameters();
}
}
else
{
try (PreparedStatement update = con.prepareStatement(UPDATE_GRAND_BOSS_DATA))
{
update.setInt(1, boss.getX());
update.setInt(2, boss.getY());
update.setInt(3, boss.getZ());
update.setInt(4, boss.getHeading());
update.setLong(5, info.getLong("respawn_time"));
double hp = boss.getCurrentHp();
double mp = boss.getCurrentMp();
if (boss.isDead())
{
hp = boss.getMaxHp();
mp = boss.getMaxMp();
}
update.setDouble(6, hp);
update.setDouble(7, mp);
update.setInt(8, _bossStatus.get(e.getKey()));
update.setInt(9, e.getKey());
update.executeUpdate();
update.clearParameters();
}
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't store grandbosses to database:" + e.getMessage(), e);
return false;
}
return true;
}
private void updateDb(int bossId, boolean statusOnly)
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
final L2GrandBossInstance boss = BOSSES.get(bossId);
final StatsSet info = _storedInfo.get(bossId);
if (statusOnly || (boss == null) || (info == null))
{
try (PreparedStatement ps = con.prepareStatement(UPDATE_GRAND_BOSS_DATA2))
{
ps.setInt(1, _bossStatus.get(bossId));
ps.setInt(2, bossId);
ps.executeUpdate();
}
}
else
{
try (PreparedStatement ps = con.prepareStatement(UPDATE_GRAND_BOSS_DATA))
{
ps.setInt(1, boss.getX());
ps.setInt(2, boss.getY());
ps.setInt(3, boss.getZ());
ps.setInt(4, boss.getHeading());
ps.setLong(5, info.getLong("respawn_time"));
double hp = boss.getCurrentHp();
double mp = boss.getCurrentMp();
if (boss.isDead())
{
hp = boss.getMaxHp();
mp = boss.getMaxMp();
}
ps.setDouble(6, hp);
ps.setDouble(7, mp);
ps.setInt(8, _bossStatus.get(bossId));
ps.setInt(9, bossId);
ps.executeUpdate();
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't update grandbosses to database:" + e.getMessage(), e);
}
}
/**
* Saves all Grand Boss info and then clears all info from memory, including all schedules.
*/
public void cleanUp()
{
storeMe();
BOSSES.clear();
_storedInfo.clear();
_bossStatus.clear();
_zones.clear();
}
public Map<Integer, L2BossZone> getZones()
{
return _zones;
}
/**
* Gets the single instance of {@code GrandBossManager}.
* @return single instance of {@code GrandBossManager}
*/
public static GrandBossManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GrandBossManager _instance = new GrandBossManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.instancemanager.tasks.GrandBossManagerStoreTask;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jmobius.gameserver.model.interfaces.IStorable;
/**
* Grand Boss manager.
* @author DaRkRaGe Revised by Emperorc
*/
public final class GrandBossManager implements IStorable
{
// SQL queries
private static final String UPDATE_GRAND_BOSS_DATA = "UPDATE grandboss_data set loc_x = ?, loc_y = ?, loc_z = ?, heading = ?, respawn_time = ?, currentHP = ?, currentMP = ?, status = ? where boss_id = ?";
private static final String UPDATE_GRAND_BOSS_DATA2 = "UPDATE grandboss_data set status = ? where boss_id = ?";
protected static Logger _log = Logger.getLogger(GrandBossManager.class.getName());
protected static Map<Integer, L2GrandBossInstance> _bosses = new ConcurrentHashMap<>();
protected static Map<Integer, StatsSet> _storedInfo = new HashMap<>();
private final Map<Integer, Integer> _bossStatus = new HashMap<>();
protected GrandBossManager()
{
init();
}
private void init()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * from grandboss_data ORDER BY boss_id"))
{
while (rs.next())
{
// Read all info from DB, and store it for AI to read and decide what to do
// faster than accessing DB in real time
final StatsSet info = new StatsSet();
final int bossId = rs.getInt("boss_id");
info.set("loc_x", rs.getInt("loc_x"));
info.set("loc_y", rs.getInt("loc_y"));
info.set("loc_z", rs.getInt("loc_z"));
info.set("heading", rs.getInt("heading"));
info.set("respawn_time", rs.getLong("respawn_time"));
info.set("currentHP", rs.getDouble("currentHP"));
info.set("currentMP", rs.getDouble("currentMP"));
final int status = rs.getInt("status");
_bossStatus.put(bossId, status);
_storedInfo.put(bossId, info);
_log.info(getClass().getSimpleName() + ": " + NpcData.getInstance().getTemplate(bossId).getName() + "(" + bossId + ") status is " + status);
if (status > 0)
{
_log.info(getClass().getSimpleName() + ": Next spawn date of " + NpcData.getInstance().getTemplate(bossId).getName() + " is " + new Date(info.getLong("respawn_time")));
}
}
_log.info(getClass().getSimpleName() + ": Loaded " + _storedInfo.size() + " Instances.");
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not load grandboss_data table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing GrandBossManager: " + e.getMessage(), e);
}
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new GrandBossManagerStoreTask(), 5 * 60 * 1000, 5 * 60 * 1000);
}
public int getBossStatus(int bossId)
{
return _bossStatus.get(bossId);
}
public void setBossStatus(int bossId, int status)
{
_bossStatus.put(bossId, status);
_log.info(getClass().getSimpleName() + ": Updated " + NpcData.getInstance().getTemplate(bossId).getName() + "(" + bossId + ") status to " + status);
updateDb(bossId, true);
}
/**
* Adds a L2GrandBossInstance to the list of bosses.
* @param boss
*/
public void addBoss(L2GrandBossInstance boss)
{
if (boss != null)
{
_bosses.put(boss.getId(), boss);
}
}
public L2GrandBossInstance getBoss(int bossId)
{
return _bosses.get(bossId);
}
public StatsSet getStatsSet(int bossId)
{
return _storedInfo.get(bossId);
}
public void setStatsSet(int bossId, StatsSet info)
{
_storedInfo.put(bossId, info);
updateDb(bossId, false);
}
@Override
public boolean storeMe()
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
for (Entry<Integer, StatsSet> e : _storedInfo.entrySet())
{
final L2GrandBossInstance boss = _bosses.get(e.getKey());
final StatsSet info = e.getValue();
if ((boss == null) || (info == null))
{
try (PreparedStatement update = con.prepareStatement(UPDATE_GRAND_BOSS_DATA2))
{
update.setInt(1, _bossStatus.get(e.getKey()));
update.setInt(2, e.getKey());
update.executeUpdate();
update.clearParameters();
}
}
else
{
try (PreparedStatement update = con.prepareStatement(UPDATE_GRAND_BOSS_DATA))
{
update.setInt(1, boss.getX());
update.setInt(2, boss.getY());
update.setInt(3, boss.getZ());
update.setInt(4, boss.getHeading());
update.setLong(5, info.getLong("respawn_time"));
double hp = boss.getCurrentHp();
double mp = boss.getCurrentMp();
if (boss.isDead())
{
hp = boss.getMaxHp();
mp = boss.getMaxMp();
}
update.setDouble(6, hp);
update.setDouble(7, mp);
update.setInt(8, _bossStatus.get(e.getKey()));
update.setInt(9, e.getKey());
update.executeUpdate();
update.clearParameters();
}
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Couldn't store grandbosses to database: " + e.getMessage(), e);
return false;
}
return true;
}
private void updateDb(int bossId, boolean statusOnly)
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
final L2GrandBossInstance boss = _bosses.get(bossId);
final StatsSet info = _storedInfo.get(bossId);
if (statusOnly || (boss == null) || (info == null))
{
try (PreparedStatement ps = con.prepareStatement(UPDATE_GRAND_BOSS_DATA2))
{
ps.setInt(1, _bossStatus.get(bossId));
ps.setInt(2, bossId);
ps.executeUpdate();
}
}
else
{
try (PreparedStatement ps = con.prepareStatement(UPDATE_GRAND_BOSS_DATA))
{
ps.setInt(1, boss.getX());
ps.setInt(2, boss.getY());
ps.setInt(3, boss.getZ());
ps.setInt(4, boss.getHeading());
ps.setLong(5, info.getLong("respawn_time"));
double hp = boss.getCurrentHp();
double mp = boss.getCurrentMp();
if (boss.isDead())
{
hp = boss.getMaxHp();
mp = boss.getMaxMp();
}
ps.setDouble(6, hp);
ps.setDouble(7, mp);
ps.setInt(8, _bossStatus.get(bossId));
ps.setInt(9, bossId);
ps.executeUpdate();
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Couldn't update grandbosses to database:" + e.getMessage(), e);
}
}
/**
* Saves all Grand Boss info and then clears all info from memory, including all schedules.
*/
public void cleanUp()
{
storeMe();
_bosses.clear();
_storedInfo.clear();
_bossStatus.clear();
}
/**
* Gets the single instance of {@code GrandBossManager}.
* @return single instance of {@code GrandBossManager}
*/
public static GrandBossManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GrandBossManager _instance = new GrandBossManager();
}
}

View File

@@ -1,364 +1,383 @@
/*
* 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.instancemanager;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.Team;
import com.l2jmobius.gameserver.instancemanager.tasks.PenaltyRemoveTask;
import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
import com.l2jmobius.gameserver.model.olympiad.OlympiadManager;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameAddPlayer;
import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameChangeTeam;
import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameRemovePlayer;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* This class manage the player add/remove, team change and event arena status,<br>
* as the clearance of the participants list or liberate the arena.
* @author BiggBoss
*/
public final class HandysBlockCheckerManager
{
// All the participants and their team classified by arena
private static final ArenaParticipantsHolder[] _arenaPlayers = new ArenaParticipantsHolder[4];
// Arena votes to start the game
private static final Map<Integer, Integer> _arenaVotes = new HashMap<>();
// Arena Status, True = is being used, otherwise, False
private static final Map<Integer, Boolean> _arenaStatus = new HashMap<>();
// Registration request penalty (10 seconds)
protected static Set<Integer> _registrationPenalty = Collections.synchronizedSet(new HashSet<Integer>());
/**
* Return the number of event-start votes for the specified arena id
* @param arenaId
* @return int (number of votes)
*/
public synchronized int getArenaVotes(int arenaId)
{
return _arenaVotes.get(arenaId);
}
/**
* Add a new vote to start the event for the specified arena id
* @param arena
*/
public synchronized void increaseArenaVotes(int arena)
{
final int newVotes = _arenaVotes.get(arena) + 1;
final ArenaParticipantsHolder holder = _arenaPlayers[arena];
if ((newVotes > (holder.getAllPlayers().size() / 2)) && !holder.getEvent().isStarted())
{
clearArenaVotes(arena);
if ((holder.getBlueTeamSize() == 0) || (holder.getRedTeamSize() == 0))
{
return;
}
if (Config.HBCE_FAIR_PLAY)
{
holder.checkAndShuffle();
}
ThreadPoolManager.getInstance().executeGeneral(holder.getEvent().new StartEvent());
}
else
{
_arenaVotes.put(arena, newVotes);
}
}
/**
* Will clear the votes queue (of event start) for the specified arena id
* @param arena
*/
public synchronized void clearArenaVotes(int arena)
{
_arenaVotes.put(arena, 0);
}
protected HandysBlockCheckerManager()
{
// Initialize arena status
_arenaStatus.put(0, false);
_arenaStatus.put(1, false);
_arenaStatus.put(2, false);
_arenaStatus.put(3, false);
// Initialize arena votes
_arenaVotes.put(0, 0);
_arenaVotes.put(1, 0);
_arenaVotes.put(2, 0);
_arenaVotes.put(3, 0);
}
/**
* Returns the players holder
* @param arena
* @return ArenaParticipantsHolder
*/
public ArenaParticipantsHolder getHolder(int arena)
{
return _arenaPlayers[arena];
}
/**
* Initializes the participants holder
*/
public void startUpParticipantsQueue()
{
for (int i = 0; i < 4; ++i)
{
_arenaPlayers[i] = new ArenaParticipantsHolder(i);
}
}
/**
* Add the player to the specified arena (through the specified arena manager) and send the needed server -> client packets
* @param player
* @param arenaId
* @return
*/
public boolean addPlayerToArena(L2PcInstance player, int arenaId)
{
final ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
synchronized (holder)
{
boolean isRed;
for (int i = 0; i < 4; i++)
{
if (_arenaPlayers[i].getAllPlayers().contains(player))
{
final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_ALREADY_REGISTERED_ON_THE_MATCH_WAITING_LIST);
msg.addCharName(player);
player.sendPacket(msg);
return false;
}
}
if (player.isCursedWeaponEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_REGISTER_WHILE_IN_POSSESSION_OF_A_CURSED_WEAPON);
return false;
}
if (player.isOnEvent() || player.isInOlympiadMode())
{
player.sendMessage("Couldnt register you due other event participation");
return false;
}
if (OlympiadManager.getInstance().isRegistered(player))
{
OlympiadManager.getInstance().unRegisterNoble(player);
player.sendPacket(SystemMessageId.APPLICANTS_FOR_THE_OLYMPIAD_UNDERGROUND_COLISEUM_OR_KRATEI_S_CUBE_MATCHES_CANNOT_REGISTER);
}
// if(UnderGroundColiseum.getInstance().isRegisteredPlayer(player))
// {
// UngerGroundColiseum.getInstance().removeParticipant(player);
// player.sendPacket(SystemMessageId.APPLICANTS_FOR_THE_OLYMPIAD_UNDERGROUND_COLISEUM_OR_KRATEI_S_CUBE_MATCHES_CANNOT_REGISTER));
// }
// if(KrateiCubeManager.getInstance().isRegisteredPlayer(player))
// {
// KrateiCubeManager.getInstance().removeParticipant(player);
// player.sendPacket(SystemMessageId.APPLICANTS_FOR_THE_OLYMPIAD_UNDERGROUND_COLISEUM_OR_KRATEI_S_CUBE_MATCHES_CANNOT_REGISTER));
// }
if (_registrationPenalty.contains(player.getObjectId()))
{
player.sendPacket(SystemMessageId.YOU_MUST_WAIT_10_SECONDS_BEFORE_ATTEMPTING_TO_REGISTER_AGAIN);
return false;
}
if (holder.getBlueTeamSize() < holder.getRedTeamSize())
{
holder.addPlayer(player, 1);
isRed = false;
}
else
{
holder.addPlayer(player, 0);
isRed = true;
}
holder.broadCastPacketToTeam(new ExCubeGameAddPlayer(player, isRed));
return true;
}
}
/**
* Will remove the specified player from the specified team and arena and will send the needed packet to all his team mates / enemy team mates
* @param player
* @param arenaId
* @param team
*/
public void removePlayer(L2PcInstance player, int arenaId, int team)
{
final ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
synchronized (holder)
{
final boolean isRed = team == 0;
holder.removePlayer(player, team);
holder.broadCastPacketToTeam(new ExCubeGameRemovePlayer(player, isRed));
// End event if theres an empty team
final int teamSize = isRed ? holder.getRedTeamSize() : holder.getBlueTeamSize();
if (teamSize == 0)
{
holder.getEvent().endEventAbnormally();
}
_registrationPenalty.add(player.getObjectId());
schedulePenaltyRemoval(player.getObjectId());
}
}
/**
* Will change the player from one team to other (if possible) and will send the needed packets
* @param player
* @param arena
* @param team
*/
public void changePlayerToTeam(L2PcInstance player, int arena, int team)
{
final ArenaParticipantsHolder holder = _arenaPlayers[arena];
synchronized (holder)
{
final boolean isFromRed = holder.getRedPlayers().contains(player);
if ((isFromRed && (holder.getBlueTeamSize() == 6)) || (!isFromRed && (holder.getRedTeamSize() == 6)))
{
player.sendMessage("The team is full");
return;
}
final int futureTeam = isFromRed ? 1 : 0;
holder.addPlayer(player, futureTeam);
holder.removePlayer(player, isFromRed ? 0 : 1);
holder.broadCastPacketToTeam(new ExCubeGameChangeTeam(player, isFromRed));
}
}
/**
* Will erase all participants from the specified holder
* @param arenaId
*/
public synchronized void clearPaticipantQueueByArenaId(int arenaId)
{
_arenaPlayers[arenaId].clearPlayers();
}
/**
* Returns true if arena is holding an event at this momment
* @param arenaId
* @return boolean
*/
public boolean arenaIsBeingUsed(int arenaId)
{
return (arenaId >= 0) && (arenaId <= 3) && _arenaStatus.get(arenaId);
}
/**
* Set the specified arena as being used
* @param arenaId
*/
public void setArenaBeingUsed(int arenaId)
{
_arenaStatus.put(arenaId, true);
}
/**
* Set as free the specified arena for future events
* @param arenaId
*/
public void setArenaFree(int arenaId)
{
_arenaStatus.put(arenaId, false);
}
/**
* Called when played logs out while participating in Block Checker Event
* @param player
*/
public void onDisconnect(L2PcInstance player)
{
final int arena = player.getBlockCheckerArena();
final int team = getHolder(arena).getPlayerTeam(player);
HandysBlockCheckerManager.getInstance().removePlayer(player, arena, team);
if (player.getTeam() == Team.NONE)
{
return;
}
player.stopAllEffects();
// Remove team aura
player.setTeam(Team.NONE);
// Remove the event items
final PcInventory inv = player.getInventory();
if (inv.getItemByItemId(13787) != null)
{
inv.destroyItemByItemId("Handys Block Checker", 13787, inv.getInventoryItemCount(13787, 0), player, player);
}
if (inv.getItemByItemId(13788) != null)
{
inv.destroyItemByItemId("Handys Block Checker", 13788, inv.getInventoryItemCount(13788, 0), player, player);
}
player.setInsideZone(ZoneId.PVP, false);
// Teleport Back
player.teleToLocation(-57478, -60367, -2370);
}
public void removePenalty(int objectId)
{
_registrationPenalty.remove(objectId);
}
private void schedulePenaltyRemoval(int objId)
{
ThreadPoolManager.getInstance().scheduleGeneral(new PenaltyRemoveTask(objId), 10000);
}
/**
* Gets the single instance of {@code HandysBlockCheckerManager}.
* @return single instance of {@code HandysBlockCheckerManager}
*/
public static HandysBlockCheckerManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final HandysBlockCheckerManager _instance = new HandysBlockCheckerManager();
}
}
/*
* 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.instancemanager;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.Team;
import com.l2jmobius.gameserver.instancemanager.tasks.PenaltyRemoveTask;
import com.l2jmobius.gameserver.model.ArenaParticipantsHolder;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.itemcontainer.PcInventory;
import com.l2jmobius.gameserver.model.olympiad.OlympiadManager;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameAddPlayer;
import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameChangeTeam;
import com.l2jmobius.gameserver.network.serverpackets.ExCubeGameRemovePlayer;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* This class manage the player add/remove, team change and event arena status,<br>
* as the clearance of the participants list or liberate the arena.
* @author BiggBoss
*/
public final class HandysBlockCheckerManager
{
// All the participants and their team classified by arena
private static final ArenaParticipantsHolder[] _arenaPlayers = new ArenaParticipantsHolder[4];
// Arena votes to start the game
private static final Map<Integer, Integer> _arenaVotes = new HashMap<>();
// Arena Status, True = is being used, otherwise, False
private static final Map<Integer, Boolean> _arenaStatus = new HashMap<>();
// Registration request penalty (10 seconds)
protected static Set<Integer> _registrationPenalty = Collections.synchronizedSet(new HashSet<>());
/**
* Return the number of event-start votes for the specified arena id
* @param arenaId
* @return int (number of votes)
*/
public synchronized int getArenaVotes(int arenaId)
{
return _arenaVotes.get(arenaId);
}
/**
* Add a new vote to start the event for the specified arena id
* @param arena
*/
public synchronized void increaseArenaVotes(int arena)
{
final int newVotes = _arenaVotes.get(arena) + 1;
final ArenaParticipantsHolder holder = _arenaPlayers[arena];
if ((newVotes > (holder.getAllPlayers().size() / 2)) && !holder.getEvent().isStarted())
{
clearArenaVotes(arena);
if ((holder.getBlueTeamSize() == 0) || (holder.getRedTeamSize() == 0))
{
return;
}
if (Config.HBCE_FAIR_PLAY)
{
holder.checkAndShuffle();
}
ThreadPoolManager.getInstance().executeGeneral(holder.getEvent().new StartEvent());
}
else
{
_arenaVotes.put(arena, newVotes);
}
}
/**
* Will clear the votes queue (of event start) for the specified arena id
* @param arena
*/
public synchronized void clearArenaVotes(int arena)
{
_arenaVotes.put(arena, 0);
}
protected HandysBlockCheckerManager()
{
// Initialize arena status
_arenaStatus.put(0, false);
_arenaStatus.put(1, false);
_arenaStatus.put(2, false);
_arenaStatus.put(3, false);
// Initialize arena votes
_arenaVotes.put(0, 0);
_arenaVotes.put(1, 0);
_arenaVotes.put(2, 0);
_arenaVotes.put(3, 0);
}
/**
* Returns the players holder
* @param arena
* @return ArenaParticipantsHolder
*/
public ArenaParticipantsHolder getHolder(int arena)
{
return _arenaPlayers[arena];
}
/**
* Initializes the participants holder
*/
public void startUpParticipantsQueue()
{
for (int i = 0; i < 4; ++i)
{
_arenaPlayers[i] = new ArenaParticipantsHolder(i);
}
}
/**
* Add the player to the specified arena (through the specified arena manager) and send the needed server -> client packets
* @param player
* @param arenaId
* @return
*/
public boolean addPlayerToArena(L2PcInstance player, int arenaId)
{
final ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
synchronized (holder)
{
boolean isRed;
for (int i = 0; i < 4; i++)
{
if (_arenaPlayers[i].getAllPlayers().contains(player))
{
final SystemMessage msg = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_ALREADY_REGISTERED_ON_THE_MATCH_WAITING_LIST);
msg.addCharName(player);
player.sendPacket(msg);
return false;
}
}
if (player.isCursedWeaponEquipped())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_REGISTER_WHILE_IN_POSSESSION_OF_A_CURSED_WEAPON);
return false;
}
if (player.isOnEvent() || player.isInOlympiadMode())
{
player.sendMessage("Couldnt register you due other event participation");
return false;
}
if (OlympiadManager.getInstance().isRegistered(player))
{
OlympiadManager.getInstance().unRegisterNoble(player);
player.sendPacket(SystemMessageId.APPLICANTS_FOR_THE_OLYMPIAD_UNDERGROUND_COLISEUM_OR_KRATEI_S_CUBE_MATCHES_CANNOT_REGISTER);
}
// if(UnderGroundColiseum.getInstance().isRegisteredPlayer(player))
// {
// UngerGroundColiseum.getInstance().removeParticipant(player);
// player.sendPacket(SystemMessageId.APPLICANTS_FOR_THE_OLYMPIAD_UNDERGROUND_COLISEUM_OR_KRATEI_S_CUBE_MATCHES_CANNOT_REGISTER));
// }
// if(KrateiCubeManager.getInstance().isRegisteredPlayer(player))
// {
// KrateiCubeManager.getInstance().removeParticipant(player);
// player.sendPacket(SystemMessageId.APPLICANTS_FOR_THE_OLYMPIAD_UNDERGROUND_COLISEUM_OR_KRATEI_S_CUBE_MATCHES_CANNOT_REGISTER));
// }
if (_registrationPenalty.contains(player.getObjectId()))
{
player.sendPacket(SystemMessageId.YOU_MUST_WAIT_10_SECONDS_BEFORE_ATTEMPTING_TO_REGISTER_AGAIN);
return false;
}
if (holder.getBlueTeamSize() < holder.getRedTeamSize())
{
holder.addPlayer(player, 1);
isRed = false;
}
else
{
holder.addPlayer(player, 0);
isRed = true;
}
holder.broadCastPacketToTeam(new ExCubeGameAddPlayer(player, isRed));
return true;
}
}
/**
* Will remove the specified player from the specified team and arena and will send the needed packet to all his team mates / enemy team mates
* @param player
* @param arenaId
* @param team
*/
public void removePlayer(L2PcInstance player, int arenaId, int team)
{
final ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
synchronized (holder)
{
final boolean isRed = team == 0;
holder.removePlayer(player, team);
holder.broadCastPacketToTeam(new ExCubeGameRemovePlayer(player, isRed));
// End event if theres an empty team
final int teamSize = isRed ? holder.getRedTeamSize() : holder.getBlueTeamSize();
if (teamSize == 0)
{
holder.getEvent().endEventAbnormally();
}
_registrationPenalty.add(player.getObjectId());
schedulePenaltyRemoval(player.getObjectId());
}
}
/**
* Will change the player from one team to other (if possible) and will send the needed packets
* @param player
* @param arena
* @param team
*/
public void changePlayerToTeam(L2PcInstance player, int arena, int team)
{
final ArenaParticipantsHolder holder = _arenaPlayers[arena];
synchronized (holder)
{
final boolean isFromRed = holder.getRedPlayers().contains(player);
if (isFromRed && (holder.getBlueTeamSize() == 6))
{
player.sendMessage("The team is full");
return;
}
else if (!isFromRed && (holder.getRedTeamSize() == 6))
{
player.sendMessage("The team is full");
return;
}
final int futureTeam = isFromRed ? 1 : 0;
holder.addPlayer(player, futureTeam);
if (isFromRed)
{
holder.removePlayer(player, 0);
}
else
{
holder.removePlayer(player, 1);
}
holder.broadCastPacketToTeam(new ExCubeGameChangeTeam(player, isFromRed));
}
}
/**
* Will erase all participants from the specified holder
* @param arenaId
*/
public synchronized void clearPaticipantQueueByArenaId(int arenaId)
{
_arenaPlayers[arenaId].clearPlayers();
}
/**
* Returns true if arena is holding an event at this momment
* @param arenaId
* @return boolean
*/
public boolean arenaIsBeingUsed(int arenaId)
{
if ((arenaId < 0) || (arenaId > 3))
{
return false;
}
return _arenaStatus.get(arenaId);
}
/**
* Set the specified arena as being used
* @param arenaId
*/
public void setArenaBeingUsed(int arenaId)
{
_arenaStatus.put(arenaId, true);
}
/**
* Set as free the specified arena for future events
* @param arenaId
*/
public void setArenaFree(int arenaId)
{
_arenaStatus.put(arenaId, false);
}
/**
* Called when played logs out while participating in Block Checker Event
* @param player
*/
public void onDisconnect(L2PcInstance player)
{
final int arena = player.getBlockCheckerArena();
final int team = getHolder(arena).getPlayerTeam(player);
HandysBlockCheckerManager.getInstance().removePlayer(player, arena, team);
if (player.getTeam() != Team.NONE)
{
player.stopAllEffects();
// Remove team aura
player.setTeam(Team.NONE);
// Remove the event items
final PcInventory inv = player.getInventory();
if (inv.getItemByItemId(13787) != null)
{
final long count = inv.getInventoryItemCount(13787, 0);
inv.destroyItemByItemId("Handys Block Checker", 13787, count, player, player);
}
if (inv.getItemByItemId(13788) != null)
{
final long count = inv.getInventoryItemCount(13788, 0);
inv.destroyItemByItemId("Handys Block Checker", 13788, count, player, player);
}
player.setInsideZone(ZoneId.PVP, false);
// Teleport Back
player.teleToLocation(-57478, -60367, -2370);
}
}
public void removePenalty(int objectId)
{
_registrationPenalty.remove(objectId);
}
private void schedulePenaltyRemoval(int objId)
{
ThreadPoolManager.getInstance().scheduleGeneral(new PenaltyRemoveTask(objId), 10000);
}
/**
* Gets the single instance of {@code HandysBlockCheckerManager}.
* @return single instance of {@code HandysBlockCheckerManager}
*/
public static HandysBlockCheckerManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final HandysBlockCheckerManager _instance = new HandysBlockCheckerManager();
}
}

View File

@@ -1,171 +1,170 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.instancemanager;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.itemauction.ItemAuctionInstance;
/**
* @author Forsaiken
*/
public final class ItemAuctionManager
{
private static final Logger _log = Logger.getLogger(ItemAuctionManager.class.getName());
private final Map<Integer, ItemAuctionInstance> _managerInstances = new HashMap<>();
private final AtomicInteger _auctionIds;
protected ItemAuctionManager()
{
_auctionIds = new AtomicInteger(1);
if (!Config.ALT_ITEM_AUCTION_ENABLED)
{
_log.log(Level.INFO, getClass().getSimpleName() + ": Disabled by config.");
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT auctionId FROM item_auction ORDER BY auctionId DESC LIMIT 0, 1"))
{
if (rs.next())
{
_auctionIds.set(rs.getInt(1) + 1);
}
}
catch (SQLException e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading auctions.", e);
}
final File file = new File(Config.DATAPACK_ROOT + "/ItemAuctions.xml");
if (!file.exists())
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Missing ItemAuctions.xml!");
return;
}
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
try
{
final Document doc = factory.newDocumentBuilder().parse(file);
for (Node na = doc.getFirstChild(); na != null; na = na.getNextSibling())
{
if ("list".equalsIgnoreCase(na.getNodeName()))
{
for (Node nb = na.getFirstChild(); nb != null; nb = nb.getNextSibling())
{
if ("instance".equalsIgnoreCase(nb.getNodeName()))
{
final NamedNodeMap nab = nb.getAttributes();
final int instanceId = Integer.parseInt(nab.getNamedItem("id").getNodeValue());
if (_managerInstances.containsKey(instanceId))
{
throw new Exception("Dublicated instanceId " + instanceId);
}
_managerInstances.put(instanceId, new ItemAuctionInstance(instanceId, _auctionIds, nb));
}
}
}
}
_log.log(Level.INFO, getClass().getSimpleName() + ": Loaded " + _managerInstances.size() + " instance(s).");
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading auctions from xml.", e);
}
}
public final void shutdown()
{
for (ItemAuctionInstance instance : _managerInstances.values())
{
instance.shutdown();
}
}
public final ItemAuctionInstance getManagerInstance(int instanceId)
{
return _managerInstances.get(instanceId);
}
public final int getNextAuctionId()
{
return _auctionIds.getAndIncrement();
}
public static void deleteAuction(int auctionId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM item_auction WHERE auctionId=?"))
{
ps.setInt(1, auctionId);
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM item_auction_bid WHERE auctionId=?"))
{
ps.setInt(1, auctionId);
ps.execute();
}
}
catch (SQLException e)
{
_log.log(Level.SEVERE, "L2ItemAuctionManagerInstance: Failed deleting auction: " + auctionId, e);
}
}
/**
* Gets the single instance of {@code ItemAuctionManager}.
* @return single instance of {@code ItemAuctionManager}
*/
public static ItemAuctionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ItemAuctionManager _instance = new ItemAuctionManager();
}
/*
* 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.instancemanager;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.itemauction.ItemAuctionInstance;
/**
* @author Forsaiken
*/
public final class ItemAuctionManager implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ItemAuctionManager.class.getName());
private final Map<Integer, ItemAuctionInstance> _managerInstances = new HashMap<>();
private final AtomicInteger _auctionIds = new AtomicInteger(1);
protected ItemAuctionManager()
{
if (!Config.ALT_ITEM_AUCTION_ENABLED)
{
LOGGER.info("Disabled by config.");
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rset = statement.executeQuery("SELECT auctionId FROM item_auction ORDER BY auctionId DESC LIMIT 0, 1"))
{
if (rset.next())
{
_auctionIds.set(rset.getInt(1) + 1);
}
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "Failed loading auctions.", e);
}
load();
}
@Override
public void load()
{
_managerInstances.clear();
parseDatapackFile("data/ItemAuctions.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _managerInstances.size() + " instance(s).");
}
@Override
public void parseDocument(Document doc, File f)
{
try
{
for (Node na = doc.getFirstChild(); na != null; na = na.getNextSibling())
{
if ("list".equalsIgnoreCase(na.getNodeName()))
{
for (Node nb = na.getFirstChild(); nb != null; nb = nb.getNextSibling())
{
if ("instance".equalsIgnoreCase(nb.getNodeName()))
{
final NamedNodeMap nab = nb.getAttributes();
final int instanceId = Integer.parseInt(nab.getNamedItem("id").getNodeValue());
if (_managerInstances.containsKey(instanceId))
{
throw new Exception("Dublicated instanceId " + instanceId);
}
final ItemAuctionInstance instance = new ItemAuctionInstance(instanceId, _auctionIds, nb);
_managerInstances.put(instanceId, instance);
}
}
}
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading auctions from xml.", e);
}
}
public final void shutdown()
{
for (ItemAuctionInstance instance : _managerInstances.values())
{
instance.shutdown();
}
}
public final ItemAuctionInstance getManagerInstance(int instanceId)
{
return _managerInstances.get(instanceId);
}
public final int getNextAuctionId()
{
return _auctionIds.getAndIncrement();
}
public static void deleteAuction(int auctionId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement statement = con.prepareStatement("DELETE FROM item_auction WHERE auctionId=?"))
{
statement.setInt(1, auctionId);
statement.execute();
}
try (PreparedStatement statement = con.prepareStatement("DELETE FROM item_auction_bid WHERE auctionId=?"))
{
statement.setInt(1, auctionId);
statement.execute();
}
}
catch (SQLException e)
{
LOGGER.log(Level.SEVERE, "L2ItemAuctionManagerInstance: Failed deleting auction: " + auctionId, e);
}
}
/**
* Gets the single instance of {@code ItemAuctionManager}.
* @return single instance of {@code ItemAuctionManager}
*/
public static ItemAuctionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ItemAuctionManager _instance = new ItemAuctionManager();
}
}

View File

@@ -1,251 +1,261 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ItemsAutoDestroy;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* This class manage all items on ground.
* @author Enforcer
*/
public final class ItemsOnGroundManager implements Runnable
{
private static final Logger _log = Logger.getLogger(ItemsOnGroundManager.class.getName());
private final List<L2ItemInstance> _items = new CopyOnWriteArrayList<>();
protected ItemsOnGroundManager()
{
if (Config.SAVE_DROPPED_ITEM_INTERVAL > 0)
{
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this, Config.SAVE_DROPPED_ITEM_INTERVAL, Config.SAVE_DROPPED_ITEM_INTERVAL);
}
load();
}
private void load()
{
// If SaveDroppedItem is false, may want to delete all items previously stored to avoid add old items on reactivate
if (!Config.SAVE_DROPPED_ITEM && Config.CLEAR_DROPPED_ITEM_TABLE)
{
emptyTable();
}
if (!Config.SAVE_DROPPED_ITEM)
{
return;
}
// if DestroyPlayerDroppedItem was previously false, items currently protected will be added to ItemsAutoDestroy
if (Config.DESTROY_DROPPED_PLAYER_ITEM)
{
String str = null;
if (!Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
{
// Recycle misc. items only
str = "UPDATE itemsonground SET drop_time = ? WHERE drop_time = -1 AND equipable = 0";
}
else if (Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
{
// Recycle all items including equip-able
str = "UPDATE itemsonground SET drop_time = ? WHERE drop_time = -1";
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(str))
{
ps.setLong(1, System.currentTimeMillis());
ps.execute();
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while updating table ItemsOnGround " + e.getMessage(), e);
}
}
// Add items to world
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable FROM itemsonground"))
{
int count = 0;
try (ResultSet rs = ps.executeQuery())
{
L2ItemInstance item;
while (rs.next())
{
item = new L2ItemInstance(rs.getInt(1), rs.getInt(2));
L2World.getInstance().storeObject(item);
// this check and..
if (item.isStackable() && (rs.getInt(3) > 1))
{
item.setCount(rs.getInt(3));
}
// this, are really necessary?
if (rs.getInt(4) > 0)
{
item.setEnchantLevel(rs.getInt(4));
}
item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7));
item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation()));
item.getWorldRegion().addVisibleObject(item);
final long dropTime = rs.getLong(8);
item.setDropTime(dropTime);
item.setProtected(dropTime == -1);
item.setIsVisible(true);
L2World.getInstance().addVisibleObject(item, item.getWorldRegion());
_items.add(item);
count++;
// add to ItemsAutoDestroy only items not protected
if (!Config.LIST_PROTECTED_ITEMS.contains(item.getId()) && (dropTime > -1) && (((Config.AUTODESTROY_ITEM_AFTER > 0) && !item.getItem().hasExImmediateEffect()) || ((Config.HERB_AUTO_DESTROY_TIME > 0) && item.getItem().hasExImmediateEffect())))
{
ItemsAutoDestroy.getInstance().addItem(item);
}
}
}
_log.info(getClass().getSimpleName() + ": Loaded " + count + " items.");
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while loading ItemsOnGround " + e.getMessage(), e);
}
if (Config.EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD)
{
emptyTable();
}
}
public void save(L2ItemInstance item)
{
if (!Config.SAVE_DROPPED_ITEM)
{
return;
}
_items.add(item);
}
public void removeObject(L2ItemInstance item)
{
if (Config.SAVE_DROPPED_ITEM)
{
_items.remove(item);
}
}
public void saveInDb()
{
run();
}
public void cleanUp()
{
_items.clear();
}
public void emptyTable()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement())
{
s.executeUpdate("DELETE FROM itemsonground");
}
catch (Exception e1)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while cleaning table ItemsOnGround " + e1.getMessage(), e1);
}
}
@Override
public synchronized void run()
{
if (!Config.SAVE_DROPPED_ITEM)
{
return;
}
emptyTable();
if (_items.isEmpty())
{
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO itemsonground(object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable) VALUES(?,?,?,?,?,?,?,?,?)"))
{
for (L2ItemInstance item : _items)
{
if ((item == null) || CursedWeaponsManager.getInstance().isCursed(item.getId()))
{
continue; // Cursed Items not saved to ground, prevent double save
}
try
{
ps.setInt(1, item.getObjectId());
ps.setInt(2, item.getId());
ps.setLong(3, item.getCount());
ps.setInt(4, item.getEnchantLevel());
ps.setInt(5, item.getX());
ps.setInt(6, item.getY());
ps.setInt(7, item.getZ());
ps.setLong(8, item.isProtected() ? -1 : item.getDropTime()); // item is protected or AutoDestroyed
ps.setLong(9, item.isEquipable() ? 1 : 0); // set equip-able
ps.execute();
ps.clearParameters();
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while inserting into table ItemsOnGround: " + e.getMessage(), e);
}
}
}
catch (SQLException e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": SQL error while storing items on ground: " + e.getMessage(), e);
}
}
/**
* Gets the single instance of {@code ItemsOnGroundManager}.
* @return single instance of {@code ItemsOnGroundManager}
*/
public static ItemsOnGroundManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ItemsOnGroundManager _instance = new ItemsOnGroundManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ItemsAutoDestroy;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* This class manage all items on ground.
* @author Enforcer
*/
public final class ItemsOnGroundManager implements Runnable
{
private static final Logger _log = Logger.getLogger(ItemsOnGroundManager.class.getName());
private final Set<L2ItemInstance> _items = ConcurrentHashMap.newKeySet();
protected ItemsOnGroundManager()
{
if (Config.SAVE_DROPPED_ITEM_INTERVAL > 0)
{
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this, Config.SAVE_DROPPED_ITEM_INTERVAL, Config.SAVE_DROPPED_ITEM_INTERVAL);
}
load();
}
private void load()
{
// If SaveDroppedItem is false, may want to delete all items previously stored to avoid add old items on reactivate
if (!Config.SAVE_DROPPED_ITEM && Config.CLEAR_DROPPED_ITEM_TABLE)
{
emptyTable();
}
if (!Config.SAVE_DROPPED_ITEM)
{
return;
}
// if DestroyPlayerDroppedItem was previously false, items currently protected will be added to ItemsAutoDestroy
if (Config.DESTROY_DROPPED_PLAYER_ITEM)
{
String str = null;
if (!Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
{
// Recycle misc. items only
str = "UPDATE itemsonground SET drop_time = ? WHERE drop_time = -1 AND equipable = 0";
}
else if (Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
{
// Recycle all items including equip-able
str = "UPDATE itemsonground SET drop_time = ? WHERE drop_time = -1";
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(str))
{
ps.setLong(1, System.currentTimeMillis());
ps.execute();
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while updating table ItemsOnGround " + e.getMessage(), e);
}
}
// Add items to world
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable FROM itemsonground"))
{
int count = 0;
try (ResultSet rs = ps.executeQuery())
{
L2ItemInstance item;
while (rs.next())
{
item = new L2ItemInstance(rs.getInt(1), rs.getInt(2));
L2World.getInstance().storeObject(item);
// this check and..
if (item.isStackable() && (rs.getInt(3) > 1))
{
item.setCount(rs.getInt(3));
}
// this, are really necessary?
if (rs.getInt(4) > 0)
{
item.setEnchantLevel(rs.getInt(4));
}
item.setXYZ(rs.getInt(5), rs.getInt(6), rs.getInt(7));
item.setWorldRegion(L2World.getInstance().getRegion(item.getLocation()));
item.getWorldRegion().addVisibleObject(item);
final long dropTime = rs.getLong(8);
item.setDropTime(dropTime);
item.setProtected(dropTime == -1);
item.setSpawned(true);
L2World.getInstance().addVisibleObject(item, item.getWorldRegion());
_items.add(item);
count++;
// add to ItemsAutoDestroy only items not protected
if (!Config.LIST_PROTECTED_ITEMS.contains(item.getId()))
{
if (dropTime > -1)
{
if (((Config.AUTODESTROY_ITEM_AFTER > 0) && !item.getItem().hasExImmediateEffect()) || ((Config.HERB_AUTO_DESTROY_TIME > 0) && item.getItem().hasExImmediateEffect()))
{
ItemsAutoDestroy.getInstance().addItem(item);
}
}
}
}
}
_log.info(getClass().getSimpleName() + ": Loaded " + count + " items.");
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while loading ItemsOnGround " + e.getMessage(), e);
}
if (Config.EMPTY_DROPPED_ITEM_TABLE_AFTER_LOAD)
{
emptyTable();
}
}
public void save(L2ItemInstance item)
{
if (Config.SAVE_DROPPED_ITEM)
{
_items.add(item);
}
}
public void removeObject(L2ItemInstance item)
{
if (Config.SAVE_DROPPED_ITEM)
{
_items.remove(item);
}
}
public void saveInDb()
{
run();
}
public void cleanUp()
{
_items.clear();
}
public void emptyTable()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement())
{
s.executeUpdate("DELETE FROM itemsonground");
}
catch (Exception e1)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while cleaning table ItemsOnGround " + e1.getMessage(), e1);
}
}
@Override
public synchronized void run()
{
if (!Config.SAVE_DROPPED_ITEM)
{
return;
}
emptyTable();
if (_items.isEmpty())
{
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO itemsonground(object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable) VALUES(?,?,?,?,?,?,?,?,?)"))
{
for (L2ItemInstance item : _items)
{
if (item == null)
{
continue;
}
if (CursedWeaponsManager.getInstance().isCursed(item.getId()))
{
continue; // Cursed Items not saved to ground, prevent double save
}
try
{
statement.setInt(1, item.getObjectId());
statement.setInt(2, item.getId());
statement.setLong(3, item.getCount());
statement.setInt(4, item.getEnchantLevel());
statement.setInt(5, item.getX());
statement.setInt(6, item.getY());
statement.setInt(7, item.getZ());
statement.setLong(8, (item.isProtected() ? -1 : item.getDropTime())); // item is protected or AutoDestroyed
statement.setLong(9, (item.isEquipable() ? 1 : 0)); // set equip-able
statement.execute();
statement.clearParameters();
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error while inserting into table ItemsOnGround: " + e.getMessage(), e);
}
}
}
catch (SQLException e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": SQL error while storing items on ground: " + e.getMessage(), e);
}
}
/**
* Gets the single instance of {@code ItemsOnGroundManager}.
* @return single instance of {@code ItemsOnGroundManager}
*/
public static ItemsOnGroundManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ItemsOnGroundManager _instance = new ItemsOnGroundManager();
}
}

View File

@@ -1,238 +0,0 @@
/*
* 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.instancemanager;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.model.zone.type.L2JumpZone;
import com.l2jmobius.gameserver.network.serverpackets.ExFlyMove;
import com.l2jmobius.gameserver.network.serverpackets.FlyToLocation;
import com.l2jmobius.gameserver.network.serverpackets.FlyToLocation.FlyType;
/**
* JumpManager
* @author ALF
*/
public class JumpManager
{
private static final Logger _log = Logger.getLogger(JumpManager.class.getName());
private final Map<Integer, Track> _tracks = new HashMap<>();
public class Track extends HashMap<Integer, JumpWay>
{
public int x = 0;
public int y = 0;
public int z = 0;
}
public class JumpWay extends ArrayList<JumpNode>
{
}
public class JumpNode
{
private final int _x;
private final int _y;
private final int _z;
private final int _next;
public JumpNode(int x, int y, int z, int next)
{
_x = x;
_y = y;
_z = z;
_next = next;
}
public int getX()
{
return _x;
}
public int getY()
{
return _y;
}
public int getZ()
{
return _z;
}
public int getNext()
{
return _next;
}
}
protected JumpManager()
{
load();
}
public void load()
{
_tracks.clear();
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
final File file = new File(Config.DATAPACK_ROOT, "JumpTrack.xml");
Document doc = null;
if (file.exists())
{
try
{
doc = factory.newDocumentBuilder().parse(file);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not parse JumpTrack.xml file: " + e.getMessage(), e);
return;
}
for (Node t = doc.getFirstChild().getFirstChild(); t != null; t = t.getNextSibling())
{
if (t.getNodeName().equals("track"))
{
final Track track = new Track();
final int trackId = Integer.parseInt(t.getAttributes().getNamedItem("trackId").getNodeValue());
try
{
track.x = Integer.parseInt(t.getAttributes().getNamedItem("ToX").getNodeValue());
track.y = Integer.parseInt(t.getAttributes().getNamedItem("ToY").getNodeValue());
track.z = Integer.parseInt(t.getAttributes().getNamedItem("ToZ").getNodeValue());
}
catch (Exception e)
{
_log.info("track id:" + trackId + " missing tox toy toz");
}
for (Node w = t.getFirstChild(); w != null; w = w.getNextSibling())
{
if (w.getNodeName().equals("way"))
{
final JumpWay jw = new JumpWay();
final int wayId = Integer.parseInt(w.getAttributes().getNamedItem("id").getNodeValue());
for (Node j = w.getFirstChild(); j != null; j = j.getNextSibling())
{
if (j.getNodeName().equals("jumpLoc"))
{
final NamedNodeMap attrs = j.getAttributes();
jw.add(new JumpNode(Integer.parseInt(attrs.getNamedItem("x").getNodeValue()), Integer.parseInt(attrs.getNamedItem("y").getNodeValue()), Integer.parseInt(attrs.getNamedItem("z").getNodeValue()), Integer.parseInt(attrs.getNamedItem("next").getNodeValue())));
}
}
track.put(wayId, jw);
}
}
_tracks.put(trackId, track);
}
}
}
_log.info(getClass().getSimpleName() + ": Loaded " + _tracks.size() + " Jump Routes.");
}
public int getTrackId(L2PcInstance player)
{
for (L2ZoneType zone : L2World.getInstance().getRegion(player.getX(), player.getY()).getZones())
{
if (zone.isCharacterInZone(player) && (zone instanceof L2JumpZone))
{
return ((L2JumpZone) zone).getTrackId();
}
}
return -1;
}
public Track getTrack(int trackId)
{
return _tracks.get(trackId);
}
public JumpWay getJumpWay(int trackId, int wayId)
{
final Track t = _tracks.get(trackId);
return t != null ? t.get(wayId) : null;
}
public void StartJump(L2PcInstance player)
{
if (!player.isInsideZone(ZoneId.JUMP))
{
return;
}
player.setJumpTrackId(getTrackId(player));
if (player.getJumpTrackId() == -1)
{
return;
}
final JumpWay jw = getJumpWay(player.getJumpTrackId(), 0);
if (jw == null)
{
return;
}
final Track t = getTrack(player.getJumpTrackId());
if ((t.x != 0) || (t.y != 0) || (t.z != 0))
{
player.broadcastPacket(new FlyToLocation(player, t.x, t.y, t.z, FlyType.DUMMY));
player.setXYZ(t.x, t.y, t.z);
}
player.sendPacket(new ExFlyMove(player.getObjectId(), player.getJumpTrackId(), jw));
}
public void NextJump(L2PcInstance player, int nextId)
{
if (player.getJumpTrackId() == -1)
{
return;
}
final JumpWay jw = getJumpWay(player.getJumpTrackId(), nextId);
if (jw == null)
{
player.enableAllSkills(); // unlock player skills
return;
}
player.sendPacket(new ExFlyMove(player.getObjectId(), player.getJumpTrackId(), jw));
final JumpNode n = jw.get(0);
player.setXYZ(n.getX(), n.getY(), n.getZ());
}
public static JumpManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final JumpManager _instance = new JumpManager();
}
}

View File

@@ -1,280 +1,301 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.tasks.MessageDeletionTask;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Message;
import com.l2jmobius.gameserver.network.serverpackets.ExNoticePostArrived;
import com.l2jmobius.gameserver.network.serverpackets.ExUnReadMailCount;
/**
* @author Migi, DS
*/
public final class MailManager
{
private static final Logger _log = Logger.getLogger(MailManager.class.getName());
private final Map<Integer, Message> _messages = new ConcurrentHashMap<>();
protected MailManager()
{
load();
}
private void load()
{
int count = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement ps = con.createStatement();
ResultSet rs = ps.executeQuery("SELECT * FROM messages ORDER BY expiration"))
{
while (rs.next())
{
final Message msg = new Message(rs);
final int msgId = msg.getId();
_messages.put(msgId, msg);
count++;
final long expiration = msg.getExpiration();
if (expiration < System.currentTimeMillis())
{
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msgId), 10000);
}
else
{
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msgId), expiration - System.currentTimeMillis());
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error loading from database:" + e.getMessage(), e);
}
_log.info(getClass().getSimpleName() + ": Successfully loaded " + count + " messages.");
}
public final Message getMessage(int msgId)
{
return _messages.get(msgId);
}
public final Collection<Message> getMessages()
{
return _messages.values();
}
public final boolean hasUnreadPost(L2PcInstance player)
{
final int objectId = player.getObjectId();
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && msg.isUnread())
{
return true;
}
}
return false;
}
public final int getInboxSize(int objectId)
{
int size = 0;
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver())
{
size++;
}
}
return size;
}
public final int getOutboxSize(int objectId)
{
int size = 0;
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getSenderId() == objectId) && !msg.isDeletedBySender())
{
size++;
}
}
return size;
}
public final List<Message> getInbox(int objectId)
{
final List<Message> inbox = new ArrayList<>();
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver())
{
inbox.add(msg);
}
}
return inbox;
}
public final long getUnreadCount(L2PcInstance player)
{
return getInbox(player.getObjectId()).stream().filter(Message::isUnread).count();
}
public final List<Message> getOutbox(int objectId)
{
final List<Message> outbox = new ArrayList<>();
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getSenderId() == objectId) && !msg.isDeletedBySender())
{
outbox.add(msg);
}
}
return outbox;
}
public void sendMessage(Message msg)
{
_messages.put(msg.getId(), msg);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = Message.getStatement(msg, con))
{
ps.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error saving message:" + e.getMessage(), e);
}
final L2PcInstance receiver = L2World.getInstance().getPlayer(msg.getReceiverId());
if (receiver != null)
{
receiver.sendPacket(ExNoticePostArrived.valueOf(true));
receiver.sendPacket(new ExUnReadMailCount(receiver));
}
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msg.getId()), msg.getExpiration() - System.currentTimeMillis());
}
public final void markAsReadInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET isUnread = 'false' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error marking as read message:" + e.getMessage(), e);
}
}
public final void markAsDeletedBySenderInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET isDeletedBySender = 'true' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error marking as deleted by sender message:" + e.getMessage(), e);
}
}
public final void markAsDeletedByReceiverInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET isDeletedByReceiver = 'true' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error marking as deleted by receiver message:" + e.getMessage(), e);
}
}
public final void removeAttachmentsInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET hasAttachments = 'false' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error removing attachments in message:" + e.getMessage(), e);
}
}
public final void deleteMessageInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM messages WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting message:" + e.getMessage(), e);
}
_messages.remove(msgId);
IdFactory.getInstance().releaseId(msgId);
}
/**
* Gets the single instance of {@code MailManager}.
* @return single instance of {@code MailManager}
*/
public static MailManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MailManager _instance = new MailManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.enums.MailType;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.tasks.MessageDeletionTask;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Message;
import com.l2jmobius.gameserver.network.serverpackets.ExNoticePostArrived;
import com.l2jmobius.gameserver.network.serverpackets.ExUnReadMailCount;
/**
* @author Migi, DS
*/
public final class MailManager
{
private static final Logger LOGGER = Logger.getLogger(MailManager.class.getName());
private final Map<Integer, Message> _messages = new ConcurrentHashMap<>();
protected MailManager()
{
load();
}
private void load()
{
int count = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement ps = con.createStatement();
ResultSet rs = ps.executeQuery("SELECT * FROM messages ORDER BY expiration"))
{
while (rs.next())
{
final Message msg = new Message(rs);
final int msgId = msg.getId();
_messages.put(msgId, msg);
count++;
final long expiration = msg.getExpiration();
if (expiration < System.currentTimeMillis())
{
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msgId), 10000);
}
else
{
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msgId), expiration - System.currentTimeMillis());
}
}
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading from database:", e);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + count + " messages.");
}
public final Message getMessage(int msgId)
{
return _messages.get(msgId);
}
public final Collection<Message> getMessages()
{
return _messages.values();
}
public final boolean hasUnreadPost(L2PcInstance player)
{
final int objectId = player.getObjectId();
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && msg.isUnread())
{
return true;
}
}
return false;
}
public final int getInboxSize(int objectId)
{
int size = 0;
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver())
{
size++;
}
}
return size;
}
public final int getOutboxSize(int objectId)
{
int size = 0;
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getSenderId() == objectId) && !msg.isDeletedBySender())
{
size++;
}
}
return size;
}
public final List<Message> getInbox(int objectId)
{
final List<Message> inbox = new LinkedList<>();
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver())
{
inbox.add(msg);
}
}
return inbox;
}
public final long getUnreadCount(L2PcInstance player)
{
return getInbox(player.getObjectId()).stream().filter(Message::isUnread).count();
}
public int getMailsInProgress(int objectId)
{
int count = 0;
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getMailType() == MailType.REGULAR))
{
if ((msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver() && !msg.isReturned() && msg.hasAttachments())
{
count++;
}
else if ((msg.getSenderId() == objectId) && !msg.isDeletedBySender() && !msg.isReturned() && msg.hasAttachments())
{
count++;
}
}
}
return count;
}
public final List<Message> getOutbox(int objectId)
{
final List<Message> outbox = new LinkedList<>();
for (Message msg : getMessages())
{
if ((msg != null) && (msg.getSenderId() == objectId) && !msg.isDeletedBySender())
{
outbox.add(msg);
}
}
return outbox;
}
public void sendMessage(Message msg)
{
_messages.put(msg.getId(), msg);
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = Message.getStatement(msg, con))
{
ps.execute();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error saving message:", e);
}
final L2PcInstance receiver = L2World.getInstance().getPlayer(msg.getReceiverId());
if (receiver != null)
{
receiver.sendPacket(ExNoticePostArrived.valueOf(true));
receiver.sendPacket(new ExUnReadMailCount(receiver));
}
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msg.getId()), msg.getExpiration() - System.currentTimeMillis());
}
public final void markAsReadInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET isUnread = 'false' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error marking as read message:", e);
}
}
public final void markAsDeletedBySenderInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET isDeletedBySender = 'true' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error marking as deleted by sender message:", e);
}
}
public final void markAsDeletedByReceiverInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET isDeletedByReceiver = 'true' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error marking as deleted by receiver message:", e);
}
}
public final void removeAttachmentsInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE messages SET hasAttachments = 'false' WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error removing attachments in message:", e);
}
}
public final void deleteMessageInDb(int msgId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM messages WHERE messageId = ?"))
{
ps.setInt(1, msgId);
ps.execute();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting message:", e);
}
_messages.remove(msgId);
IdFactory.getInstance().releaseId(msgId);
}
/**
* Gets the single instance of {@code MailManager}.
* @return single instance of {@code MailManager}
*/
public static MailManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MailManager _instance = new MailManager();
}
}

View File

@@ -1,446 +1,484 @@
/*
* 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.instancemanager;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.L2MapRegion;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.TeleportWhereType;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.entity.Instance;
import com.l2jmobius.gameserver.model.entity.clanhall.SiegableHall;
import com.l2jmobius.gameserver.model.zone.type.L2ClanHallZone;
import com.l2jmobius.gameserver.model.zone.type.L2RespawnZone;
import com.l2jmobius.util.data.xml.IXmlReader;
/**
* Map Region Manager.
* @author Nyaran
*/
public final class MapRegionManager implements IXmlReader
{
private static final Map<String, L2MapRegion> _regions = new HashMap<>();
private static final String defaultRespawn = "talking_island_town";
protected MapRegionManager()
{
load();
}
@Override
public void load()
{
_regions.clear();
parseDatapackDirectory("mapregion", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _regions.size() + " map regions.");
}
@Override
public void parseDocument(Document doc)
{
NamedNodeMap attrs;
String name;
String town;
int locId;
int castle;
int bbs;
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("region".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
name = attrs.getNamedItem("name").getNodeValue();
town = attrs.getNamedItem("town").getNodeValue();
locId = parseInteger(attrs, "locId");
castle = parseInteger(attrs, "castle");
bbs = parseInteger(attrs, "bbs");
final L2MapRegion region = new L2MapRegion(name, town, locId, castle, bbs);
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
attrs = c.getAttributes();
if ("respawnPoint".equalsIgnoreCase(c.getNodeName()))
{
final int spawnX = parseInteger(attrs, "X");
final int spawnY = parseInteger(attrs, "Y");
final int spawnZ = parseInteger(attrs, "Z");
if (parseBoolean(attrs, "isOther", false))
{
region.addOtherSpawn(spawnX, spawnY, spawnZ);
}
else if (parseBoolean(attrs, "isChaotic", false))
{
region.addChaoticSpawn(spawnX, spawnY, spawnZ);
}
else if (parseBoolean(attrs, "isBanish", false))
{
region.addBanishSpawn(spawnX, spawnY, spawnZ);
}
else
{
region.addSpawn(spawnX, spawnY, spawnZ);
}
}
else if ("map".equalsIgnoreCase(c.getNodeName()))
{
region.addMap(parseInteger(attrs, "X"), parseInteger(attrs, "Y"));
}
else if ("banned".equalsIgnoreCase(c.getNodeName()))
{
region.addBannedRace(attrs.getNamedItem("race").getNodeValue(), attrs.getNamedItem("point").getNodeValue());
}
}
_regions.put(name, region);
}
}
}
}
}
/**
* @param locX
* @param locY
* @return
*/
public final L2MapRegion getMapRegion(int locX, int locY)
{
for (L2MapRegion region : _regions.values())
{
if (region.isZoneInRegion(getMapRegionX(locX), getMapRegionY(locY)))
{
return region;
}
}
return null;
}
/**
* @param locX
* @param locY
* @return
*/
public final int getMapRegionLocId(int locX, int locY)
{
final L2MapRegion region = getMapRegion(locX, locY);
return region != null ? region.getLocId() : 0;
}
/**
* @param obj
* @return
*/
public final L2MapRegion getMapRegion(L2Object obj)
{
return getMapRegion(obj.getX(), obj.getY());
}
/**
* @param obj
* @return
*/
public final int getMapRegionLocId(L2Object obj)
{
return getMapRegionLocId(obj.getX(), obj.getY());
}
/**
* @param posX
* @return
*/
public final int getMapRegionX(int posX)
{
return (posX >> 15) + 9 + 11; // + centerTileX;
}
/**
* @param posY
* @return
*/
public final int getMapRegionY(int posY)
{
return (posY >> 15) + 10 + 8; // + centerTileX;
}
/**
* Get town name by character position
* @param activeChar
* @return
*/
public String getClosestTownName(L2Character activeChar)
{
final L2MapRegion region = getMapRegion(activeChar);
return region == null ? "Aden Castle Town" : region.getTown();
}
/**
* @param activeChar
* @return
*/
public int getAreaCastle(L2Character activeChar)
{
final L2MapRegion region = getMapRegion(activeChar);
return region == null ? 0 : region.getCastle();
}
/**
* @param activeChar
* @param teleportWhere
* @return
*/
public Location getTeleToLocation(L2Character activeChar, TeleportWhereType teleportWhere)
{
Location loc;
if (activeChar.isPlayer())
{
final L2PcInstance player = activeChar.getActingPlayer();
Castle castle = null;
Fort fort = null;
ClanHall clanhall = null;
if ((player.getClan() != null) && !player.isFlyingMounted() && !player.isFlying()) // flying players in gracia cant use teleports to aden continent
{
// If teleport to clan hall
if (teleportWhere == TeleportWhereType.CLANHALL)
{
clanhall = ClanHallManager.getInstance().getAbstractHallByOwner(player.getClan());
if (clanhall != null)
{
final L2ClanHallZone zone = clanhall.getZone();
if ((zone != null) && !player.isFlyingMounted())
{
return player.getReputation() < 0 ? zone.getChaoticSpawnLoc() : zone.getSpawnLoc();
}
}
}
// If teleport to castle
if (teleportWhere == TeleportWhereType.CASTLE)
{
castle = CastleManager.getInstance().getCastleByOwner(player.getClan());
// Otherwise check if player is on castle or fortress ground
// and player's clan is defender
if (castle == null)
{
castle = CastleManager.getInstance().getCastle(player);
if ((castle == null) || !castle.getSiege().isInProgress() || (castle.getSiege().getDefenderClan(player.getClan()) == null))
{
castle = null;
}
}
if ((castle != null) && (castle.getResidenceId() > 0))
{
return player.getReputation() < 0 ? castle.getResidenceZone().getChaoticSpawnLoc() : castle.getResidenceZone().getSpawnLoc();
}
}
// If teleport to fortress
if (teleportWhere == TeleportWhereType.FORTRESS)
{
fort = FortManager.getInstance().getFortByOwner(player.getClan());
// Otherwise check if player is on castle or fortress ground
// and player's clan is defender
if (fort == null)
{
fort = FortManager.getInstance().getFort(player);
if ((fort == null) || !fort.getSiege().isInProgress() || (fort.getOwnerClan() != player.getClan()))
{
fort = null;
}
}
if ((fort != null) && (fort.getResidenceId() > 0))
{
return player.getReputation() < 0 ? fort.getResidenceZone().getChaoticSpawnLoc() : fort.getResidenceZone().getSpawnLoc();
}
}
// If teleport to SiegeHQ
if (teleportWhere == TeleportWhereType.SIEGEFLAG)
{
castle = CastleManager.getInstance().getCastle(player);
fort = FortManager.getInstance().getFort(player);
clanhall = ClanHallManager.getInstance().getNearbyAbstractHall(activeChar.getX(), activeChar.getY(), 10000);
if (castle != null)
{
if (castle.getSiege().isInProgress())
{
// Check if player's clan is attacker
final List<L2Npc> flags = castle.getSiege().getFlag(player.getClan());
if ((flags != null) && !flags.isEmpty())
{
// Spawn to flag - Need more work to get player to the nearest flag
return flags.get(0).getLocation();
}
}
}
else if (fort != null)
{
if (fort.getSiege().isInProgress())
{
// Check if player's clan is attacker
final List<L2Npc> flags = fort.getSiege().getFlag(player.getClan());
if ((flags != null) && !flags.isEmpty())
{
// Spawn to flag - Need more work to get player to the nearest flag
return flags.get(0).getLocation();
}
}
}
else if ((clanhall != null) && clanhall.isSiegableHall())
{
final SiegableHall sHall = (SiegableHall) clanhall;
final List<L2Npc> flags = sHall.getSiege().getFlag(player.getClan());
if ((flags != null) && !flags.isEmpty())
{
return flags.get(0).getLocation();
}
}
}
}
// Karma player land out of city
if (player.getReputation() < 0)
{
try
{
final L2RespawnZone zone = ZoneManager.getInstance().getZone(player, L2RespawnZone.class);
return zone != null ? getRestartRegion(activeChar, zone.getRespawnPoint((L2PcInstance) activeChar)).getChaoticSpawnLoc() : getMapRegion(activeChar).getChaoticSpawnLoc();
}
catch (Exception e)
{
return player.isFlyingMounted() ? _regions.get("union_base_of_kserth").getChaoticSpawnLoc() : _regions.get(defaultRespawn).getChaoticSpawnLoc();
}
}
// Checking if needed to be respawned in "far" town from the castle;
castle = CastleManager.getInstance().getCastle(player);
// Check if player's clan is participating
if ((castle != null) && castle.getSiege().isInProgress() && (castle.getSiege().checkIsDefender(player.getClan()) || castle.getSiege().checkIsAttacker(player.getClan())))
{
return castle.getResidenceZone().getOtherSpawnLoc();
}
// Checking if in an instance
if (player.getInstanceId() > 0)
{
final Instance inst = InstanceManager.getInstance().getInstance(player.getInstanceId());
if (inst != null)
{
loc = inst.getExitLoc();
if (loc != null)
{
return loc;
}
}
}
}
if (Config.FACTION_SYSTEM_ENABLED && Config.FACTION_RESPAWN_AT_BASE)
{
if (activeChar.getActingPlayer().isGood())
{
return Config.FACTION_GOOD_BASE_LOCATION;
}
if (activeChar.getActingPlayer().isEvil())
{
return Config.FACTION_EVIL_BASE_LOCATION;
}
}
// Get the nearest town
try
{
final L2RespawnZone zone = ZoneManager.getInstance().getZone(activeChar, L2RespawnZone.class);
return zone != null ? getRestartRegion(activeChar, zone.getRespawnPoint((L2PcInstance) activeChar)).getSpawnLoc() : getMapRegion(activeChar).getSpawnLoc();
}
catch (Exception e)
{
// Port to the default respawn if no closest town found.
return _regions.get(defaultRespawn).getSpawnLoc();
}
}
/**
* @param activeChar
* @param point
* @return
*/
public L2MapRegion getRestartRegion(L2Character activeChar, String point)
{
try
{
final L2PcInstance player = (L2PcInstance) activeChar;
final L2MapRegion region = _regions.get(point);
if (region.getBannedRace().containsKey(player.getRace()))
{
getRestartRegion(player, region.getBannedRace().get(player.getRace()));
}
return region;
}
catch (Exception e)
{
return _regions.get(defaultRespawn);
}
}
/**
* @param regionName the map region name.
* @return if exists the map region identified by that name, null otherwise.
*/
public L2MapRegion getMapRegionByName(String regionName)
{
return _regions.get(regionName);
}
/**
* Gets the single instance of {@code MapRegionManager}.
* @return single instance of {@code MapRegionManager}
*/
public static MapRegionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MapRegionManager _instance = new MapRegionManager();
}
}
/*
* 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.instancemanager;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.data.xml.impl.ClanHallData;
import com.l2jmobius.gameserver.model.L2MapRegion;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.TeleportWhereType;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.model.interfaces.ILocational;
import com.l2jmobius.gameserver.model.zone.type.L2RespawnZone;
/**
* Map Region Manager.
* @author Nyaran
*/
public final class MapRegionManager implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(MapRegionManager.class.getName());
private final Map<String, L2MapRegion> _regions = new HashMap<>();
private final String defaultRespawn = "talking_island_town";
protected MapRegionManager()
{
load();
}
@Override
public void load()
{
_regions.clear();
parseDatapackDirectory("data/mapregion", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _regions.size() + " map regions.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
String name;
String town;
int locId;
int castle;
int bbs;
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("region".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
name = attrs.getNamedItem("name").getNodeValue();
town = attrs.getNamedItem("town").getNodeValue();
locId = parseInteger(attrs, "locId");
castle = parseInteger(attrs, "castle");
bbs = parseInteger(attrs, "bbs");
final L2MapRegion region = new L2MapRegion(name, town, locId, castle, bbs);
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
attrs = c.getAttributes();
if ("respawnPoint".equalsIgnoreCase(c.getNodeName()))
{
final int spawnX = parseInteger(attrs, "X");
final int spawnY = parseInteger(attrs, "Y");
final int spawnZ = parseInteger(attrs, "Z");
final boolean other = parseBoolean(attrs, "isOther", false);
final boolean chaotic = parseBoolean(attrs, "isChaotic", false);
final boolean banish = parseBoolean(attrs, "isBanish", false);
if (other)
{
region.addOtherSpawn(spawnX, spawnY, spawnZ);
}
else if (chaotic)
{
region.addChaoticSpawn(spawnX, spawnY, spawnZ);
}
else if (banish)
{
region.addBanishSpawn(spawnX, spawnY, spawnZ);
}
else
{
region.addSpawn(spawnX, spawnY, spawnZ);
}
}
else if ("map".equalsIgnoreCase(c.getNodeName()))
{
region.addMap(parseInteger(attrs, "X"), parseInteger(attrs, "Y"));
}
else if ("banned".equalsIgnoreCase(c.getNodeName()))
{
region.addBannedRace(attrs.getNamedItem("race").getNodeValue(), attrs.getNamedItem("point").getNodeValue());
}
}
_regions.put(name, region);
}
}
}
}
}
/**
* @param locX
* @param locY
* @return
*/
public final L2MapRegion getMapRegion(int locX, int locY)
{
for (L2MapRegion region : _regions.values())
{
if (region.isZoneInRegion(getMapRegionX(locX), getMapRegionY(locY)))
{
return region;
}
}
return null;
}
/**
* @param locX
* @param locY
* @return
*/
public final int getMapRegionLocId(int locX, int locY)
{
final L2MapRegion region = getMapRegion(locX, locY);
if (region != null)
{
return region.getLocId();
}
return 0;
}
/**
* @param obj
* @return
*/
public final L2MapRegion getMapRegion(L2Object obj)
{
return getMapRegion(obj.getX(), obj.getY());
}
/**
* @param obj
* @return
*/
public final int getMapRegionLocId(L2Object obj)
{
return getMapRegionLocId(obj.getX(), obj.getY());
}
/**
* @param posX
* @return
*/
public final int getMapRegionX(int posX)
{
return (posX >> 15) + 9 + 11; // + centerTileX;
}
/**
* @param posY
* @return
*/
public final int getMapRegionY(int posY)
{
return (posY >> 15) + 10 + 8; // + centerTileX;
}
/**
* Get town name by character position
* @param activeChar
* @return
*/
public String getClosestTownName(L2Character activeChar)
{
final L2MapRegion region = getMapRegion(activeChar);
if (region == null)
{
return "Aden Castle Town";
}
return region.getTown();
}
/**
* @param activeChar
* @return
*/
public int getAreaCastle(L2Character activeChar)
{
final L2MapRegion region = getMapRegion(activeChar);
if (region == null)
{
return 0;
}
return region.getCastle();
}
/**
* @param activeChar
* @param teleportWhere
* @return
*/
public Location getTeleToLocation(L2Character activeChar, TeleportWhereType teleportWhere)
{
if (activeChar.isPlayer())
{
final L2PcInstance player = activeChar.getActingPlayer();
Castle castle = null;
Fort fort = null;
ClanHall clanhall = null;
if ((player.getClan() != null) && !player.isFlyingMounted() && !player.isFlying()) // flying players in gracia cant use teleports to aden continent
{
// If teleport to clan hall
if (teleportWhere == TeleportWhereType.CLANHALL)
{
clanhall = ClanHallData.getInstance().getClanHallByClan(player.getClan());
if ((clanhall != null) && !player.isFlyingMounted())
{
return clanhall.getOwnerLocation();
}
}
// If teleport to castle
if (teleportWhere == TeleportWhereType.CASTLE)
{
castle = CastleManager.getInstance().getCastleByOwner(player.getClan());
// Otherwise check if player is on castle or fortress ground
// and player's clan is defender
if (castle == null)
{
castle = CastleManager.getInstance().getCastle(player);
if (!((castle != null) && castle.getSiege().isInProgress() && (castle.getSiege().getDefenderClan(player.getClan()) != null)))
{
castle = null;
}
}
if ((castle != null) && (castle.getResidenceId() > 0))
{
if (player.getReputation() < 0)
{
return castle.getResidenceZone().getChaoticSpawnLoc();
}
return castle.getResidenceZone().getSpawnLoc();
}
}
// If teleport to fortress
if (teleportWhere == TeleportWhereType.FORTRESS)
{
fort = FortManager.getInstance().getFortByOwner(player.getClan());
// Otherwise check if player is on castle or fortress ground
// and player's clan is defender
if (fort == null)
{
fort = FortManager.getInstance().getFort(player);
if (!((fort != null) && fort.getSiege().isInProgress() && (fort.getOwnerClan() == player.getClan())))
{
fort = null;
}
}
if ((fort != null) && (fort.getResidenceId() > 0))
{
if (player.getReputation() < 0)
{
return fort.getResidenceZone().getChaoticSpawnLoc();
}
return fort.getResidenceZone().getSpawnLoc();
}
}
// If teleport to SiegeHQ
if (teleportWhere == TeleportWhereType.SIEGEFLAG)
{
castle = CastleManager.getInstance().getCastle(player);
fort = FortManager.getInstance().getFort(player);
if (castle != null)
{
if (castle.getSiege().isInProgress())
{
// Check if player's clan is attacker
final Set<L2Npc> flags = castle.getSiege().getFlag(player.getClan());
if ((flags != null) && !flags.isEmpty())
{
// Spawn to flag - Need more work to get player to the nearest flag
return flags.stream().findAny().get().getLocation();
}
}
}
else if (fort != null)
{
if (fort.getSiege().isInProgress())
{
// Check if player's clan is attacker
final Set<L2Npc> flags = fort.getSiege().getFlag(player.getClan());
if ((flags != null) && !flags.isEmpty())
{
// Spawn to flag - Need more work to get player to the nearest flag
return flags.stream().findAny().get().getLocation();
}
}
}
}
}
// Karma player land out of city
if (player.getReputation() < 0)
{
try
{
final L2RespawnZone zone = ZoneManager.getInstance().getZone(player, L2RespawnZone.class);
if (zone != null)
{
return getRestartRegion(activeChar, zone.getRespawnPoint((L2PcInstance) activeChar)).getChaoticSpawnLoc();
}
return getMapRegion(activeChar).getChaoticSpawnLoc();
}
catch (Exception e)
{
if (player.isFlyingMounted())
{
return _regions.get("union_base_of_kserth").getChaoticSpawnLoc();
}
return _regions.get(defaultRespawn).getChaoticSpawnLoc();
}
}
// Checking if needed to be respawned in "far" town from the castle;
castle = CastleManager.getInstance().getCastle(player);
if (castle != null)
{
if (castle.getSiege().isInProgress())
{
// Check if player's clan is participating
if ((castle.getSiege().checkIsDefender(player.getClan()) || castle.getSiege().checkIsAttacker(player.getClan())))
{
return castle.getResidenceZone().getOtherSpawnLoc();
}
}
}
// Checking if in an instance
final Instance inst = player.getInstanceWorld();
if (inst != null)
{
final Location loc = inst.getExitLocation(player);
if (loc != null)
{
return loc;
}
}
}
if (Config.FACTION_SYSTEM_ENABLED && Config.FACTION_RESPAWN_AT_BASE)
{
if (activeChar.getActingPlayer().isGood())
{
return Config.FACTION_GOOD_BASE_LOCATION;
}
if (activeChar.getActingPlayer().isEvil())
{
return Config.FACTION_EVIL_BASE_LOCATION;
}
}
// Get the nearest town
try
{
final L2RespawnZone zone = ZoneManager.getInstance().getZone(activeChar, L2RespawnZone.class);
if (zone != null)
{
return getRestartRegion(activeChar, zone.getRespawnPoint((L2PcInstance) activeChar)).getSpawnLoc();
}
return getMapRegion(activeChar).getSpawnLoc();
}
catch (Exception e)
{
// Port to the default respawn if no closest town found.
return _regions.get(defaultRespawn).getSpawnLoc();
}
}
/**
* @param activeChar
* @param point
* @return
*/
public L2MapRegion getRestartRegion(L2Character activeChar, String point)
{
try
{
final L2PcInstance player = ((L2PcInstance) activeChar);
final L2MapRegion region = _regions.get(point);
if (region.getBannedRace().containsKey(player.getRace()))
{
getRestartRegion(player, region.getBannedRace().get(player.getRace()));
}
return region;
}
catch (Exception e)
{
return _regions.get(defaultRespawn);
}
}
/**
* @param regionName the map region name.
* @return if exists the map region identified by that name, null otherwise.
*/
public L2MapRegion getMapRegionByName(String regionName)
{
return _regions.get(regionName);
}
public int getBBs(ILocational loc)
{
final L2MapRegion region = getMapRegion(loc.getX(), loc.getY());
return region != null ? region.getBbs() : _regions.get(defaultRespawn).getBbs();
}
/**
* Gets the single instance of {@code MapRegionManager}.
* @return single instance of {@code MapRegionManager}
*/
public static MapRegionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MapRegionManager _instance = new MapRegionManager();
}
}

View File

@@ -0,0 +1,145 @@
/*
* 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.instancemanager;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import com.l2jmobius.gameserver.enums.MatchingRoomType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.matching.MatchingRoom;
/**
* @author Sdw
*/
public class MatchingRoomManager
{
private volatile Set<L2PcInstance> _waitingList;
private static final Map<MatchingRoomType, Map<Integer, MatchingRoom>> _rooms = new ConcurrentHashMap<>(2);
private final AtomicInteger _id = new AtomicInteger(0);
public void addToWaitingList(L2PcInstance player)
{
if (_waitingList == null)
{
synchronized (this)
{
if (_waitingList == null)
{
_waitingList = ConcurrentHashMap.newKeySet(1);
}
}
}
_waitingList.add(player);
}
public void removeFromWaitingList(L2PcInstance player)
{
getPlayerInWaitingList().remove(player);
}
public Set<L2PcInstance> getPlayerInWaitingList()
{
return _waitingList == null ? Collections.emptySet() : _waitingList;
}
public List<L2PcInstance> getPlayerInWaitingList(int minLevel, int maxLevel, List<ClassId> classIds, String query)
{
return _waitingList == null ? Collections.emptyList() : _waitingList.stream().filter(p -> (p.getLevel() >= minLevel) && (p.getLevel() <= maxLevel)).filter(p -> (classIds == null) || classIds.contains(p.getClassId())).filter(p -> query.isEmpty() || p.getName().toLowerCase().contains(query)).collect(Collectors.toList());
}
public int addMatchingRoom(MatchingRoom room)
{
final int roomId = _id.incrementAndGet();
_rooms.computeIfAbsent(room.getRoomType(), k -> new ConcurrentHashMap<>()).put(roomId, room);
return roomId;
}
public void removeMatchingRoom(MatchingRoom room)
{
_rooms.getOrDefault(room.getRoomType(), Collections.emptyMap()).remove(room.getId());
}
public Map<Integer, MatchingRoom> getPartyMathchingRooms()
{
return _rooms.get(MatchingRoomType.PARTY);
}
public List<MatchingRoom> getPartyMathchingRooms(int location, int level)
{
//@formatter:off
return _rooms.getOrDefault(MatchingRoomType.PARTY, Collections.emptyMap()).values().stream()
.filter(r -> (location < 0) || (r.getLocation() == location))
.filter(r -> (r.getMinLvl() <= level) && (r.getMaxLvl() >= level))
.collect(Collectors.toList());
//@formatter:on
}
public Map<Integer, MatchingRoom> getCCMathchingRooms()
{
return _rooms.get(MatchingRoomType.COMMAND_CHANNEL);
}
public List<MatchingRoom> getCCMathchingRooms(int location, int level)
{
//@formatter:off
return _rooms.getOrDefault(MatchingRoomType.COMMAND_CHANNEL, Collections.emptyMap()).values().stream()
.filter(r -> r.getLocation() == location)
.filter(r -> (r.getMinLvl() <= level) && (r.getMaxLvl() >= level))
.collect(Collectors.toList());
//@formatter:on
}
public MatchingRoom getCCMatchingRoom(int roomId)
{
return _rooms.getOrDefault(MatchingRoomType.COMMAND_CHANNEL, Collections.emptyMap()).get(roomId);
}
public MatchingRoom getPartyMathchingRoom(int location, int level)
{
//@formatter:off
return _rooms.getOrDefault(MatchingRoomType.PARTY, Collections.emptyMap()).values().stream()
.filter(r -> r.getLocation() == location)
.filter(r -> (r.getMinLvl() <= level) && (r.getMaxLvl() >= level))
.findFirst()
.orElse(null);
//@formatter:on
}
public MatchingRoom getPartyMathchingRoom(int roomId)
{
return _rooms.getOrDefault(MatchingRoomType.PARTY, Collections.emptyMap()).get(roomId);
}
public static MatchingRoomManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MatchingRoomManager _instance = new MatchingRoomManager();
}
}

View File

@@ -1,255 +1,268 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Mentee;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.variables.PlayerVariables;
/**
* @author UnAfraid
*/
public class MentorManager
{
private static final Logger _log = Logger.getLogger(MentorManager.class.getName());
private final Map<Integer, Map<Integer, L2Mentee>> _menteeData = new ConcurrentHashMap<>();
private final Map<Integer, L2Mentee> _mentors = new ConcurrentHashMap<>();
protected MentorManager()
{
load();
}
private void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rset = statement.executeQuery("SELECT * FROM character_mentees"))
{
while (rset.next())
{
addMentor(rset.getInt("mentorId"), rset.getInt("charId"));
}
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
}
/**
* Removes mentee for current L2PcInstance
* @param mentorId
* @param menteeId
*/
public void deleteMentee(int mentorId, int menteeId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM character_mentees WHERE mentorId = ? AND charId = ?"))
{
statement.setInt(1, mentorId);
statement.setInt(2, menteeId);
statement.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
}
/**
* @param mentorId
* @param menteeId
*/
public void deleteMentor(int mentorId, int menteeId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM character_mentees WHERE mentorId = ? AND charId = ?"))
{
statement.setInt(1, mentorId);
statement.setInt(2, menteeId);
statement.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
finally
{
removeMentor(mentorId, menteeId);
}
}
public boolean isMentor(int objectId)
{
return _menteeData.containsKey(objectId);
}
public boolean isMentee(int objectId)
{
return _menteeData.values().stream().anyMatch(map -> map.containsKey(objectId));
}
public Map<Integer, Map<Integer, L2Mentee>> getMentorData()
{
return _menteeData;
}
public void cancelMentoringBuffs(L2PcInstance player)
{
if (player == null)
{
return;
}
//@formatter:off
player.getEffectList().getEffects()
.stream()
.map(BuffInfo::getSkill)
.filter(Skill::isMentoring)
.forEach(player::stopSkillEffects);
//@formatter:on
}
public void setPenalty(int mentorId, long penalty)
{
final L2PcInstance player = L2World.getInstance().getPlayer(mentorId);
(player != null ? player.getVariables() : new PlayerVariables(mentorId)).set("Mentor-Penalty-" + mentorId, String.valueOf(System.currentTimeMillis() + penalty));
}
public long getMentorPenalty(int mentorId)
{
final L2PcInstance player = L2World.getInstance().getPlayer(mentorId);
return (player != null ? player.getVariables() : new PlayerVariables(mentorId)).getLong("Mentor-Penalty-" + mentorId, 0);
}
/**
* @param mentorId
* @param menteeId
*/
public void addMentor(int mentorId, int menteeId)
{
_menteeData.computeIfAbsent(mentorId, map -> new ConcurrentHashMap<>());
if (_menteeData.get(mentorId).containsKey(menteeId))
{
_menteeData.get(mentorId).get(menteeId).load(); // Just reloading data if is already there
}
else
{
_menteeData.get(mentorId).put(menteeId, new L2Mentee(menteeId));
}
}
/**
* @param mentorId
* @param menteeId
*/
public void removeMentor(int mentorId, int menteeId)
{
if (_menteeData.containsKey(mentorId))
{
_menteeData.get(mentorId).remove(menteeId);
if (_menteeData.get(mentorId).isEmpty())
{
_menteeData.remove(mentorId);
_mentors.remove(mentorId);
}
}
}
/**
* @param menteeId
* @return
*/
public L2Mentee getMentor(int menteeId)
{
for (Entry<Integer, Map<Integer, L2Mentee>> map : _menteeData.entrySet())
{
if (map.getValue().containsKey(menteeId))
{
if (!_mentors.containsKey(map.getKey()))
{
_mentors.put(map.getKey(), new L2Mentee(map.getKey()));
}
return _mentors.get(map.getKey());
}
}
return null;
}
public Collection<L2Mentee> getMentees(int mentorId)
{
return _menteeData.containsKey(mentorId) ? _menteeData.get(mentorId).values() : Collections.emptyList();
}
/**
* @param mentorId
* @param menteeId
* @return
*/
public L2Mentee getMentee(int mentorId, int menteeId)
{
return _menteeData.containsKey(mentorId) ? _menteeData.get(mentorId).get(menteeId) : null;
}
public boolean isAllMenteesOffline(int menteorId, int menteeId)
{
boolean isAllMenteesOffline = true;
for (L2Mentee men : getMentees(menteorId))
{
if (men.isOnline() && (men.getObjectId() != menteeId) && isAllMenteesOffline)
{
isAllMenteesOffline = false;
break;
}
}
return isAllMenteesOffline;
}
public boolean hasOnlineMentees(int menteorId)
{
return getMentees(menteorId).stream().filter(Objects::nonNull).filter(L2Mentee::isOnline).count() > 0;
}
public static MentorManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MentorManager _instance = new MentorManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Mentee;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.skills.BuffInfo;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.variables.PlayerVariables;
/**
* @author UnAfraid
*/
public class MentorManager
{
private static final Logger _log = Logger.getLogger(MentorManager.class.getName());
private final Map<Integer, Map<Integer, L2Mentee>> _menteeData = new ConcurrentHashMap<>();
private final Map<Integer, L2Mentee> _mentors = new ConcurrentHashMap<>();
protected MentorManager()
{
load();
}
private void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rset = statement.executeQuery("SELECT * FROM character_mentees"))
{
while (rset.next())
{
addMentor(rset.getInt("mentorId"), rset.getInt("charId"));
}
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
}
/**
* Removes mentee for current L2PcInstance
* @param mentorId
* @param menteeId
*/
public void deleteMentee(int mentorId, int menteeId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM character_mentees WHERE mentorId = ? AND charId = ?"))
{
statement.setInt(1, mentorId);
statement.setInt(2, menteeId);
statement.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
}
/**
* @param mentorId
* @param menteeId
*/
public void deleteMentor(int mentorId, int menteeId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM character_mentees WHERE mentorId = ? AND charId = ?"))
{
statement.setInt(1, mentorId);
statement.setInt(2, menteeId);
statement.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, e.getMessage(), e);
}
finally
{
removeMentor(mentorId, menteeId);
}
}
public boolean isMentor(int objectId)
{
return _menteeData.containsKey(objectId);
}
public boolean isMentee(int objectId)
{
return _menteeData.values().stream().anyMatch(map -> map.containsKey(objectId));
}
public Map<Integer, Map<Integer, L2Mentee>> getMentorData()
{
return _menteeData;
}
public void cancelAllMentoringBuffs(L2PcInstance player)
{
if (player == null)
{
return;
}
//@formatter:off
player.getEffectList().getEffects()
.stream()
.map(BuffInfo::getSkill)
.filter(Skill::isMentoring)
.forEach(player::stopSkillEffects);
//@formatter:on
}
public void setPenalty(int mentorId, long penalty)
{
final L2PcInstance player = L2World.getInstance().getPlayer(mentorId);
final PlayerVariables vars = player != null ? player.getVariables() : new PlayerVariables(mentorId);
vars.set("Mentor-Penalty-" + mentorId, String.valueOf(System.currentTimeMillis() + penalty));
}
public long getMentorPenalty(int mentorId)
{
final L2PcInstance player = L2World.getInstance().getPlayer(mentorId);
final PlayerVariables vars = player != null ? player.getVariables() : new PlayerVariables(mentorId);
return vars.getLong("Mentor-Penalty-" + mentorId, 0);
}
/**
* @param mentorId
* @param menteeId
*/
public void addMentor(int mentorId, int menteeId)
{
final Map<Integer, L2Mentee> mentees = _menteeData.computeIfAbsent(mentorId, map -> new ConcurrentHashMap<>());
if (mentees.containsKey(menteeId))
{
mentees.get(menteeId).load(); // Just reloading data if is already there
}
else
{
mentees.put(menteeId, new L2Mentee(menteeId));
}
}
/**
* @param mentorId
* @param menteeId
*/
public void removeMentor(int mentorId, int menteeId)
{
if (_menteeData.containsKey(mentorId))
{
_menteeData.get(mentorId).remove(menteeId);
if (_menteeData.get(mentorId).isEmpty())
{
_menteeData.remove(mentorId);
_mentors.remove(mentorId);
}
}
}
/**
* @param menteeId
* @return
*/
public L2Mentee getMentor(int menteeId)
{
for (Entry<Integer, Map<Integer, L2Mentee>> map : _menteeData.entrySet())
{
if (map.getValue().containsKey(menteeId))
{
if (!_mentors.containsKey(map.getKey()))
{
_mentors.put(map.getKey(), new L2Mentee(map.getKey()));
}
return _mentors.get(map.getKey());
}
}
return null;
}
public Collection<L2Mentee> getMentees(int mentorId)
{
if (_menteeData.containsKey(mentorId))
{
return _menteeData.get(mentorId).values();
}
return Collections.emptyList();
}
/**
* @param mentorId
* @param menteeId
* @return
*/
public L2Mentee getMentee(int mentorId, int menteeId)
{
if (_menteeData.containsKey(mentorId))
{
return _menteeData.get(mentorId).get(menteeId);
}
return null;
}
public boolean isAllMenteesOffline(int menteorId, int menteeId)
{
boolean isAllMenteesOffline = true;
for (L2Mentee men : getMentees(menteorId))
{
if (men.isOnline() && (men.getObjectId() != menteeId))
{
if (isAllMenteesOffline)
{
isAllMenteesOffline = false;
break;
}
}
}
return isAllMenteesOffline;
}
public boolean hasOnlineMentees(int menteorId)
{
return getMentees(menteorId).stream().filter(Objects::nonNull).filter(L2Mentee::isOnline).count() > 0;
}
public static MentorManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MentorManager _instance = new MentorManager();
}
}

View File

@@ -1,425 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.enums.ItemLocation;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* This class is similar to the SiegeGuardManager, except it handles the loading of the mercenary tickets that are dropped on castle floors by the castle lords.<br>
* These tickets (a.k.a. badges) need to be read after each server reboot except when the server crashed in the middle of an ongoing siege.<br>
* In addition, this class keeps track of the added tickets, in order to properly limit the number of mercenaries in each castle and the number of mercenaries from each mercenary type.<br>
* Finally, we provide auxiliary functions to identify the castle in which each item (and its corresponding NPC) belong to, in order to help avoid mixing them up.
* @author yellowperil, Fulminus
*/
public final class MercTicketManager
{
private static final Logger _log = Logger.getLogger(MercTicketManager.class.getName());
private static final List<L2ItemInstance> DROPPED_TICKETS = new CopyOnWriteArrayList<>();
// TODO: move all these values into siege.properties
// max tickets per merc type = 10 + (castleid * 2)?
// max ticker per castle = 40 + (castleid * 20)?
// @formatter:off
private static final int[] MAX_MERC_PER_TYPE =
{
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Gludio
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, // Dion
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Giran
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, // Oren
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Aden
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Innadril
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Goddard
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // Rune
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 // Schuttgart
};
//TODO: not retail like: clan lvl 5 - 30 ticks max, lvl 7+ - 50 max
protected static final int[] MERCS_MAX_PER_CASTLE =
{
100, // Gludio
150, // Dion
200, // Giran
300, // Oren
400, // Aden
400, // Innadril
400, // Goddard
400, // Rune
400 // Schuttgart
};
private static final int[] ITEM_IDS =
{
3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, 6047, 6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6295, 6296, // Gludio
3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 6125, 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6245, 6246, 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, 6297, 6298, // Dion
3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, 6144, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6195, 6196, 6197, 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6255, 6256, 6257, 6258, 6259, 6260, 6261, 6262, 6263, 6264, 6299, 6300, // Giran
3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6265, 6266, 6267, 6268, 6269, 6270, 6271, 6272, 6273, 6274, 6301, 6302, // Oren
4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 6155, 6156, 6157, 6158, 6159, 6160, 6161, 6162, 6163, 6164, 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6275, 6276, 6277, 6278, 6279, 6280, 6281, 6282, 6283, 6284, 6303, 6304, // Aden
5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6105, 6106, 6107, 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, 6234, 6285, 6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, 6294, 6305, 6306, // Innadril
6779, 6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, 6788, 6802, 6803, 6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, 6792, 6793, 6794, 6795, 6796, 6797, 6798, 6799, 6800, 6801, 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, 6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, 6828, 6829, 6830, 6831, 6832, 6833, // Goddard
7973, 7974, 7975, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7998, 7999, 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 8008, 8009, 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8024, 8025, 8026, 8027, 8028, 8029, // Rune
7918, 7919, 7920, 7921, 7922, 7923, 7924, 7925, 7926, 7927, 7941, 7942, 7943, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7931, 7932, 7933, 7934, 7935, 7936, 7937, 7938, 7939, 7940, 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7958, 7959, 7960, 7961, 7962, 7963, 7964, 7965, 7966, 7967, 7968, 7969, 7970, 7971, 7972 // Schuttgart
};
private static final int[] NPC_IDS =
{
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Gludio
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Dion
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Giran
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Oren
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Aden
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Innadril
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Goddard
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Rune
35010, 35011, 35012, 35013, 35014, 35015, 35016, 35017, 35018, 35019, 35020, 35021, 35022, 35023, 35024, 35025, 35026, 35027, 35028, 35029, 35030,35031,35032,35033,35034,35035,35036,35037,35038,35039, 35040, 35041, 35042, 35043, 35044, 35045, 35046, 35047, 35048, 35049, 35050, 35051, 35052, 35053, 35054, 35055, 35056, 35057, 35058, 35059, 35060, 35061, // Schuttgart
};
// @formatter:on
private static final int GUARDIAN_TYPES_COUNT = 52;
protected MercTicketManager()
{
load();
}
// returns the castleId for the passed ticket item id
public int getTicketCastleId(int itemId)
{
for (int i = 0; i < 9; i++) // CastleID`s from 1 to 9 minus;
{
for (int i2 = 0; i2 < 50; i2 += 10)
{
// Simplified if statement;
if ((itemId >= ITEM_IDS[i2 + (i * GUARDIAN_TYPES_COUNT)]) && (itemId <= ITEM_IDS[i2 + 9 + (i * GUARDIAN_TYPES_COUNT)]))
{
return i + 1;
}
}
if ((itemId >= ITEM_IDS[50]) && (itemId <= ITEM_IDS[51]))
{
return i + 1;
}
}
return -1;
}
public void reload()
{
DROPPED_TICKETS.clear();
load();
}
/**
* Load merc tickets into the world.
*/
private final void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM castle_siege_guards Where isHired = 1"))
{
int npcId;
int itemId;
int x, y, z;
final int mercPlaced[] = new int[20];
// start index to begin the search for the itemId corresponding to this NPC
// this will help with:
// a) skip unnecessary iterations in the search loop
// b) avoid finding the wrong itemId whenever tickets of different spawn the same npc!
int startindex = 0;
while (rs.next())
{
npcId = rs.getInt("npcId");
x = rs.getInt("x");
y = rs.getInt("y");
z = rs.getInt("z");
final Castle castle = CastleManager.getInstance().getCastle(x, y, z);
if (castle != null)
{
if (mercPlaced[castle.getResidenceId() - 1] >= MERCS_MAX_PER_CASTLE[castle.getResidenceId() - 1])
{
continue;
}
startindex = GUARDIAN_TYPES_COUNT * (castle.getResidenceId() - 1);
mercPlaced[castle.getResidenceId() - 1] += 1;
}
// find the FIRST ticket itemId with spawns the saved NPC in the saved location
for (int i = startindex; i < (startindex + GUARDIAN_TYPES_COUNT); i++)
{
if (NPC_IDS[i] == npcId) // Find the index of the item used
{
// only handle tickets if a siege is not ongoing in this npc's castle
if ((castle != null) && !castle.getSiege().isInProgress())
{
itemId = ITEM_IDS[i];
// create the ticket in the gameworld
final L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
dropticket.setItemLocation(ItemLocation.VOID);
dropticket.dropMe(null, x, y, z);
dropticket.setDropTime(0); // avoids it from being removed by the auto item destroyer
L2World.getInstance().storeObject(dropticket);
DROPPED_TICKETS.add(dropticket);
}
break;
}
}
}
rs.close();
s.close();
_log.info(getClass().getSimpleName() + ": Loaded: " + DROPPED_TICKETS.size() + " Mercenary Tickets");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadMercenaryData(): " + e.getMessage(), e);
}
}
/**
* Checks if the passed item has reached the limit of number of dropped tickets that this SPECIFIC item may have in its castle
* @param itemId
* @return
*/
public boolean isAtTypeLimit(int itemId)
{
int limit = -1;
// find the max value for this item
for (int i = 0; i < ITEM_IDS.length; i++)
{
if (ITEM_IDS[i] == itemId) // Find the index of the item used
{
limit = MAX_MERC_PER_TYPE[i];
break;
}
}
if (limit <= 0)
{
return true;
}
int count = 0;
for (L2ItemInstance ticket : DROPPED_TICKETS)
{
if ((ticket != null) && (ticket.getId() == itemId))
{
count++;
}
}
return count >= limit;
}
/**
* Checks if the passed item belongs to a castle which has reached its limit of number of dropped tickets.
* @param itemId
* @return
*/
public boolean isAtCasleLimit(int itemId)
{
final int castleId = getTicketCastleId(itemId);
if (castleId <= 0)
{
return true;
}
final int limit = MERCS_MAX_PER_CASTLE[castleId - 1];
if (limit <= 0)
{
return true;
}
int count = 0;
for (L2ItemInstance ticket : DROPPED_TICKETS)
{
if ((ticket != null) && (getTicketCastleId(ticket.getId()) == castleId))
{
count++;
}
}
return count >= limit;
}
public int getMaxAllowedMerc(int castleId)
{
return MERCS_MAX_PER_CASTLE[castleId - 1];
}
public boolean isTooCloseToAnotherTicket(int x, int y, int z)
{
for (L2ItemInstance item : DROPPED_TICKETS)
{
final double dx = x - item.getX();
final double dy = y - item.getY();
final double dz = z - item.getZ();
if (((dx * dx) + (dy * dy) + (dz * dz)) < (25 * 25))
{
return true;
}
}
return false;
}
/**
* addTicket actions 1) find the npc that needs to be saved in the mercenary spawns, given this item 2) Use the passed character's location info to add the spawn 3) create a copy of the item to drop in the world returns the id of the mercenary npc that was added to the spawn returns -1 if this
* fails.
* @param itemId
* @param activeChar
* @return
*/
public int addTicket(int itemId, L2PcInstance activeChar)
{
final int x = activeChar.getX();
final int y = activeChar.getY();
final int z = activeChar.getZ();
final int heading = activeChar.getHeading();
final Castle castle = CastleManager.getInstance().getCastle(activeChar);
if (castle == null)
{
return -1;
}
for (int i = 0; i < ITEM_IDS.length; i++)
{
if (ITEM_IDS[i] == itemId) // Find the index of the item used
{
spawnMercenary(NPC_IDS[i], x, y, z, 3000);
// Hire merc for this castle. NpcId is at the same index as the item used.
castle.getSiege().getSiegeGuardManager().hireMerc(x, y, z, heading, NPC_IDS[i]);
// create the ticket in the gameworld
final L2ItemInstance dropticket = new L2ItemInstance(IdFactory.getInstance().getNextId(), itemId);
dropticket.setItemLocation(ItemLocation.VOID);
dropticket.dropMe(null, x, y, z);
dropticket.setDropTime(0); // avoids it from beeing removed by the auto item destroyer
L2World.getInstance().storeObject(dropticket); // add to the world
// and keep track of this ticket in the list
DROPPED_TICKETS.add(dropticket);
return NPC_IDS[i];
}
}
return -1;
}
private void spawnMercenary(int npcId, int x, int y, int z, int despawnDelay)
{
final L2NpcTemplate template = NpcData.getInstance().getTemplate(npcId);
if (template == null)
{
return;
}
final L2DefenderInstance npc = new L2DefenderInstance(template);
npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
npc.setDecayed(false);
npc.spawnMe(x, y, z + 20);
if (despawnDelay > 0)
{
npc.scheduleDespawn(despawnDelay);
}
}
/**
* Delete all tickets from a castle; remove the items from the world and remove references to them from this class
* @param castleId
*/
public void deleteTickets(int castleId)
{
for (L2ItemInstance item : DROPPED_TICKETS)
{
if ((item != null) && (getTicketCastleId(item.getId()) == castleId))
{
item.decayMe();
L2World.getInstance().removeObject(item);
DROPPED_TICKETS.remove(item);
}
}
}
/**
* remove a single ticket and its associated spawn from the world (used when the castle lord picks up a ticket, for example)
* @param item
*/
public void removeTicket(L2ItemInstance item)
{
final int itemId = item.getId();
int npcId = -1;
// find the FIRST ticket itemId with spawns the saved NPC in the saved location
for (int i = 0; i < ITEM_IDS.length; i++)
{
if (ITEM_IDS[i] == itemId) // Find the index of the item used
{
npcId = NPC_IDS[i];
break;
}
}
// find the castle where this item is
final Castle castle = CastleManager.getInstance().getCastleById(getTicketCastleId(itemId));
if ((npcId > 0) && (castle != null))
{
(new SiegeGuardManager(castle)).removeMerc(npcId, item.getX(), item.getY(), item.getZ());
}
DROPPED_TICKETS.remove(item);
}
public int[] getItemIds()
{
return ITEM_IDS;
}
public final List<L2ItemInstance> getDroppedTickets()
{
return DROPPED_TICKETS;
}
/**
* Gets the single instance of {@code MercTicketManager}.
* @return single instance of {@code MercTicketManager}
*/
public static MercTicketManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MercTicketManager _instance = new MercTicketManager();
}
}

View File

@@ -1,97 +0,0 @@
/*
* 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.instancemanager;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExPCCafePointInfo;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.util.Rnd;
public final class PcCafePointsManager
{
public PcCafePointsManager()
{
}
public void givePcCafePoint(L2PcInstance player, long exp)
{
if (!Config.PC_BANG_ENABLED || player.isInsideZone(ZoneId.PEACE) || player.isInsideZone(ZoneId.PVP) || player.isInsideZone(ZoneId.SIEGE) || (player.isOnlineInt() == 0) || player.isJailed())
{
return;
}
if (player.getPcBangPoints() >= Config.PC_BANG_MAX_POINTS)
{
final SystemMessage message = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PC_POINTS);
player.sendPacket(message);
return;
}
int points = (int) (exp * 0.0001 * Config.PC_BANG_POINT_RATE);
if (Config.PC_BANG_RANDOM_POINT)
{
points = Rnd.get(points / 2, points);
}
if ((points == 0) && (exp > 0) && Config.PC_BANG_REWARD_LOW_EXP_KILLS && (Rnd.get(100) < Config.PC_BANG_LOW_EXP_KILLS_CHANCE))
{
points = 1; // minimum points
}
if (points <= 0)
{
return;
}
SystemMessage message = null;
if (Config.PC_BANG_ENABLE_DOUBLE_POINTS && (Rnd.get(100) < Config.PC_BANG_DOUBLE_POINTS_CHANCE))
{
points *= 2;
message = SystemMessage.getSystemMessage(SystemMessageId.DOUBLE_POINTS_YOU_EARNED_S1_PC_POINT_S);
}
else
{
message = SystemMessage.getSystemMessage(SystemMessageId.YOU_EARNED_S1_PC_POINT_S);
}
if ((player.getPcBangPoints() + points) > Config.PC_BANG_MAX_POINTS)
{
points = Config.PC_BANG_MAX_POINTS - player.getPcBangPoints();
}
message.addLong(points);
player.sendPacket(message);
player.setPcBangPoints(player.getPcBangPoints() + points);
player.sendPacket(new ExPCCafePointInfo(player.getPcBangPoints(), points, 1));
}
/**
* Gets the single instance of {@code PcCafePointsManager}.
* @return single instance of {@code PcCafePointsManager}
*/
public static PcCafePointsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PcCafePointsManager _instance = new PcCafePointsManager();
}
}

View File

@@ -1,454 +1,471 @@
/*
* 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.instancemanager;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.data.xml.impl.AdminData;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.enums.PetitionState;
import com.l2jmobius.gameserver.model.Petition;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.util.StringUtil;
/**
* Petition Manager
* @author Tempy
*/
public final class PetitionManager
{
protected static final Logger _log = Logger.getLogger(PetitionManager.class.getName());
private final Map<Integer, Petition> _pendingPetitions;
private final Map<Integer, Petition> _completedPetitions;
protected PetitionManager()
{
_pendingPetitions = new HashMap<>();
_completedPetitions = new HashMap<>();
}
public void clearCompletedPetitions()
{
final int numPetitions = getPendingPetitionCount();
getCompletedPetitions().clear();
_log.info(getClass().getSimpleName() + ": Completed petition data cleared. " + numPetitions + " petition(s) removed.");
}
public void clearPendingPetitions()
{
final int numPetitions = getPendingPetitionCount();
getPendingPetitions().clear();
_log.info(getClass().getSimpleName() + ": Pending petition queue cleared. " + numPetitions + " petition(s) removed.");
}
public boolean acceptPetition(L2PcInstance respondingAdmin, int petitionId)
{
if (!isValidPetition(petitionId))
{
return false;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
if (currPetition.getResponder() != null)
{
return false;
}
currPetition.setResponder(respondingAdmin);
currPetition.setState(PetitionState.IN_PROCESS);
// Petition application accepted. (Send to Petitioner)
currPetition.sendPetitionerPacket(SystemMessage.getSystemMessage(SystemMessageId.PETITION_APPLICATION_ACCEPTED));
// Petition application accepted. Reciept No. is <ID>
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PETITION_APPLICATION_HAS_BEEN_ACCEPTED_NRECEIPT_NO_IS_S1);
sm.addInt(currPetition.getId());
currPetition.sendResponderPacket(sm);
// Petition consultation with <Player> underway.
sm = SystemMessage.getSystemMessage(SystemMessageId.STARTING_PETITION_CONSULTATION_WITH_C1);
sm.addString(currPetition.getPetitioner().getName());
currPetition.sendResponderPacket(sm);
// Set responder name on petitioner instance
currPetition.getPetitioner().setLastPetitionGmName(currPetition.getResponder().getName());
return true;
}
public boolean cancelActivePetition(L2PcInstance player)
{
for (Petition currPetition : getPendingPetitions().values())
{
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
return currPetition.endPetitionConsultation(PetitionState.PETITIONER_CANCEL);
}
if ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId()))
{
return currPetition.endPetitionConsultation(PetitionState.RESPONDER_CANCEL);
}
}
return false;
}
public void checkPetitionMessages(L2PcInstance petitioner)
{
if (petitioner != null)
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == petitioner.getObjectId()))
{
for (CreatureSay logMessage : currPetition.getLogMessages())
{
petitioner.sendPacket(logMessage);
}
return;
}
}
}
}
public boolean endActivePetition(L2PcInstance player)
{
if (!player.isGM())
{
return false;
}
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId()))
{
return currPetition.endPetitionConsultation(PetitionState.COMPLETED);
}
}
return false;
}
public Map<Integer, Petition> getCompletedPetitions()
{
return _completedPetitions;
}
public Map<Integer, Petition> getPendingPetitions()
{
return _pendingPetitions;
}
public int getPendingPetitionCount()
{
return getPendingPetitions().size();
}
public int getPlayerTotalPetitionCount(L2PcInstance player)
{
if (player == null)
{
return 0;
}
int petitionCount = 0;
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
petitionCount++;
}
}
for (Petition currPetition : getCompletedPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
petitionCount++;
}
}
return petitionCount;
}
public boolean isPetitionInProcess()
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if (currPetition.getState() == PetitionState.IN_PROCESS)
{
return true;
}
}
return false;
}
public boolean isPetitionInProcess(int petitionId)
{
return isValidPetition(petitionId) && (getPendingPetitions().get(petitionId).getState() == PetitionState.IN_PROCESS);
}
public boolean isPlayerInConsultation(L2PcInstance player)
{
if (player != null)
{
for (Petition currPetition : getPendingPetitions().values())
{
if ((currPetition == null) || (currPetition.getState() != PetitionState.IN_PROCESS))
{
continue;
}
if (((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId())) || ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId())))
{
return true;
}
}
}
return false;
}
public boolean isPetitioningAllowed()
{
return Config.PETITIONING_ALLOWED;
}
public boolean isPlayerPetitionPending(L2PcInstance petitioner)
{
if (petitioner != null)
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == petitioner.getObjectId()))
{
return true;
}
}
}
return false;
}
private boolean isValidPetition(int petitionId)
{
return getPendingPetitions().containsKey(petitionId);
}
public boolean rejectPetition(L2PcInstance respondingAdmin, int petitionId)
{
if (!isValidPetition(petitionId))
{
return false;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
if (currPetition.getResponder() != null)
{
return false;
}
currPetition.setResponder(respondingAdmin);
return currPetition.endPetitionConsultation(PetitionState.RESPONDER_REJECT);
}
public boolean sendActivePetitionMessage(L2PcInstance player, String messageText)
{
// if (!isPlayerInConsultation(player))
// return false;
CreatureSay cs;
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
cs = new CreatureSay(player.getObjectId(), ChatType.PETITION_PLAYER, player.getName(), messageText);
currPetition.addLogMessage(cs);
currPetition.sendResponderPacket(cs);
currPetition.sendPetitionerPacket(cs);
return true;
}
if ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId()))
{
cs = new CreatureSay(player.getObjectId(), ChatType.PETITION_GM, player.getName(), messageText);
currPetition.addLogMessage(cs);
currPetition.sendResponderPacket(cs);
currPetition.sendPetitionerPacket(cs);
return true;
}
}
return false;
}
public void sendPendingPetitionList(L2PcInstance activeChar)
{
final StringBuilder htmlContent = StringUtil.startAppend(600 + (getPendingPetitionCount() * 300), "<html><body><center><table width=270><tr><td width=45><button value=\"Main\" action=\"bypass -h admin_admin\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td width=180><center>Petition Menu</center></td><td width=45><button value=\"Back\" action=\"bypass -h admin_admin7\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br><table width=\"270\"><tr><td><table width=\"270\"><tr><td><button value=\"Reset\" action=\"bypass -h admin_reset_petitions\" width=\"80\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td align=right><button value=\"Refresh\" action=\"bypass -h admin_view_petitions\" width=\"80\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br></td></tr>");
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
if (getPendingPetitionCount() == 0)
{
htmlContent.append("<tr><td>There are no currently pending petitions.</td></tr>");
}
else
{
htmlContent.append("<tr><td><font color=\"LEVEL\">Current Petitions:</font><br></td></tr>");
}
boolean color = true;
int petcount = 0;
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
StringUtil.append(htmlContent, "<tr><td width=\"270\"><table width=\"270\" cellpadding=\"2\" bgcolor=", color ? "131210" : "444444", "><tr><td width=\"130\">", dateFormat.format(new Date(currPetition.getSubmitTime())));
StringUtil.append(htmlContent, "</td><td width=\"140\" align=right><font color=\"", currPetition.getPetitioner().isOnline() ? "00FF00" : "999999", "\">", currPetition.getPetitioner().getName(), "</font></td></tr>");
StringUtil.append(htmlContent, "<tr><td width=\"130\">");
if (currPetition.getState() != PetitionState.IN_PROCESS)
{
StringUtil.append(htmlContent, "<table width=\"130\" cellpadding=\"2\"><tr><td><button value=\"View\" action=\"bypass -h admin_view_petition ", String.valueOf(currPetition.getId()), "\" width=\"50\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td><button value=\"Reject\" action=\"bypass -h admin_reject_petition ", String.valueOf(currPetition.getId()), "\" width=\"50\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>");
}
else
{
htmlContent.append("<font color=\"" + (currPetition.getResponder().isOnline() ? "00FF00" : "999999") + "\">" + currPetition.getResponder().getName() + "</font>");
}
StringUtil.append(htmlContent, "</td>", currPetition.getTypeAsString(), "<td width=\"140\" align=right>", currPetition.getTypeAsString(), "</td></tr></table></td></tr>");
color = !color;
petcount++;
if (petcount > 10)
{
htmlContent.append("<tr><td><font color=\"LEVEL\">There is more pending petition...</font><br></td></tr>");
break;
}
}
htmlContent.append("</table></center></body></html>");
final NpcHtmlMessage htmlMsg = new NpcHtmlMessage();
htmlMsg.setHtml(htmlContent.toString());
activeChar.sendPacket(htmlMsg);
}
public int submitPetition(L2PcInstance petitioner, String petitionText, int petitionType)
{
// Create a new petition instance and add it to the list of pending petitions.
final Petition newPetition = new Petition(petitioner, petitionText, petitionType);
final int newPetitionId = newPetition.getId();
getPendingPetitions().put(newPetitionId, newPetition);
// Notify all GMs that a new petition has been submitted.
final String msgContent = petitioner.getName() + " has submitted a new petition."; // (ID: " + newPetitionId + ").";
AdminData.getInstance().broadcastToGMs(new CreatureSay(petitioner.getObjectId(), ChatType.HERO_VOICE, "Petition System", msgContent));
return newPetitionId;
}
public void viewPetition(L2PcInstance activeChar, int petitionId)
{
if (!activeChar.isGM() || !isValidPetition(petitionId))
{
return;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
final NpcHtmlMessage html = new NpcHtmlMessage();
html.setFile(activeChar.getHtmlPrefix(), "html/admin/petition.htm");
html.replace("%petition%", String.valueOf(currPetition.getId()));
html.replace("%time%", dateFormat.format(new Date(currPetition.getSubmitTime())));
html.replace("%type%", currPetition.getTypeAsString());
html.replace("%petitioner%", currPetition.getPetitioner().getName());
html.replace("%online%", currPetition.getPetitioner().isOnline() ? "00FF00" : "999999");
html.replace("%text%", currPetition.getContent());
activeChar.sendPacket(html);
}
/**
* Gets the single instance of {@code PetitionManager}.
* @return single instance of {@code PetitionManager}
*/
public static PetitionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PetitionManager _instance = new PetitionManager();
}
}
/*
* 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.instancemanager;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.data.xml.impl.AdminData;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.enums.PetitionState;
import com.l2jmobius.gameserver.model.Petition;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* Petition Manager
* @author Tempy
*/
public final class PetitionManager
{
protected static final Logger _log = Logger.getLogger(PetitionManager.class.getName());
private final Map<Integer, Petition> _pendingPetitions;
private final Map<Integer, Petition> _completedPetitions;
protected PetitionManager()
{
_pendingPetitions = new HashMap<>();
_completedPetitions = new HashMap<>();
}
public void clearCompletedPetitions()
{
final int numPetitions = getPendingPetitionCount();
getCompletedPetitions().clear();
_log.info(getClass().getSimpleName() + ": Completed petition data cleared. " + numPetitions + " petition(s) removed.");
}
public void clearPendingPetitions()
{
final int numPetitions = getPendingPetitionCount();
getPendingPetitions().clear();
_log.info(getClass().getSimpleName() + ": Pending petition queue cleared. " + numPetitions + " petition(s) removed.");
}
public boolean acceptPetition(L2PcInstance respondingAdmin, int petitionId)
{
if (!isValidPetition(petitionId))
{
return false;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
if (currPetition.getResponder() != null)
{
return false;
}
currPetition.setResponder(respondingAdmin);
currPetition.setState(PetitionState.IN_PROCESS);
// Petition application accepted. (Send to Petitioner)
currPetition.sendPetitionerPacket(SystemMessage.getSystemMessage(SystemMessageId.PETITION_APPLICATION_ACCEPTED));
// Petition application accepted. Reciept No. is <ID>
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOUR_PETITION_APPLICATION_HAS_BEEN_ACCEPTED_NRECEIPT_NO_IS_S1);
sm.addInt(currPetition.getId());
currPetition.sendResponderPacket(sm);
// Petition consultation with <Player> underway.
sm = SystemMessage.getSystemMessage(SystemMessageId.STARTING_PETITION_CONSULTATION_WITH_C1);
sm.addString(currPetition.getPetitioner().getName());
currPetition.sendResponderPacket(sm);
// Set responder name on petitioner instance
currPetition.getPetitioner().setLastPetitionGmName(currPetition.getResponder().getName());
return true;
}
public boolean cancelActivePetition(L2PcInstance player)
{
for (Petition currPetition : getPendingPetitions().values())
{
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
return (currPetition.endPetitionConsultation(PetitionState.PETITIONER_CANCEL));
}
if ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId()))
{
return (currPetition.endPetitionConsultation(PetitionState.RESPONDER_CANCEL));
}
}
return false;
}
public void checkPetitionMessages(L2PcInstance petitioner)
{
if (petitioner != null)
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == petitioner.getObjectId()))
{
for (CreatureSay logMessage : currPetition.getLogMessages())
{
petitioner.sendPacket(logMessage);
}
return;
}
}
}
}
public boolean endActivePetition(L2PcInstance player)
{
if (!player.isGM())
{
return false;
}
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId()))
{
return (currPetition.endPetitionConsultation(PetitionState.COMPLETED));
}
}
return false;
}
public Map<Integer, Petition> getCompletedPetitions()
{
return _completedPetitions;
}
public Map<Integer, Petition> getPendingPetitions()
{
return _pendingPetitions;
}
public int getPendingPetitionCount()
{
return getPendingPetitions().size();
}
public int getPlayerTotalPetitionCount(L2PcInstance player)
{
if (player == null)
{
return 0;
}
int petitionCount = 0;
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
petitionCount++;
}
}
for (Petition currPetition : getCompletedPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
petitionCount++;
}
}
return petitionCount;
}
public boolean isPetitionInProcess()
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if (currPetition.getState() == PetitionState.IN_PROCESS)
{
return true;
}
}
return false;
}
public boolean isPetitionInProcess(int petitionId)
{
if (!isValidPetition(petitionId))
{
return false;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
return (currPetition.getState() == PetitionState.IN_PROCESS);
}
public boolean isPlayerInConsultation(L2PcInstance player)
{
if (player != null)
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if (currPetition.getState() != PetitionState.IN_PROCESS)
{
continue;
}
if (((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId())) || ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId())))
{
return true;
}
}
}
return false;
}
public boolean isPetitioningAllowed()
{
return Config.PETITIONING_ALLOWED;
}
public boolean isPlayerPetitionPending(L2PcInstance petitioner)
{
if (petitioner != null)
{
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == petitioner.getObjectId()))
{
return true;
}
}
}
return false;
}
private boolean isValidPetition(int petitionId)
{
return getPendingPetitions().containsKey(petitionId);
}
public boolean rejectPetition(L2PcInstance respondingAdmin, int petitionId)
{
if (!isValidPetition(petitionId))
{
return false;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
if (currPetition.getResponder() != null)
{
return false;
}
currPetition.setResponder(respondingAdmin);
return (currPetition.endPetitionConsultation(PetitionState.RESPONDER_REJECT));
}
public boolean sendActivePetitionMessage(L2PcInstance player, String messageText)
{
// if (!isPlayerInConsultation(player))
// return false;
CreatureSay cs;
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
if ((currPetition.getPetitioner() != null) && (currPetition.getPetitioner().getObjectId() == player.getObjectId()))
{
cs = new CreatureSay(player.getObjectId(), ChatType.PETITION_PLAYER, player.getName(), messageText);
currPetition.addLogMessage(cs);
currPetition.sendResponderPacket(cs);
currPetition.sendPetitionerPacket(cs);
return true;
}
if ((currPetition.getResponder() != null) && (currPetition.getResponder().getObjectId() == player.getObjectId()))
{
cs = new CreatureSay(player.getObjectId(), ChatType.PETITION_GM, player.getName(), messageText);
currPetition.addLogMessage(cs);
currPetition.sendResponderPacket(cs);
currPetition.sendPetitionerPacket(cs);
return true;
}
}
return false;
}
public void sendPendingPetitionList(L2PcInstance activeChar)
{
final StringBuilder htmlContent = new StringBuilder(600 + (getPendingPetitionCount() * 300));
htmlContent.append("<html><body><center><table width=270><tr><td width=45><button value=\"Main\" action=\"bypass -h admin_admin\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td width=180><center>Petition Menu</center></td><td width=45><button value=\"Back\" action=\"bypass -h admin_admin7\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br><table width=\"270\"><tr><td><table width=\"270\"><tr><td><button value=\"Reset\" action=\"bypass -h admin_reset_petitions\" width=\"80\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td align=right><button value=\"Refresh\" action=\"bypass -h admin_view_petitions\" width=\"80\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br></td></tr>");
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
if (getPendingPetitionCount() == 0)
{
htmlContent.append("<tr><td>There are no currently pending petitions.</td></tr>");
}
else
{
htmlContent.append("<tr><td><font color=\"LEVEL\">Current Petitions:</font><br></td></tr>");
}
boolean color = true;
int petcount = 0;
for (Petition currPetition : getPendingPetitions().values())
{
if (currPetition == null)
{
continue;
}
htmlContent.append("<tr><td width=\"270\"><table width=\"270\" cellpadding=\"2\" bgcolor=" + (color ? "131210" : "444444") + "><tr><td width=\"130\">" + dateFormat.format(new Date(currPetition.getSubmitTime())));
htmlContent.append("</td><td width=\"140\" align=right><font color=\"" + (currPetition.getPetitioner().isOnline() ? "00FF00" : "999999") + "\">" + currPetition.getPetitioner().getName() + "</font></td></tr>");
htmlContent.append("<tr><td width=\"130\">");
if (currPetition.getState() != PetitionState.IN_PROCESS)
{
htmlContent.append("<table width=\"130\" cellpadding=\"2\"><tr><td><button value=\"View\" action=\"bypass -h admin_view_petition " + currPetition.getId() + "\" width=\"50\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td><td><button value=\"Reject\" action=\"bypass -h admin_reject_petition " + currPetition.getId() + "\" width=\"50\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>");
}
else
{
htmlContent.append("<font color=\"" + (currPetition.getResponder().isOnline() ? "00FF00" : "999999") + "\">" + currPetition.getResponder().getName() + "</font>");
}
htmlContent.append("</td>" + currPetition.getTypeAsString() + "<td width=\"140\" align=right>" + currPetition.getTypeAsString() + "</td></tr></table></td></tr>");
color = !color;
petcount++;
if (petcount > 10)
{
htmlContent.append("<tr><td><font color=\"LEVEL\">There is more pending petition...</font><br></td></tr>");
break;
}
}
htmlContent.append("</table></center></body></html>");
final NpcHtmlMessage htmlMsg = new NpcHtmlMessage();
htmlMsg.setHtml(htmlContent.toString());
activeChar.sendPacket(htmlMsg);
}
public int submitPetition(L2PcInstance petitioner, String petitionText, int petitionType)
{
// Create a new petition instance and add it to the list of pending petitions.
final Petition newPetition = new Petition(petitioner, petitionText, petitionType);
final int newPetitionId = newPetition.getId();
getPendingPetitions().put(newPetitionId, newPetition);
// Notify all GMs that a new petition has been submitted.
final String msgContent = petitioner.getName() + " has submitted a new petition."; // (ID: " + newPetitionId + ").";
AdminData.getInstance().broadcastToGMs(new CreatureSay(petitioner.getObjectId(), ChatType.HERO_VOICE, "Petition System", msgContent));
return newPetitionId;
}
public void viewPetition(L2PcInstance activeChar, int petitionId)
{
if (!activeChar.isGM())
{
return;
}
if (!isValidPetition(petitionId))
{
return;
}
final Petition currPetition = getPendingPetitions().get(petitionId);
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
final NpcHtmlMessage html = new NpcHtmlMessage();
html.setFile(activeChar.getHtmlPrefix(), "data/html/admin/petition.htm");
html.replace("%petition%", String.valueOf(currPetition.getId()));
html.replace("%time%", dateFormat.format(new Date(currPetition.getSubmitTime())));
html.replace("%type%", currPetition.getTypeAsString());
html.replace("%petitioner%", currPetition.getPetitioner().getName());
html.replace("%online%", (currPetition.getPetitioner().isOnline() ? "00FF00" : "999999"));
html.replace("%text%", currPetition.getContent());
activeChar.sendPacket(html);
}
/**
* Gets the single instance of {@code PetitionManager}.
* @return single instance of {@code PetitionManager}
*/
public static PetitionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PetitionManager _instance = new PetitionManager();
}
}

View File

@@ -1,135 +1,147 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.holders.PunishmentHolder;
import com.l2jmobius.gameserver.model.punishment.PunishmentAffect;
import com.l2jmobius.gameserver.model.punishment.PunishmentTask;
import com.l2jmobius.gameserver.model.punishment.PunishmentType;
/**
* @author UnAfraid
*/
public final class PunishmentManager
{
private static final Logger _log = Logger.getLogger(PunishmentManager.class.getName());
private final Map<PunishmentAffect, PunishmentHolder> _tasks = new ConcurrentHashMap<>();
protected PunishmentManager()
{
load();
}
private void load()
{
// Initiate task holders.
for (PunishmentAffect affect : PunishmentAffect.values())
{
_tasks.put(affect, new PunishmentHolder());
}
int initiated = 0;
int expired = 0;
// Load punishments.
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement st = con.createStatement();
ResultSet rset = st.executeQuery("SELECT * FROM punishments"))
{
while (rset.next())
{
final int id = rset.getInt("id");
final String key = rset.getString("key");
final PunishmentAffect affect = PunishmentAffect.getByName(rset.getString("affect"));
final PunishmentType type = PunishmentType.getByName(rset.getString("type"));
final long expirationTime = rset.getLong("expiration");
if ((type != null) && (affect != null))
{
if ((expirationTime > 0) && (System.currentTimeMillis() > expirationTime)) // expired task.
{
expired++;
}
else
{
initiated++;
_tasks.get(affect).addPunishment(new PunishmentTask(id, key, affect, type, expirationTime, rset.getString("reason"), rset.getString("punishedBy"), true));
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while loading punishments: ", e);
}
_log.log(Level.INFO, getClass().getSimpleName() + ": Loaded " + initiated + " active and " + expired + " expired punishments.");
}
public void startPunishment(PunishmentTask task)
{
_tasks.get(task.getAffect()).addPunishment(task);
}
public void stopPunishment(Object key, PunishmentAffect affect, PunishmentType type)
{
final PunishmentTask task = getPunishment(key, affect, type);
if (task != null)
{
_tasks.get(affect).stopPunishment(task);
}
}
public boolean hasPunishment(Object key, PunishmentAffect affect, PunishmentType type)
{
return _tasks.get(affect).hasPunishment(String.valueOf(key), type);
}
public long getPunishmentExpiration(Object key, PunishmentAffect affect, PunishmentType type)
{
final PunishmentTask p = getPunishment(key, affect, type);
return p != null ? p.getExpirationTime() : 0;
}
private PunishmentTask getPunishment(Object key, PunishmentAffect affect, PunishmentType type)
{
return _tasks.get(affect).getPunishment(String.valueOf(key), type);
}
/**
* Gets the single instance of {@code PunishmentManager}.
* @return single instance of {@code PunishmentManager}
*/
public static PunishmentManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PunishmentManager _instance = new PunishmentManager();
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.holders.PunishmentHolder;
import com.l2jmobius.gameserver.model.punishment.PunishmentAffect;
import com.l2jmobius.gameserver.model.punishment.PunishmentTask;
import com.l2jmobius.gameserver.model.punishment.PunishmentType;
/**
* @author UnAfraid
*/
public final class PunishmentManager
{
private static final Logger LOGGER = Logger.getLogger(PunishmentManager.class.getName());
private final Map<PunishmentAffect, PunishmentHolder> _tasks = new ConcurrentHashMap<>();
protected PunishmentManager()
{
load();
}
private void load()
{
// Initiate task holders.
for (PunishmentAffect affect : PunishmentAffect.values())
{
_tasks.put(affect, new PunishmentHolder());
}
int initiated = 0;
int expired = 0;
// Load punishments.
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement st = con.createStatement();
ResultSet rset = st.executeQuery("SELECT * FROM punishments"))
{
while (rset.next())
{
final int id = rset.getInt("id");
final String key = rset.getString("key");
final PunishmentAffect affect = PunishmentAffect.getByName(rset.getString("affect"));
final PunishmentType type = PunishmentType.getByName(rset.getString("type"));
final long expirationTime = rset.getLong("expiration");
final String reason = rset.getString("reason");
final String punishedBy = rset.getString("punishedBy");
if ((type != null) && (affect != null))
{
if ((expirationTime > 0) && (System.currentTimeMillis() > expirationTime)) // expired task.
{
expired++;
}
else
{
initiated++;
_tasks.get(affect).addPunishment(new PunishmentTask(id, key, affect, type, expirationTime, reason, punishedBy, true));
}
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while loading punishments: ", e);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + initiated + " active and " + expired + " expired punishments.");
}
public void startPunishment(PunishmentTask task)
{
_tasks.get(task.getAffect()).addPunishment(task);
}
public void stopPunishment(PunishmentAffect affect, PunishmentType type)
{
final PunishmentHolder holder = _tasks.get(affect);
if (holder != null)
{
holder.stopPunishment(type);
}
}
public void stopPunishment(Object key, PunishmentAffect affect, PunishmentType type)
{
final PunishmentTask task = getPunishment(key, affect, type);
if (task != null)
{
_tasks.get(affect).stopPunishment(task);
}
}
public boolean hasPunishment(Object key, PunishmentAffect affect, PunishmentType type)
{
final PunishmentHolder holder = _tasks.get(affect);
return holder.hasPunishment(String.valueOf(key), type);
}
public long getPunishmentExpiration(Object key, PunishmentAffect affect, PunishmentType type)
{
final PunishmentTask p = getPunishment(key, affect, type);
return p != null ? p.getExpirationTime() : 0;
}
private PunishmentTask getPunishment(Object key, PunishmentAffect affect, PunishmentType type)
{
return _tasks.get(affect).getPunishment(String.valueOf(key), type);
}
/**
* Gets the single instance of {@code PunishmentManager}.
* @return single instance of {@code PunishmentManager}
*/
public static PunishmentManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PunishmentManager _instance = new PunishmentManager();
}
}

View File

@@ -1,274 +1,276 @@
/*
* 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.instancemanager;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.scripting.L2ScriptEngineManager;
import com.l2jmobius.gameserver.scripting.ScriptManager;
import com.l2jmobius.util.Util;
/**
* Quests and scripts manager.
* @author Zoey76
*/
public final class QuestManager extends ScriptManager<Quest>
{
protected static final Logger _log = Logger.getLogger(QuestManager.class.getName());
/** Map containing all the quests. */
private final Map<String, Quest> _quests = new ConcurrentHashMap<>();
/** Map containing all the scripts. */
private final Map<String, Quest> _scripts = new ConcurrentHashMap<>();
protected QuestManager()
{
// Prevent initialization.
}
public boolean reload(String questFolder)
{
final Quest q = getQuest(questFolder);
return (q != null) && q.reload();
}
/**
* Reloads a the quest by ID.
* @param questId the ID of the quest to be reloaded
* @return {@code true} if reload was successful, {@code false} otherwise
*/
public boolean reload(int questId)
{
final Quest q = getQuest(questId);
return (q != null) && q.reload();
}
/**
* Reload all quests and scripts.<br>
* Unload all quests and scripts and load scripts.cfg.
*/
public void reloadAllScripts()
{
_log.info(getClass().getSimpleName() + ": Reloading all server scripts.");
// Unload quests.
for (Quest quest : _quests.values())
{
if (quest != null)
{
quest.unload(false);
}
}
_quests.clear();
// Unload scripts.
for (Quest script : _scripts.values())
{
if (script != null)
{
script.unload(false);
}
}
_scripts.clear();
try
{
L2ScriptEngineManager.getInstance().executeScriptList(new File(Config.DATAPACK_ROOT, "scripts.cfg"));
}
catch (IOException e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading scripts.cfg, no script going to be loaded!", e);
}
QuestManager.getInstance().report();
}
/**
* Logs how many quests and scripts are loaded.
*/
public void report()
{
_log.info(getClass().getSimpleName() + ": Loaded: " + _quests.size() + " quests.");
_log.info(getClass().getSimpleName() + ": Loaded: " + _scripts.size() + " scripts.");
}
/**
* Calls {@link Quest#saveGlobalData()} in all quests and scripts.
*/
public void save()
{
// Save quests.
for (Quest quest : _quests.values())
{
quest.saveGlobalData();
}
// Save scripts.
for (Quest script : _scripts.values())
{
script.saveGlobalData();
}
}
/**
* Gets a quest by name.<br>
* <i>For backwards compatibility, verifies scripts with the given name if the quest is not found.</i>
* @param name the quest name
* @return the quest
*/
public Quest getQuest(String name)
{
return _quests.containsKey(name) ? _quests.get(name) : _scripts.get(name);
}
/**
* Gets a quest by ID.
* @param questId the ID of the quest to get
* @return if found, the quest, {@code null} otherwise
*/
public Quest getQuest(int questId)
{
for (Quest q : _quests.values())
{
if (q.getId() == questId)
{
return q;
}
}
return null;
}
/**
* Adds a new quest.
* @param quest the quest to be added
*/
public void addQuest(Quest quest)
{
if (quest == null)
{
throw new IllegalArgumentException("Quest argument cannot be null");
}
// FIXME: unloading the old quest at this point is a tad too late.
// the new quest has already initialized itself and read the data, starting
// an unpredictable number of tasks with that data. The old quest will now
// save data which will never be read.
// However, requesting the newQuest to re-read the data is not necessarily a
// good option, since the newQuest may have already started timers, spawned NPCs
// or taken any other action which it might re-take by re-reading the data.
// the current solution properly closes the running tasks of the old quest but
// ignores the data; perhaps the least of all evils...
final Quest old = _quests.put(quest.getName(), quest);
if (old != null)
{
old.unload();
_log.info(getClass().getSimpleName() + ": Replaced quest " + old.getName() + " (" + old.getId() + ") with a new version!");
}
if (Config.ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS)
{
_log.info("Loaded quest " + Util.splitWords(quest.getName().contains("_") ? quest.getName().substring(quest.getName().indexOf('_') + 1) : quest.getName()) + ".");
}
}
/**
* Removes a script.
* @param script the script to remove
* @return {@code true} if the script was removed, {@code false} otherwise
*/
public boolean removeScript(Quest script)
{
if (_quests.containsKey(script.getName()))
{
_quests.remove(script.getName());
return true;
}
if (_scripts.containsKey(script.getName()))
{
_scripts.remove(script.getName());
return true;
}
return false;
}
public Map<String, Quest> getQuests()
{
return _quests;
}
@Override
public boolean unload(Quest ms)
{
ms.saveGlobalData();
return removeScript(ms);
}
@Override
public String getScriptManagerName()
{
return getClass().getSimpleName();
}
/**
* Gets all the registered scripts.
* @return all the scripts
*/
@Override
public Map<String, Quest> getScripts()
{
return _scripts;
}
/**
* Adds a script.
* @param script the script to be added
*/
public void addScript(Quest script)
{
final Quest old = _scripts.put(script.getClass().getSimpleName(), script);
if (old != null)
{
old.unload();
_log.info(getClass().getSimpleName() + ": Replaced script " + old.getName() + " with a new version!");
}
if (Config.ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS)
{
_log.info("Loaded script " + Util.splitWords(script.getClass().getSimpleName()) + ".");
}
}
/**
* Gets the single instance of {@code QuestManager}.
* @return single instance of {@code QuestManager}
*/
public static QuestManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final QuestManager _instance = new QuestManager();
}
}
/*
* 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.instancemanager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.gameserver.model.quest.Quest;
import com.l2jmobius.gameserver.scripting.ScriptEngineManager;
/**
* Quests and scripts manager.
* @author Zoey76
*/
public final class QuestManager
{
protected static final Logger LOGGER = Logger.getLogger(QuestManager.class.getName());
/** Map containing all the quests. */
private final Map<String, Quest> _quests = new ConcurrentHashMap<>();
/** Map containing all the scripts. */
private final Map<String, Quest> _scripts = new ConcurrentHashMap<>();
protected QuestManager()
{
}
public boolean reload(String questFolder)
{
final Quest q = getQuest(questFolder);
if (q == null)
{
return false;
}
return q.reload();
}
/**
* Reloads a the quest by ID.
* @param questId the ID of the quest to be reloaded
* @return {@code true} if reload was successful, {@code false} otherwise
*/
public boolean reload(int questId)
{
final Quest q = getQuest(questId);
if (q == null)
{
return false;
}
return q.reload();
}
/**
* Reload all quests and scripts.<br>
* Unload all quests and scripts and load scripts.cfg.
*/
public void reloadAllScripts()
{
LOGGER.info("Reloading all server scripts.");
// Unload quests.
for (Quest quest : _quests.values())
{
if (quest != null)
{
quest.unload(false);
}
}
_quests.clear();
// Unload scripts.
for (Quest script : _scripts.values())
{
if (script != null)
{
script.unload(false);
}
}
_scripts.clear();
try
{
ScriptEngineManager.getInstance().executeScriptList();
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Failed loading scripts.cfg, no script going to be loaded!", e);
}
QuestManager.getInstance().report();
}
/**
* Logs how many quests and scripts are loaded.
*/
public void report()
{
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _quests.size() + " quests.");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _scripts.size() + " scripts.");
}
/**
* Calls {@link Quest#onSave()} in all quests and scripts.
*/
public void save()
{
// Save quests.
for (Quest quest : _quests.values())
{
quest.onSave();
}
// Save scripts.
for (Quest script : _scripts.values())
{
script.onSave();
}
}
/**
* Gets a quest by name.<br>
* <i>For backwards compatibility, verifies scripts with the given name if the quest is not found.</i>
* @param name the quest name
* @return the quest
*/
public Quest getQuest(String name)
{
if (_quests.containsKey(name))
{
return _quests.get(name);
}
return _scripts.get(name);
}
/**
* Gets a quest by ID.
* @param questId the ID of the quest to get
* @return if found, the quest, {@code null} otherwise
*/
public Quest getQuest(int questId)
{
for (Quest q : _quests.values())
{
if (q.getId() == questId)
{
return q;
}
}
return null;
}
/**
* Adds a new quest.
* @param quest the quest to be added
*/
public void addQuest(Quest quest)
{
if (quest == null)
{
throw new IllegalArgumentException("Quest argument cannot be null");
}
// FIXME: unloading the old quest at this point is a tad too late.
// the new quest has already initialized itself and read the data, starting
// an unpredictable number of tasks with that data. The old quest will now
// save data which will never be read.
// However, requesting the newQuest to re-read the data is not necessarily a
// good option, since the newQuest may have already started timers, spawned NPCs
// or taken any other action which it might re-take by re-reading the data.
// the current solution properly closes the running tasks of the old quest but
// ignores the data; perhaps the least of all evils...
final Quest old = _quests.put(quest.getName(), quest);
if (old != null)
{
old.unload();
LOGGER.info("Replaced quest " + old.getName() + " (" + old.getId() + ") with a new version!");
}
if (Config.ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS)
{
final String questName = quest.getName().contains("_") ? quest.getName().substring(quest.getName().indexOf('_') + 1) : quest.getName();
LOGGER.info("Loaded quest " + CommonUtil.splitWords(questName) + ".");
}
}
/**
* Removes a script.
* @param script the script to remove
* @return {@code true} if the script was removed, {@code false} otherwise
*/
public boolean removeScript(Quest script)
{
if (_quests.containsKey(script.getName()))
{
_quests.remove(script.getName());
return true;
}
else if (_scripts.containsKey(script.getName()))
{
_scripts.remove(script.getName());
return true;
}
return false;
}
public Map<String, Quest> getQuests()
{
return _quests;
}
public boolean unload(Quest ms)
{
ms.onSave();
return removeScript(ms);
}
/**
* Gets all the registered scripts.
* @return all the scripts
*/
public Map<String, Quest> getScripts()
{
return _scripts;
}
/**
* Adds a script.
* @param script the script to be added
*/
public void addScript(Quest script)
{
final Quest old = _scripts.put(script.getClass().getSimpleName(), script);
if (old != null)
{
old.unload();
LOGGER.info("Replaced script " + old.getName() + " with a new version!");
}
if (Config.ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS)
{
LOGGER.info("Loaded script " + CommonUtil.splitWords(script.getClass().getSimpleName()) + ".");
}
}
/**
* Gets the single instance of {@code QuestManager}.
* @return single instance of {@code QuestManager}
*/
public static QuestManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final QuestManager _instance = new QuestManager();
}
}

View File

@@ -1,545 +0,0 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.datatables.SpawnTable;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2RaidBossInstance;
import com.l2jmobius.util.Rnd;
/**
* Raid Boss spawn manager.
* @author godson
*/
public class RaidBossSpawnManager
{
private static final Logger _log = Logger.getLogger(RaidBossSpawnManager.class.getName());
protected static final Map<Integer, L2RaidBossInstance> _bosses = new ConcurrentHashMap<>();
protected static final Map<Integer, L2Spawn> _spawns = new ConcurrentHashMap<>();
protected static final Map<Integer, StatsSet> _storedInfo = new ConcurrentHashMap<>();
protected static final Map<Integer, ScheduledFuture<?>> _schedules = new ConcurrentHashMap<>();
public static enum StatusEnum
{
ALIVE,
DEAD,
UNDEFINED
}
/**
* Instantiates a new raid boss spawn manager.
*/
protected RaidBossSpawnManager()
{
load();
}
/**
* Load.
*/
public void load()
{
_bosses.clear();
_spawns.clear();
_storedInfo.clear();
_schedules.clear();
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM raidboss_spawnlist ORDER BY boss_id"))
{
while (rs.next())
{
final L2Spawn spawnDat = new L2Spawn(rs.getInt("boss_id"));
spawnDat.setX(rs.getInt("loc_x"));
spawnDat.setY(rs.getInt("loc_y"));
spawnDat.setZ(rs.getInt("loc_z"));
spawnDat.setAmount(rs.getInt("amount"));
spawnDat.setHeading(rs.getInt("heading"));
spawnDat.setRespawnDelay(rs.getInt("respawn_delay"), rs.getInt("respawn_random"));
addNewSpawn(spawnDat, rs.getLong("respawn_time"), rs.getDouble("currentHP"), rs.getDouble("currentMP"), false);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _bosses.size() + " Instances");
_log.info(getClass().getSimpleName() + ": Scheduled " + _schedules.size() + " Instances");
}
catch (SQLException e)
{
_log.warning(getClass().getSimpleName() + ": Couldnt load raidboss_spawnlist table");
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing RaidBossSpawnManager: " + e.getMessage(), e);
}
}
private static class SpawnSchedule implements Runnable
{
private static final Logger _log = Logger.getLogger(SpawnSchedule.class.getName());
private final int bossId;
/**
* Instantiates a new spawn schedule.
* @param npcId the npc id
*/
public SpawnSchedule(int npcId)
{
bossId = npcId;
}
@Override
public void run()
{
L2RaidBossInstance raidboss = null;
if (bossId == 25328)
{
raidboss = DayNightSpawnManager.getInstance().handleBoss(_spawns.get(bossId));
}
else
{
raidboss = (L2RaidBossInstance) _spawns.get(bossId).doSpawn();
}
if (raidboss != null)
{
raidboss.setRaidStatus(StatusEnum.ALIVE);
final StatsSet info = new StatsSet();
info.set("currentHP", raidboss.getCurrentHp());
info.set("currentMP", raidboss.getCurrentMp());
info.set("respawnTime", 0L);
_storedInfo.put(bossId, info);
_log.info(getClass().getSimpleName() + ": Spawning Raid Boss " + raidboss.getName());
_bosses.put(bossId, raidboss);
}
_schedules.remove(bossId);
}
}
/**
* Update status.
* @param boss the boss
* @param isBossDead the is boss dead
*/
public void updateStatus(L2RaidBossInstance boss, boolean isBossDead)
{
final StatsSet info = _storedInfo.get(boss.getId());
if (info == null)
{
return;
}
if (isBossDead)
{
boss.setRaidStatus(StatusEnum.DEAD);
final int respawnMinDelay = (int) (boss.getSpawn().getRespawnMinDelay() * Config.RAID_MIN_RESPAWN_MULTIPLIER);
final int respawnMaxDelay = (int) (boss.getSpawn().getRespawnMaxDelay() * Config.RAID_MAX_RESPAWN_MULTIPLIER);
final int respawnDelay = Rnd.get(respawnMinDelay, respawnMaxDelay);
final long respawnTime = Calendar.getInstance().getTimeInMillis() + respawnDelay;
info.set("currentHP", boss.getMaxHp());
info.set("currentMP", boss.getMaxMp());
info.set("respawnTime", respawnTime);
if (!_schedules.containsKey(boss.getId()) && ((respawnMinDelay > 0) || (respawnMaxDelay > 0)))
{
final Calendar time = Calendar.getInstance();
time.setTimeInMillis(respawnTime);
_log.info(getClass().getSimpleName() + ": Updated " + boss.getName() + " respawn time to " + time.getTime());
_schedules.put(boss.getId(), ThreadPoolManager.getInstance().scheduleGeneral(new SpawnSchedule(boss.getId()), respawnDelay));
updateDb();
}
}
else
{
boss.setRaidStatus(StatusEnum.ALIVE);
info.set("currentHP", boss.getCurrentHp());
info.set("currentMP", boss.getCurrentMp());
info.set("respawnTime", 0L);
}
_storedInfo.put(boss.getId(), info);
}
/**
* Adds the new spawn.
* @param spawnDat the spawn dat
* @param respawnTime the respawn time
* @param currentHP the current hp
* @param currentMP the current mp
* @param storeInDb the store in db
*/
public void addNewSpawn(L2Spawn spawnDat, long respawnTime, double currentHP, double currentMP, boolean storeInDb)
{
if ((spawnDat == null) || _spawns.containsKey(spawnDat.getId()))
{
return;
}
final int bossId = spawnDat.getId();
final long time = Calendar.getInstance().getTimeInMillis();
SpawnTable.getInstance().addNewSpawn(spawnDat, false);
if ((respawnTime == 0L) || (time > respawnTime))
{
final L2RaidBossInstance raidboss = bossId == 25328 ? DayNightSpawnManager.getInstance().handleBoss(spawnDat) : (L2RaidBossInstance) spawnDat.doSpawn();
if (raidboss != null)
{
raidboss.setCurrentHp(currentHP);
raidboss.setCurrentMp(currentMP);
raidboss.setRaidStatus(StatusEnum.ALIVE);
_bosses.put(bossId, raidboss);
final StatsSet info = new StatsSet();
info.set("currentHP", currentHP);
info.set("currentMP", currentMP);
info.set("respawnTime", 0L);
_storedInfo.put(bossId, info);
}
}
else
{
_schedules.put(bossId, ThreadPoolManager.getInstance().scheduleGeneral(new SpawnSchedule(bossId), respawnTime - Calendar.getInstance().getTimeInMillis()));
}
_spawns.put(bossId, spawnDat);
if (storeInDb)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO raidboss_spawnlist (boss_id,amount,loc_x,loc_y,loc_z,heading,respawn_time,currentHp,currentMp) VALUES(?,?,?,?,?,?,?,?,?)"))
{
ps.setInt(1, spawnDat.getId());
ps.setInt(2, spawnDat.getAmount());
ps.setInt(3, spawnDat.getX());
ps.setInt(4, spawnDat.getY());
ps.setInt(5, spawnDat.getZ());
ps.setInt(6, spawnDat.getHeading());
ps.setLong(7, respawnTime);
ps.setDouble(8, currentHP);
ps.setDouble(9, currentMP);
ps.execute();
}
catch (Exception e)
{
// problem with storing spawn
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not store raidboss #" + bossId + " in the DB:" + e.getMessage(), e);
}
}
}
/**
* Delete spawn.
* @param spawnDat the spawn dat
* @param updateDb the update db
*/
public void deleteSpawn(L2Spawn spawnDat, boolean updateDb)
{
if (spawnDat == null)
{
return;
}
final int bossId = spawnDat.getId();
if (!_spawns.containsKey(bossId))
{
return;
}
SpawnTable.getInstance().deleteSpawn(spawnDat, false);
_spawns.remove(bossId);
if (_bosses.containsKey(bossId))
{
_bosses.remove(bossId);
}
if (_schedules.containsKey(bossId))
{
_schedules.remove(bossId).cancel(true);
}
if (_storedInfo.containsKey(bossId))
{
_storedInfo.remove(bossId);
}
if (updateDb)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM raidboss_spawnlist WHERE boss_id=?"))
{
ps.setInt(1, bossId);
ps.execute();
}
catch (Exception e)
{
// problem with deleting spawn
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not remove raidboss #" + bossId + " from DB: " + e.getMessage(), e);
}
}
}
/**
* Update database.
*/
private void updateDb()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE raidboss_spawnlist SET respawn_time = ?, currentHP = ?, currentMP = ? WHERE boss_id = ?"))
{
for (Integer bossId : _storedInfo.keySet())
{
if (bossId == null)
{
continue;
}
final L2RaidBossInstance boss = _bosses.get(bossId);
if (boss == null)
{
continue;
}
if (boss.getRaidStatus().equals(StatusEnum.ALIVE))
{
updateStatus(boss, false);
}
final StatsSet info = _storedInfo.get(bossId);
if (info == null)
{
continue;
}
try
{
// TODO(Zoey76): Change this to use batch.
ps.setLong(1, info.getLong("respawnTime"));
ps.setDouble(2, info.getDouble("currentHP"));
ps.setDouble(3, info.getDouble("currentMP"));
ps.setInt(4, bossId);
ps.executeUpdate();
ps.clearParameters();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldnt update raidboss_spawnlist table " + e.getMessage(), e);
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": SQL error while updating RaidBoss spawn to database: " + e.getMessage(), e);
}
}
/**
* Gets the all raid boss status.
* @return the all raid boss status
*/
public String[] getAllRaidBossStatus()
{
final String[] msg = new String[(_bosses == null) ? 0 : _bosses.size()];
if (_bosses == null)
{
msg[0] = "None";
return msg;
}
int index = 0;
for (int i : _bosses.keySet())
{
final L2RaidBossInstance boss = _bosses.get(i);
msg[index++] = boss.getName() + ": " + boss.getRaidStatus().name();
}
return msg;
}
/**
* Gets the raid boss status.
* @param bossId the boss id
* @return the raid boss status
*/
public String getRaidBossStatus(int bossId)
{
String msg = "RaidBoss Status..." + Config.EOL;
if (_bosses == null)
{
return msg += "None";
}
if (_bosses.containsKey(bossId))
{
final L2RaidBossInstance boss = _bosses.get(bossId);
msg += boss.getName() + ": " + boss.getRaidStatus().name();
}
return msg;
}
/**
* Gets the raid boss status id.
* @param bossId the boss id
* @return the raid boss status id
*/
public StatusEnum getRaidBossStatusId(int bossId)
{
if (_bosses.containsKey(bossId))
{
return _bosses.get(bossId).getRaidStatus();
}
else if (_schedules.containsKey(bossId))
{
return StatusEnum.DEAD;
}
else
{
return StatusEnum.UNDEFINED;
}
}
/**
* Notify spawn night boss.
* @param raidboss the raidboss
*/
public void notifySpawnNightBoss(L2RaidBossInstance raidboss)
{
final StatsSet info = new StatsSet();
info.set("currentHP", raidboss.getCurrentHp());
info.set("currentMP", raidboss.getCurrentMp());
info.set("respawnTime", 0L);
raidboss.setRaidStatus(StatusEnum.ALIVE);
_storedInfo.put(raidboss.getId(), info);
_log.info(getClass().getSimpleName() + ": Spawning Night Raid Boss " + raidboss.getName());
_bosses.put(raidboss.getId(), raidboss);
}
/**
* Checks if the boss is defined.
* @param bossId the boss id
* @return {@code true} if is defined
*/
public boolean isDefined(int bossId)
{
return _spawns.containsKey(bossId);
}
/**
* Gets the bosses.
* @return the bosses
*/
public Map<Integer, L2RaidBossInstance> getBosses()
{
return _bosses;
}
/**
* Gets the spawns.
* @return the spawns
*/
public Map<Integer, L2Spawn> getSpawns()
{
return _spawns;
}
/**
* Gets the stored info.
* @return the stored info
*/
public Map<Integer, StatsSet> getStoredInfo()
{
return _storedInfo;
}
/**
* Saves and clears the raid bosses status, including all schedules.
*/
public void cleanUp()
{
updateDb();
_bosses.clear();
if (_schedules != null)
{
for (Integer bossId : _schedules.keySet())
{
_schedules.get(bossId).cancel(true);
}
_schedules.clear();
}
_storedInfo.clear();
_spawns.clear();
}
/**
* Gets the single instance of RaidBossSpawnManager.
* @return single instance of RaidBossSpawnManager
*/
public static RaidBossSpawnManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final RaidBossSpawnManager _instance = new RaidBossSpawnManager();
}
}

View File

@@ -0,0 +1,454 @@
/*
* 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.instancemanager;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.cache.HtmCache;
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.handler.CommunityBoardHandler;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SellBuffHolder;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.olympiad.OlympiadManager;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.serverpackets.ExPrivateStoreSetWholeMsg;
import com.l2jmobius.gameserver.util.HtmlUtil;
import com.l2jmobius.gameserver.util.Util;
/**
* Sell Buffs Manager
* @author St3eT
*/
public final class SellBuffsManager implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SellBuffsManager.class.getName());
private static final List<Integer> ALLOWED_BUFFS = new ArrayList<>();
private static final String htmlFolder = "data/html/mods/SellBuffs/";
protected SellBuffsManager()
{
load();
}
@Override
public void load()
{
if (Config.SELLBUFF_ENABLED)
{
ALLOWED_BUFFS.clear();
parseDatapackFile("data/SellBuffData.xml");
LOGGER.info(": Loaded " + ALLOWED_BUFFS.size() + " allowed buffs.");
}
}
@Override
public void parseDocument(Document doc, File f)
{
final NodeList node = doc.getDocumentElement().getElementsByTagName("skill");
for (int i = 0; i < node.getLength(); ++i)
{
final Element elem = (Element) node.item(i);
final int skillId = Integer.parseInt(elem.getAttribute("id"));
if (!ALLOWED_BUFFS.contains(skillId))
{
ALLOWED_BUFFS.add(skillId);
}
}
}
public void sendSellMenu(L2PcInstance player)
{
final String html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), htmlFolder + (player.isSellingBuffs() ? "BuffMenu_already.html" : "BuffMenu.html"));
CommunityBoardHandler.separateAndSend(html, player);
}
public void sendBuffChoiceMenu(L2PcInstance player, int index)
{
String html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), htmlFolder + "BuffChoice.html");
html = html.replace("%list%", buildSkillMenu(player, index));
CommunityBoardHandler.separateAndSend(html, player);
}
public void sendBuffEditMenu(L2PcInstance player)
{
String html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), htmlFolder + "BuffChoice.html");
html = html.replace("%list%", buildEditMenu(player));
CommunityBoardHandler.separateAndSend(html, player);
}
public void sendBuffMenu(L2PcInstance player, L2PcInstance seller, int index)
{
if (!seller.isSellingBuffs() || seller.getSellingBuffs().isEmpty())
{
return;
}
String html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), htmlFolder + "BuffBuyMenu.html");
html = html.replace("%list%", buildBuffMenu(player, seller, index));
CommunityBoardHandler.separateAndSend(html, player);
}
public void startSellBuffs(L2PcInstance player, String title)
{
player.sitDown();
player.setIsSellingBuffs(true);
player.setPrivateStoreType(PrivateStoreType.PACKAGE_SELL);
player.getSellList().setTitle(title);
player.getSellList().setPackaged(true);
player.broadcastUserInfo();
player.broadcastPacket(new ExPrivateStoreSetWholeMsg(player));
sendSellMenu(player);
}
public void stopSellBuffs(L2PcInstance player)
{
player.setIsSellingBuffs(false);
player.setPrivateStoreType(PrivateStoreType.NONE);
player.standUp();
player.broadcastUserInfo();
sendSellMenu(player);
}
private String buildBuffMenu(L2PcInstance player, L2PcInstance seller, int index)
{
final int ceiling = index + 10;
int nextIndex = -1;
int previousIndex = -1;
int emptyFields = 0;
final StringBuilder sb = new StringBuilder();
final List<SellBuffHolder> sellList = new ArrayList<>();
int count = 0;
for (SellBuffHolder holder : seller.getSellingBuffs())
{
count++;
if ((count > index) && (count <= ceiling))
{
sellList.add(holder);
}
}
if (count > 10)
{
if (count > (index + 10))
{
nextIndex = index + 10;
}
}
if (index >= 10)
{
previousIndex = index - 10;
}
emptyFields = ceiling - sellList.size();
sb.append("<br>");
sb.append(HtmlUtil.getMpGauge(250, (long) seller.getCurrentMp(), seller.getMaxMp(), false));
sb.append("<br>");
sb.append("<table border=0 cellpadding=0 cellspacing=0 background=\"L2UI_CH3.refinewnd_back_Pattern\">");
sb.append("<tr><td><br><br><br></td></tr>");
sb.append("<tr>");
sb.append("<td fixwidth=\"10\"></td>");
sb.append("<td> <button action=\"\" value=\"Icon\" width=75 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Icon
sb.append("<td> <button action=\"\" value=\"Name\" width=175 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Name
sb.append("<td> <button action=\"\" value=\"Level\" width=85 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Leve
sb.append("<td> <button action=\"\" value=\"MP Cost\" width=100 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Price
sb.append("<td> <button action=\"\" value=\"Price\" width=200 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Price
sb.append("<td> <button action=\"\" value=\"Action\" width=100 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Action
sb.append("<td fixwidth=\"20\"></td>");
sb.append("</tr>");
for (SellBuffHolder holder : sellList)
{
final Skill skill = seller.getKnownSkill(holder.getSkillId());
if (skill == null)
{
emptyFields++;
continue;
}
final L2Item item = ItemTable.getInstance().getTemplate(Config.SELLBUFF_PAYMENT_ID);
sb.append("<tr>");
sb.append("<td fixwidth=\"20\"></td>");
sb.append("<td align=center><img src=\"" + skill.getIcon() + "\" width=\"32\" height=\"32\"></td>");
sb.append("<td align=left>" + skill.getName() + (skill.getLevel() > 100 ? "<font color=\"LEVEL\"> + " + (skill.getLevel() % 100) + "</font></td>" : "</td>"));
sb.append("<td align=center>" + ((skill.getLevel() > 100) ? SkillData.getInstance().getMaxLevel(skill.getId()) : skill.getLevel()) + "</td>");
sb.append("<td align=center> <font color=\"1E90FF\">" + (skill.getMpConsume() * Config.SELLBUFF_MP_MULTIPLER) + "</font></td>");
sb.append("<td align=center> " + Util.formatAdena(holder.getPrice()) + " <font color=\"LEVEL\"> " + (item != null ? item.getName() : "") + "</font> </td>");
sb.append("<td align=center fixwidth=\"50\"><button value=\"Buy Buff\" action=\"bypass -h sellbuffbuyskill " + seller.getObjectId() + " " + skill.getId() + " " + index + "\" width=\"85\" height=\"26\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
sb.append("</tr>");
sb.append("<tr><td><br><br></td></tr>");
}
for (int i = 0; i < emptyFields; i++)
{
sb.append("<tr>");
sb.append("<td fixwidth=\"20\"></td>");
sb.append("<td align=center></td>");
sb.append("<td align=left></td>");
sb.append("<td align=center></td>");
sb.append("<td align=center></font></td>");
sb.append("<td align=center></td>");
sb.append("<td align=center fixwidth=\"50\"></td>");
sb.append("</tr>");
sb.append("<tr><td><br><br></td></tr>");
}
sb.append("</table>");
sb.append("<table width=\"250\" border=\"0\">");
sb.append("<tr>");
if (previousIndex > -1)
{
sb.append("<td align=left><button value=\"Previous Page\" action=\"bypass -h sellbuffbuymenu " + seller.getObjectId() + " " + previousIndex + "\" width=\"100\" height=\"30\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
}
if (nextIndex > -1)
{
sb.append("<td align=right><button value=\"Next Page\" action=\"bypass -h sellbuffbuymenu " + seller.getObjectId() + " " + nextIndex + "\" width=\"100\" height=\"30\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
}
sb.append("</tr>");
sb.append("</table>");
return sb.toString();
}
private String buildEditMenu(L2PcInstance player)
{
final StringBuilder sb = new StringBuilder();
sb.append("<table border=0 cellpadding=0 cellspacing=0 background=\"L2UI_CH3.refinewnd_back_Pattern\">");
sb.append("<tr><td><br><br><br></td></tr>");
sb.append("<tr>");
sb.append("<td fixwidth=\"10\"></td>");
sb.append("<td> <button action=\"\" value=\"Icon\" width=75 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Icon
sb.append("<td> <button action=\"\" value=\"Name\" width=150 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Name
sb.append("<td> <button action=\"\" value=\"Level\" width=75 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Level
sb.append("<td> <button action=\"\" value=\"Old Price\" width=100 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Old price
sb.append("<td> <button action=\"\" value=\"New Price\" width=125 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // New price
sb.append("<td> <button action=\"\" value=\"Action\" width=125 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Change Price
sb.append("<td> <button action=\"\" value=\"Remove\" width=85 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Remove Buff
sb.append("<td fixwidth=\"20\"></td>");
sb.append("</tr>");
if (player.getSellingBuffs().isEmpty())
{
sb.append("</table>");
sb.append("<br><br><br>");
sb.append("You don't have added any buffs yet!");
}
else
{
for (SellBuffHolder holder : player.getSellingBuffs())
{
final Skill skill = player.getKnownSkill(holder.getSkillId());
if (skill == null)
{
continue;
}
sb.append("<tr>");
sb.append("<td fixwidth=\"20\"></td>");
sb.append("<td align=center><img src=\"" + skill.getIcon() + "\" width=\"32\" height=\"32\"></td>"); // Icon
sb.append("<td align=left>" + skill.getName() + (skill.getLevel() > 100 ? "<font color=\"LEVEL\"> + " + (skill.getLevel() % 100) + "</font></td>" : "</td>")); // Name + enchant
sb.append("<td align=center>" + ((skill.getLevel() > 100) ? SkillData.getInstance().getMaxLevel(skill.getId()) : skill.getLevel()) + "</td>"); // Level
sb.append("<td align=center> " + Util.formatAdena(holder.getPrice()) + " </td>"); // Price show
sb.append("<td align=center><edit var=\"price_" + skill.getId() + "\" width=120 type=\"number\"></td>"); // Price edit
sb.append("<td align=center><button value=\"Edit\" action=\"bypass -h sellbuffchangeprice " + skill.getId() + " $price_" + skill.getId() + "\" width=\"85\" height=\"26\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
sb.append("<td align=center><button value=\" X \" action=\"bypass -h sellbuffremove " + skill.getId() + "\" width=\"26\" height=\"26\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
sb.append("</tr>");
sb.append("<tr><td><br><br></td></tr>");
}
sb.append("</table>");
}
return sb.toString();
}
private String buildSkillMenu(L2PcInstance player, int index)
{
final int ceiling = index + 10;
int nextIndex = -1;
int previousIndex = -1;
final StringBuilder sb = new StringBuilder();
final List<Skill> skillList = new ArrayList<>();
int count = 0;
for (Skill skill : player.getAllSkills())
{
if (ALLOWED_BUFFS.contains(skill.getId()) && !isInSellList(player, skill))
{
count++;
if ((count > index) && (count <= ceiling))
{
skillList.add(skill);
}
}
}
if (count > 10)
{
if (count > (index + 10))
{
nextIndex = index + 10;
}
}
if (index >= 10)
{
previousIndex = index - 10;
}
sb.append("<table border=0 cellpadding=0 cellspacing=0 background=\"L2UI_CH3.refinewnd_back_Pattern\">");
sb.append("<tr><td><br><br><br></td></tr>");
sb.append("<tr>");
sb.append("<td fixwidth=\"10\"></td>");
sb.append("<td> <button action=\"\" value=\"Icon\" width=100 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Icon
sb.append("<td> <button action=\"\" value=\"Name\" width=175 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Name
sb.append("<td> <button action=\"\" value=\"Level\" width=150 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Leve
sb.append("<td> <button action=\"\" value=\"Price\" width=150 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Price
sb.append("<td> <button action=\"\" value=\"Action\" width=125 height=23 back=\"L2UI_CT1.OlympiadWnd_DF_Watch_Down\" fore=\"L2UI_CT1.OlympiadWnd_DF_Watch\"> </td>"); // Action
sb.append("<td fixwidth=\"20\"></td>");
sb.append("</tr>");
if (skillList.isEmpty())
{
sb.append("</table>");
sb.append("<br><br><br>");
sb.append("At this moment you cant add any buffs!");
}
else
{
for (Skill skill : skillList)
{
sb.append("<tr>");
sb.append("<td fixwidth=\"20\"></td>");
sb.append("<td align=center><img src=\"" + skill.getIcon() + "\" width=\"32\" height=\"32\"></td>");
sb.append("<td align=left>" + skill.getName() + (skill.getLevel() > 100 ? "<font color=\"LEVEL\"> + " + (skill.getLevel() % 100) + "</font></td>" : "</td>"));
sb.append("<td align=center>" + ((skill.getLevel() > 100) ? SkillData.getInstance().getMaxLevel(skill.getId()) : skill.getLevel()) + "</td>");
sb.append("<td align=center><edit var=\"price_" + skill.getId() + "\" width=120 type=\"number\"></td>");
sb.append("<td align=center fixwidth=\"50\"><button value=\"Add Buff\" action=\"bypass -h sellbuffaddskill " + skill.getId() + " $price_" + skill.getId() + "\" width=\"85\" height=\"26\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
sb.append("</tr>");
sb.append("<tr><td><br><br></td></tr>");
}
sb.append("</table>");
}
sb.append("<table width=\"250\" border=\"0\">");
sb.append("<tr>");
if (previousIndex > -1)
{
sb.append("<td align=left><button value=\"Previous Page\" action=\"bypass -h sellbuffadd " + previousIndex + "\" width=\"100\" height=\"30\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
}
if (nextIndex > -1)
{
sb.append("<td align=right><button value=\"Next Page\" action=\"bypass -h sellbuffadd " + nextIndex + "\" width=\"100\" height=\"30\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>");
}
sb.append("</tr>");
sb.append("</table>");
return sb.toString();
}
public boolean isInSellList(L2PcInstance player, Skill skill)
{
return player.getSellingBuffs().stream().filter(h -> (h.getSkillId() == skill.getId())).findFirst().orElse(null) != null;
}
public boolean canStartSellBuffs(L2PcInstance player)
{
if (player.isAlikeDead())
{
player.sendMessage("You can't sell buffs in fake death!");
return false;
}
else if (player.isInOlympiadMode() || OlympiadManager.getInstance().isRegistered(player))
{
player.sendMessage("You can't sell buffs with Olympiad status!");
return false;
}
else if (CeremonyOfChaosManager.getInstance().isRegistered(player))
{
player.sendMessage("You can't sell buffs with Ceremony of Chaos status!");
return false;
}
else if (player.isCursedWeaponEquipped() || (player.getReputation() < 0))
{
player.sendMessage("You can't sell buffs in Chaotic state!");
return false;
}
else if (player.isInDuel())
{
player.sendMessage("You can't sell buffs in Duel state!");
return false;
}
else if (player.isFishing())
{
player.sendMessage("You can't sell buffs while fishing.");
return false;
}
else if (player.isMounted() || player.isFlyingMounted() || player.isFlying())
{
player.sendMessage("You can't sell buffs in Mounth state!");
return false;
}
else if (player.isTransformed())
{
player.sendMessage("You can't sell buffs in Transform state!");
return false;
}
else if (player.isInsideZone(ZoneId.NO_STORE) || !player.isInsideZone(ZoneId.PEACE) || player.isJailed())
{
player.sendMessage("You can't sell buffs here!");
return false;
}
return true;
}
/**
* Gets the single instance of {@code SellBuffsManager}.
* @return single instance of {@code SellBuffsManager}
*/
public static final SellBuffsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SellBuffsManager _instance = new SellBuffsManager();
}
}

View File

@@ -1,261 +1,393 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
public final class SiegeGuardManager
{
private static Logger _log = Logger.getLogger(SiegeGuardManager.class.getName());
private final Castle _castle;
private final List<L2Spawn> _siegeGuardSpawn = new ArrayList<>();
public SiegeGuardManager(Castle castle)
{
_castle = castle;
}
/**
* Add guard.
* @param activeChar
* @param npcId
*/
public void addSiegeGuard(L2PcInstance activeChar, int npcId)
{
if (activeChar == null)
{
return;
}
addSiegeGuard(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
}
/**
* Add guard.
* @param x
* @param y
* @param z
* @param heading
* @param npcId
*/
public void addSiegeGuard(int x, int y, int z, int heading, int npcId)
{
saveSiegeGuard(x, y, z, heading, npcId, 0);
}
/**
* Hire merc.
* @param activeChar
* @param npcId
*/
public void hireMerc(L2PcInstance activeChar, int npcId)
{
if (activeChar == null)
{
return;
}
hireMerc(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
}
/**
* Hire merc.
* @param x
* @param y
* @param z
* @param heading
* @param npcId
*/
public void hireMerc(int x, int y, int z, int heading, int npcId)
{
saveSiegeGuard(x, y, z, heading, npcId, 1);
}
/**
* Remove a single mercenary, identified by the npcId and location. Presumably, this is used when a castle lord picks up a previously dropped ticket
* @param npcId
* @param x
* @param y
* @param z
*/
public void removeMerc(int npcId, int x, int y, int z)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Delete From castle_siege_guards Where npcId = ? And x = ? AND y = ? AND z = ? AND isHired = 1"))
{
ps.setInt(1, npcId);
ps.setInt(2, x);
ps.setInt(3, y);
ps.setInt(4, z);
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting hired siege guard at " + x + ',' + y + ',' + z + ": " + e.getMessage(), e);
}
}
/**
* Remove mercs.
*/
public void removeMercs()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Delete From castle_siege_guards Where castleId = ? And isHired = 1"))
{
ps.setInt(1, getCastle().getResidenceId());
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting hired siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
}
/**
* Spawn guards.
*/
public void spawnSiegeGuard()
{
try
{
int hiredCount = 0;
final int hiredMax = MercTicketManager.getInstance().getMaxAllowedMerc(_castle.getResidenceId());
final boolean isHired = getCastle().getOwnerId() > 0;
loadSiegeGuard();
for (L2Spawn spawn : _siegeGuardSpawn)
{
if (spawn != null)
{
spawn.init();
if (isHired)
{
spawn.stopRespawn();
if (++hiredCount > hiredMax)
{
return;
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Error spawning siege guards for castle " + getCastle().getName(), e);
}
}
/**
* Unspawn guards.
*/
public void unspawnSiegeGuard()
{
for (L2Spawn spawn : _siegeGuardSpawn)
{
if ((spawn != null) && (spawn.getLastSpawn() != null))
{
spawn.stopRespawn();
spawn.getLastSpawn().doDie(spawn.getLastSpawn());
}
}
_siegeGuardSpawn.clear();
}
/**
* Load guards.
*/
private void loadSiegeGuard()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM castle_siege_guards Where castleId = ? And isHired = ?"))
{
ps.setInt(1, getCastle().getResidenceId());
ps.setInt(2, getCastle().getOwnerId() > 0 ? 1 : 0);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
final L2Spawn spawn = new L2Spawn(rs.getInt("npcId"));
spawn.setAmount(1);
spawn.setX(rs.getInt("x"));
spawn.setY(rs.getInt("y"));
spawn.setZ(rs.getInt("z"));
spawn.setHeading(rs.getInt("heading"));
spawn.setRespawnDelay(rs.getInt("respawnDelay"));
spawn.setLocationId(0);
_siegeGuardSpawn.add(spawn);
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error loading siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
}
/**
* Save guards.
* @param x
* @param y
* @param z
* @param heading
* @param npcId
* @param isHire
*/
private void saveSiegeGuard(int x, int y, int z, int heading, int npcId, int isHire)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Insert Into castle_siege_guards (castleId, npcId, x, y, z, heading, respawnDelay, isHired) Values (?, ?, ?, ?, ?, ?, ?, ?)"))
{
ps.setInt(1, getCastle().getResidenceId());
ps.setInt(2, npcId);
ps.setInt(3, x);
ps.setInt(4, y);
ps.setInt(5, z);
ps.setInt(6, heading);
ps.setInt(7, isHire == 1 ? 0 : 600);
ps.setInt(8, isHire);
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error adding siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
}
public final Castle getCastle()
{
return _castle;
}
public final List<L2Spawn> getSiegeGuardSpawn()
{
return _siegeGuardSpawn;
}
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.xml.impl.CastleData;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.enums.ItemLocation;
import com.l2jmobius.gameserver.model.L2Spawn;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.holders.SiegeGuardHolder;
import com.l2jmobius.gameserver.model.interfaces.IPositionable;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* Siege Guard Manager.
* @author St3eT
*/
public final class SiegeGuardManager
{
private static final Logger LOGGER = Logger.getLogger(SiegeGuardManager.class.getName());
private static final Set<L2ItemInstance> _droppedTickets = ConcurrentHashMap.newKeySet();
private static final Map<Integer, Set<L2Spawn>> _siegeGuardSpawn = new ConcurrentHashMap<>();
protected SiegeGuardManager()
{
_droppedTickets.clear();
load();
}
private void load()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
ResultSet rs = con.createStatement().executeQuery("SELECT * FROM castle_siege_guards Where isHired = 1"))
{
while (rs.next())
{
final int npcId = rs.getInt("npcId");
final int x = rs.getInt("x");
final int y = rs.getInt("y");
final int z = rs.getInt("z");
final Castle castle = CastleManager.getInstance().getCastle(x, y, z);
if (castle == null)
{
LOGGER.warning("Siege guard ticket cannot be placed! Castle is null at X: " + x + ", Y: " + y + ", Z: " + z);
continue;
}
final SiegeGuardHolder holder = getSiegeGuardByNpc(castle.getResidenceId(), npcId);
if ((holder != null) && !castle.getSiege().isInProgress())
{
final L2ItemInstance dropticket = new L2ItemInstance(holder.getItemId());
dropticket.setItemLocation(ItemLocation.VOID);
dropticket.dropMe(null, x, y, z);
L2World.getInstance().storeObject(dropticket);
_droppedTickets.add(dropticket);
}
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _droppedTickets.size() + " siege guards tickets.");
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
}
/**
* Finds {@code SiegeGuardHolder} equals to castle id and npc id.
* @param castleId the ID of the castle
* @param itemId the ID of the item
* @return the {@code SiegeGuardHolder} for this castle ID and item ID if any, otherwise {@code null}
*/
public SiegeGuardHolder getSiegeGuardByItem(int castleId, int itemId)
{
return CastleData.getInstance().getSiegeGuardsForCastle(castleId).stream().filter(g -> (g.getItemId() == itemId)).findFirst().orElse(null);
}
/**
* Finds {@code SiegeGuardHolder} equals to castle id and npc id.
* @param castleId the ID of the castle
* @param npcId the ID of the npc
* @return the {@code SiegeGuardHolder} for this castle ID and npc ID if any, otherwise {@code null}
*/
public SiegeGuardHolder getSiegeGuardByNpc(int castleId, int npcId)
{
return CastleData.getInstance().getSiegeGuardsForCastle(castleId).stream().filter(g -> (g.getNpcId() == npcId)).findFirst().orElse(null);
}
/**
* Checks if {@code PlayerInstance} is too much close to another ticket.
* @param player the PlayerInstance
* @return {@code true} if {@code PlayerInstance} is too much close to another ticket, {@code false} otherwise
*/
public boolean isTooCloseToAnotherTicket(L2PcInstance player)
{
return _droppedTickets.stream().filter(g -> g.calculateDistance(player, true, false) < 25).findFirst().orElse(null) != null;
}
/**
* Checks if castle is under npc limit.
* @param castleId the ID of the castle
* @param itemId the ID of the item
* @return {@code true} if castle is under npc limit, {@code false} otherwise
*/
public boolean isAtNpcLimit(int castleId, int itemId)
{
final long count = _droppedTickets.stream().filter(i -> i.getId() == itemId).count();
final SiegeGuardHolder holder = getSiegeGuardByItem(castleId, itemId);
return count >= holder.getMaxNpcAmout();
}
/**
* Adds ticket in current world.
* @param itemId the ID of the item
* @param player the PlayerInstance
*/
public void addTicket(int itemId, L2PcInstance player)
{
final Castle castle = CastleManager.getInstance().getCastle(player);
if (castle == null)
{
return;
}
if (isAtNpcLimit(castle.getResidenceId(), itemId))
{
return;
}
final SiegeGuardHolder holder = getSiegeGuardByItem(castle.getResidenceId(), itemId);
if (holder != null)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("Insert Into castle_siege_guards (castleId, npcId, x, y, z, heading, respawnDelay, isHired) Values (?, ?, ?, ?, ?, ?, ?, ?)"))
{
statement.setInt(1, castle.getResidenceId());
statement.setInt(2, holder.getNpcId());
statement.setInt(3, player.getX());
statement.setInt(4, player.getY());
statement.setInt(5, player.getZ());
statement.setInt(6, player.getHeading());
statement.setInt(7, 0);
statement.setInt(8, 1);
statement.execute();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Error adding siege guard for castle " + castle.getName() + ": " + e.getMessage(), e);
}
spawnMercenary(player, holder);
final L2ItemInstance dropticket = new L2ItemInstance(itemId);
dropticket.setItemLocation(ItemLocation.VOID);
dropticket.dropMe(null, player.getX(), player.getY(), player.getZ());
L2World.getInstance().storeObject(dropticket);
_droppedTickets.add(dropticket);
}
}
/**
* Spawns Siege Guard in current world.
* @param pos the object containing the spawn location coordinates
* @param holder SiegeGuardHolder holder
*/
private void spawnMercenary(IPositionable pos, SiegeGuardHolder holder)
{
final L2NpcTemplate template = NpcData.getInstance().getTemplate(holder.getNpcId());
if (template != null)
{
final L2DefenderInstance npc = new L2DefenderInstance(template);
npc.setCurrentHpMp(npc.getMaxHp(), npc.getMaxMp());
npc.setDecayed(false);
npc.setHeading(pos.getHeading());
npc.spawnMe(pos.getX(), pos.getY(), (pos.getZ() + 20));
npc.scheduleDespawn(3000);
npc.setIsImmobilized(holder.isStationary());
}
}
/**
* Delete all tickets from a castle.
* @param castleId the ID of the castle
*/
public void deleteTickets(int castleId)
{
for (L2ItemInstance ticket : _droppedTickets)
{
if ((ticket != null) && (getSiegeGuardByItem(castleId, ticket.getId()) != null))
{
ticket.decayMe();
_droppedTickets.remove(ticket);
}
}
}
/**
* remove a single ticket and its associated spawn from the world (used when the castle lord picks up a ticket, for example).
* @param item the item ID
*/
public void removeTicket(L2ItemInstance item)
{
final Castle castle = CastleManager.getInstance().getCastle(item);
if (castle == null)
{
return;
}
final SiegeGuardHolder holder = getSiegeGuardByItem(castle.getResidenceId(), item.getId());
if (holder == null)
{
return;
}
removeSiegeGuard(holder.getNpcId(), item);
_droppedTickets.remove(item);
}
/**
* Loads all siege guards for castle.
* @param castle the castle instance
*/
private void loadSiegeGuard(Castle castle)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM castle_siege_guards Where castleId = ? And isHired = ?"))
{
ps.setInt(1, castle.getResidenceId());
ps.setInt(2, castle.getOwnerId() > 0 ? 1 : 0);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
final L2Spawn spawn = new L2Spawn(rs.getInt("npcId"));
spawn.setAmount(1);
spawn.setX(rs.getInt("x"));
spawn.setY(rs.getInt("y"));
spawn.setZ(rs.getInt("z"));
spawn.setHeading(rs.getInt("heading"));
spawn.setRespawnDelay(rs.getInt("respawnDelay"));
spawn.setLocationId(0);
getSpawnedGuards(castle.getResidenceId()).add(spawn);
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Error loading siege guard for castle " + castle.getName() + ": " + e.getMessage(), e);
}
}
/**
* Remove single siege guard.
* @param npcId the ID of NPC
* @param pos
*/
public void removeSiegeGuard(int npcId, IPositionable pos)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Delete From castle_siege_guards Where npcId = ? And x = ? AND y = ? AND z = ? AND isHired = 1"))
{
ps.setInt(1, npcId);
ps.setInt(2, pos.getX());
ps.setInt(3, pos.getY());
ps.setInt(4, pos.getZ());
ps.execute();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Error deleting hired siege guard at " + pos + " : " + e.getMessage(), e);
}
}
/**
* Remove all siege guards for castle.
* @param castle the castle instance
*/
public void removeSiegeGuards(Castle castle)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Delete From castle_siege_guards Where castleId = ? And isHired = 1"))
{
ps.setInt(1, castle.getResidenceId());
ps.execute();
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Error deleting hired siege guard for castle " + castle.getName() + ": " + e.getMessage(), e);
}
}
/**
* Spawn all siege guards for castle.
* @param castle the castle instance
*/
public void spawnSiegeGuard(Castle castle)
{
try
{
final boolean isHired = (castle.getOwnerId() > 0);
loadSiegeGuard(castle);
for (L2Spawn spawn : getSpawnedGuards(castle.getResidenceId()))
{
if (spawn != null)
{
spawn.init();
if (isHired)
{
spawn.stopRespawn();
}
final SiegeGuardHolder holder = getSiegeGuardByNpc(castle.getResidenceId(), spawn.getLastSpawn().getId());
if (holder == null)
{
continue;
}
spawn.getLastSpawn().setIsImmobilized(holder.isStationary());
}
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Error spawning siege guards for castle " + castle.getName(), e);
}
}
/**
* Unspawn all siege guards for castle.
* @param castle the castle instance
*/
public void unspawnSiegeGuard(Castle castle)
{
for (L2Spawn spawn : getSpawnedGuards(castle.getResidenceId()))
{
if ((spawn != null) && (spawn.getLastSpawn() != null))
{
spawn.stopRespawn();
spawn.getLastSpawn().doDie(spawn.getLastSpawn());
}
}
getSpawnedGuards(castle.getResidenceId()).clear();
}
public Set<L2Spawn> getSpawnedGuards(int castleId)
{
return _siegeGuardSpawn.computeIfAbsent(castleId, key -> ConcurrentHashMap.newKeySet());
}
/**
* Gets the single instance of {@code MercTicketManager}.
* @return single instance of {@code MercTicketManager}
*/
public static SiegeGuardManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SiegeGuardManager _instance = new SiegeGuardManager();
}
}

View File

@@ -1,306 +1,305 @@
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.datatables.SkillData;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.TowerSpawn;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.entity.Siege;
import com.l2jmobius.gameserver.model.interfaces.ILocational;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.util.PropertiesParser;
public final class SiegeManager
{
private static final Logger _log = Logger.getLogger(SiegeManager.class.getName());
private final Map<Integer, List<TowerSpawn>> _controlTowers = new HashMap<>();
private final Map<Integer, List<TowerSpawn>> _flameTowers = new HashMap<>();
private int _attackerMaxClans = 500; // Max number of clans
private int _attackerRespawnDelay = 0; // Time in ms. Changeable in siege.config
private int _defenderMaxClans = 500; // Max number of clans
private int _flagMaxCount = 1; // Changeable in siege.config
private int _siegeClanMinLevel = 5; // Changeable in siege.config
private int _siegeLength = 120; // Time in minute. Changeable in siege.config
private int _bloodAllianceReward = 0; // Number of Blood Alliance items reward for successful castle defending
protected SiegeManager()
{
load();
}
public final void addSiegeSkills(L2PcInstance character)
{
for (Skill sk : SkillData.getInstance().getSiegeSkills(character.isNoble(), character.getClan().getCastleId() > 0))
{
character.addSkill(sk, false);
}
}
/**
* @param clan The L2Clan of the player
* @param castleid
* @return true if the clan is registered or owner of a castle
*/
public final boolean checkIsRegistered(L2Clan clan, int castleid)
{
if (clan == null)
{
return false;
}
if (clan.getCastleId() > 0)
{
return true;
}
boolean register = false;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT clan_id FROM siege_clans where clan_id=? and castle_id=?"))
{
ps.setInt(1, clan.getId());
ps.setInt(2, castleid);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
register = true;
break;
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Exception: checkIsRegistered(): " + e.getMessage(), e);
}
return register;
}
public final void removeSiegeSkills(L2PcInstance character)
{
for (Skill sk : SkillData.getInstance().getSiegeSkills(character.isNoble(), character.getClan().getCastleId() > 0))
{
character.removeSkill(sk);
}
}
private final void load()
{
final PropertiesParser siegeSettings = new PropertiesParser(Config.SIEGE_CONFIGURATION_FILE);
// Siege setting
_attackerMaxClans = siegeSettings.getInt("AttackerMaxClans", 500);
_attackerRespawnDelay = siegeSettings.getInt("AttackerRespawn", 0);
_defenderMaxClans = siegeSettings.getInt("DefenderMaxClans", 500);
_flagMaxCount = siegeSettings.getInt("MaxFlags", 1);
_siegeClanMinLevel = siegeSettings.getInt("SiegeClanMinLevel", 5);
_siegeLength = siegeSettings.getInt("SiegeLength", 120);
_bloodAllianceReward = siegeSettings.getInt("BloodAllianceReward", 1);
for (Castle castle : CastleManager.getInstance().getCastles())
{
final List<TowerSpawn> controlTowers = new ArrayList<>();
for (int i = 1; i < 0xFF; i++)
{
final String settingsKeyName = castle.getName() + "ControlTower" + i;
if (!siegeSettings.containskey(settingsKeyName))
{
break;
}
final StringTokenizer st = new StringTokenizer(siegeSettings.getString(settingsKeyName, ""), ",");
try
{
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int npcId = Integer.parseInt(st.nextToken());
controlTowers.add(new TowerSpawn(npcId, new Location(x, y, z)));
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Error while loading control tower(s) for " + castle.getName() + " castle.");
}
}
final List<TowerSpawn> flameTowers = new ArrayList<>();
for (int i = 1; i < 0xFF; i++)
{
final String settingsKeyName = castle.getName() + "FlameTower" + i;
if (!siegeSettings.containskey(settingsKeyName))
{
break;
}
final StringTokenizer st = new StringTokenizer(siegeSettings.getString(settingsKeyName, ""), ",");
try
{
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int npcId = Integer.parseInt(st.nextToken());
final List<Integer> zoneList = new ArrayList<>();
while (st.hasMoreTokens())
{
zoneList.add(Integer.parseInt(st.nextToken()));
}
flameTowers.add(new TowerSpawn(npcId, new Location(x, y, z), zoneList));
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Error while loading flame tower(s) for " + castle.getName() + " castle.");
}
}
_controlTowers.put(castle.getResidenceId(), controlTowers);
_flameTowers.put(castle.getResidenceId(), flameTowers);
MercTicketManager.MERCS_MAX_PER_CASTLE[castle.getResidenceId() - 1] = siegeSettings.getInt(castle.getName() + "MaxMercenaries", MercTicketManager.MERCS_MAX_PER_CASTLE[castle.getResidenceId() - 1]);
if (castle.getOwnerId() != 0)
{
loadTrapUpgrade(castle.getResidenceId());
}
}
}
public final List<TowerSpawn> getControlTowers(int castleId)
{
return _controlTowers.get(castleId);
}
public final List<TowerSpawn> getFlameTowers(int castleId)
{
return _flameTowers.get(castleId);
}
public final int getAttackerMaxClans()
{
return _attackerMaxClans;
}
public final int getAttackerRespawnDelay()
{
return _attackerRespawnDelay;
}
public final int getDefenderMaxClans()
{
return _defenderMaxClans;
}
public final int getFlagMaxCount()
{
return _flagMaxCount;
}
public final Siege getSiege(ILocational loc)
{
return getSiege(loc.getX(), loc.getY(), loc.getZ());
}
public final Siege getSiege(L2Object activeObject)
{
return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final Siege getSiege(int x, int y, int z)
{
for (Castle castle : CastleManager.getInstance().getCastles())
{
if (castle.getSiege().checkIfInZone(x, y, z))
{
return castle.getSiege();
}
}
return null;
}
public final int getSiegeClanMinLevel()
{
return _siegeClanMinLevel;
}
public final int getSiegeLength()
{
return _siegeLength;
}
public final int getBloodAllianceReward()
{
return _bloodAllianceReward;
}
public final List<Siege> getSieges()
{
final List<Siege> sieges = new ArrayList<>();
for (Castle castle : CastleManager.getInstance().getCastles())
{
sieges.add(castle.getSiege());
}
return sieges;
}
private final void loadTrapUpgrade(int castleId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM castle_trapupgrade WHERE castleId=?"))
{
ps.setInt(1, castleId);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
_flameTowers.get(castleId).get(rs.getInt("towerIndex")).setUpgradeLevel(rs.getInt("level"));
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadTrapUpgrade(): " + e.getMessage(), e);
}
}
public static SiegeManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SiegeManager _instance = new SiegeManager();
}
/*
* 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.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.PropertiesParser;
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Object;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.TowerSpawn;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.entity.Siege;
import com.l2jmobius.gameserver.model.interfaces.ILocational;
import com.l2jmobius.gameserver.model.skills.Skill;
public final class SiegeManager
{
private static final Logger _log = Logger.getLogger(SiegeManager.class.getName());
private final Map<Integer, List<TowerSpawn>> _controlTowers = new HashMap<>();
private final Map<Integer, List<TowerSpawn>> _flameTowers = new HashMap<>();
private int _attackerMaxClans = 500; // Max number of clans
private int _attackerRespawnDelay = 0; // Time in ms. Changeable in siege.config
private int _defenderMaxClans = 500; // Max number of clans
private int _flagMaxCount = 1; // Changeable in siege.config
private int _siegeClanMinLevel = 5; // Changeable in siege.config
private int _siegeLength = 120; // Time in minute. Changeable in siege.config
private int _bloodAllianceReward = 0; // Number of Blood Alliance items reward for successful castle defending
protected SiegeManager()
{
load();
}
public final void addSiegeSkills(L2PcInstance character)
{
for (Skill sk : SkillData.getInstance().getSiegeSkills(character.isNoble(), character.getClan().getCastleId() > 0))
{
character.addSkill(sk, false);
}
}
/**
* @param clan The L2Clan of the player
* @param castleid
* @return true if the clan is registered or owner of a castle
*/
public final boolean checkIsRegistered(L2Clan clan, int castleid)
{
if (clan == null)
{
return false;
}
if (clan.getCastleId() > 0)
{
return true;
}
boolean register = false;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM siege_clans where clan_id=? and castle_id=?"))
{
statement.setInt(1, clan.getId());
statement.setInt(2, castleid);
try (ResultSet rs = statement.executeQuery())
{
if (rs.next())
{
register = true;
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Exception: checkIsRegistered(): " + e.getMessage(), e);
}
return register;
}
public final void removeSiegeSkills(L2PcInstance character)
{
for (Skill sk : SkillData.getInstance().getSiegeSkills(character.isNoble(), character.getClan().getCastleId() > 0))
{
character.removeSkill(sk);
}
}
private void load()
{
final PropertiesParser siegeSettings = new PropertiesParser(Config.SIEGE_CONFIGURATION_FILE);
// Siege setting
_attackerMaxClans = siegeSettings.getInt("AttackerMaxClans", 500);
_attackerRespawnDelay = siegeSettings.getInt("AttackerRespawn", 0);
_defenderMaxClans = siegeSettings.getInt("DefenderMaxClans", 500);
_flagMaxCount = siegeSettings.getInt("MaxFlags", 1);
_siegeClanMinLevel = siegeSettings.getInt("SiegeClanMinLevel", 5);
_siegeLength = siegeSettings.getInt("SiegeLength", 120);
_bloodAllianceReward = siegeSettings.getInt("BloodAllianceReward", 1);
for (Castle castle : CastleManager.getInstance().getCastles())
{
final List<TowerSpawn> controlTowers = new ArrayList<>();
for (int i = 1; i < 0xFF; i++)
{
final String settingsKeyName = castle.getName() + "ControlTower" + i;
if (!siegeSettings.containskey(settingsKeyName))
{
break;
}
final StringTokenizer st = new StringTokenizer(siegeSettings.getString(settingsKeyName, ""), ",");
try
{
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int npcId = Integer.parseInt(st.nextToken());
controlTowers.add(new TowerSpawn(npcId, new Location(x, y, z)));
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Error while loading control tower(s) for " + castle.getName() + " castle.");
}
}
final List<TowerSpawn> flameTowers = new ArrayList<>();
for (int i = 1; i < 0xFF; i++)
{
final String settingsKeyName = castle.getName() + "FlameTower" + i;
if (!siegeSettings.containskey(settingsKeyName))
{
break;
}
final StringTokenizer st = new StringTokenizer(siegeSettings.getString(settingsKeyName, ""), ",");
try
{
final int x = Integer.parseInt(st.nextToken());
final int y = Integer.parseInt(st.nextToken());
final int z = Integer.parseInt(st.nextToken());
final int npcId = Integer.parseInt(st.nextToken());
final List<Integer> zoneList = new ArrayList<>();
while (st.hasMoreTokens())
{
zoneList.add(Integer.parseInt(st.nextToken()));
}
flameTowers.add(new TowerSpawn(npcId, new Location(x, y, z), zoneList));
}
catch (Exception e)
{
_log.warning(getClass().getSimpleName() + ": Error while loading flame tower(s) for " + castle.getName() + " castle.");
}
}
_controlTowers.put(castle.getResidenceId(), controlTowers);
_flameTowers.put(castle.getResidenceId(), flameTowers);
if (castle.getOwnerId() != 0)
{
loadTrapUpgrade(castle.getResidenceId());
}
}
}
public final List<TowerSpawn> getControlTowers(int castleId)
{
return _controlTowers.get(castleId);
}
public final List<TowerSpawn> getFlameTowers(int castleId)
{
return _flameTowers.get(castleId);
}
public final int getAttackerMaxClans()
{
return _attackerMaxClans;
}
public final int getAttackerRespawnDelay()
{
return _attackerRespawnDelay;
}
public final int getDefenderMaxClans()
{
return _defenderMaxClans;
}
public final int getFlagMaxCount()
{
return _flagMaxCount;
}
public final Siege getSiege(ILocational loc)
{
return getSiege(loc.getX(), loc.getY(), loc.getZ());
}
public final Siege getSiege(L2Object activeObject)
{
return getSiege(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final Siege getSiege(int x, int y, int z)
{
for (Castle castle : CastleManager.getInstance().getCastles())
{
if (castle.getSiege().checkIfInZone(x, y, z))
{
return castle.getSiege();
}
}
return null;
}
public final int getSiegeClanMinLevel()
{
return _siegeClanMinLevel;
}
public final int getSiegeLength()
{
return _siegeLength;
}
public final int getBloodAllianceReward()
{
return _bloodAllianceReward;
}
public final List<Siege> getSieges()
{
final List<Siege> sieges = new LinkedList<>();
for (Castle castle : CastleManager.getInstance().getCastles())
{
sieges.add(castle.getSiege());
}
return sieges;
}
private void loadTrapUpgrade(int castleId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM castle_trapupgrade WHERE castleId=?"))
{
ps.setInt(1, castleId);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
_flameTowers.get(castleId).get(rs.getInt("towerIndex")).setUpgradeLevel(rs.getInt("level"));
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadTrapUpgrade(): " + e.getMessage(), e);
}
}
public static SiegeManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SiegeManager _instance = new SiegeManager();
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.instancemanager;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.events.timers.TimerHolder;
/**
* @author UnAfraid
*/
public class TimersManager
{
private final Map<Integer, Set<TimerHolder<?>>> _timers = new ConcurrentHashMap<>();
public void registerTimer(TimerHolder<?> timer)
{
final L2Npc npc = timer.getNpc();
if (npc != null)
{
_timers.computeIfAbsent(npc.getObjectId(), key -> ConcurrentHashMap.newKeySet()).add(timer);
}
final L2PcInstance player = timer.getPlayer();
if (player != null)
{
_timers.computeIfAbsent(player.getObjectId(), key -> ConcurrentHashMap.newKeySet()).add(timer);
}
}
public void cancelTimers(int objectId)
{
final Set<TimerHolder<?>> timers = _timers.remove(objectId);
if (timers != null)
{
timers.forEach(TimerHolder::cancelTimer);
}
}
public static TimersManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final TimersManager _instance = new TimersManager();
}
}

View File

@@ -1,122 +1,101 @@
/*
* 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.instancemanager;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.type.L2TownZone;
public final class TownManager
{
public static int getTownCastle(int townId)
{
switch (townId)
{
case 912:
{
return 1;
}
case 916:
{
return 2;
}
case 918:
{
return 3;
}
case 922:
{
return 4;
}
case 924:
{
return 5;
}
case 926:
{
return 6;
}
case 1538:
{
return 7;
}
case 1537:
{
return 8;
}
case 1714:
{
return 9;
}
default:
{
return 0;
}
}
}
public static boolean townHasCastleInSiege(int townId)
{
final int castleIndex = getTownCastle(townId);
if (castleIndex > 0)
{
final Castle castle = CastleManager.getInstance().getCastles().get(CastleManager.getInstance().getCastleIndex(castleIndex));
if (castle != null)
{
return castle.getSiege().isInProgress();
}
}
return false;
}
public static boolean townHasCastleInSiege(int x, int y)
{
return townHasCastleInSiege(MapRegionManager.getInstance().getMapRegionLocId(x, y));
}
public static L2TownZone getTown(int townId)
{
for (L2TownZone temp : ZoneManager.getInstance().getAllZones(L2TownZone.class))
{
if (temp.getTownId() == townId)
{
return temp;
}
}
return null;
}
/**
* Returns the town at that position (if any)
* @param x
* @param y
* @param z
* @return
*/
public static L2TownZone getTown(int x, int y, int z)
{
for (L2ZoneType temp : ZoneManager.getInstance().getZones(x, y, z))
{
if (temp instanceof L2TownZone)
{
return (L2TownZone) temp;
}
}
return null;
}
}
/*
* 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.instancemanager;
import com.l2jmobius.gameserver.model.entity.Castle;
import com.l2jmobius.gameserver.model.zone.L2ZoneType;
import com.l2jmobius.gameserver.model.zone.type.L2TownZone;
public final class TownManager
{
public static int getTownCastle(int townId)
{
switch (townId)
{
case 912:
return 1;
case 916:
return 2;
case 918:
return 3;
case 922:
return 4;
case 924:
return 5;
case 926:
return 6;
case 1538:
return 7;
case 1537:
return 8;
case 1714:
return 9;
default:
return 0;
}
}
public static boolean townHasCastleInSiege(int townId)
{
final int castleId = getTownCastle(townId);
if (castleId > 0)
{
final Castle castle = CastleManager.getInstance().getCastleById(castleId);
if (castle != null)
{
return castle.getSiege().isInProgress();
}
}
return false;
}
public static boolean townHasCastleInSiege(int x, int y)
{
return townHasCastleInSiege(MapRegionManager.getInstance().getMapRegionLocId(x, y));
}
public static L2TownZone getTown(int townId)
{
for (L2TownZone temp : ZoneManager.getInstance().getAllZones(L2TownZone.class))
{
if (temp.getTownId() == townId)
{
return temp;
}
}
return null;
}
/**
* Returns the town at that position (if any)
* @param x
* @param y
* @param z
* @return
*/
public static L2TownZone getTown(int x, int y, int z)
{
for (L2ZoneType temp : ZoneManager.getInstance().getZones(x, y, z))
{
if (temp instanceof L2TownZone)
{
return (L2TownZone) temp;
}
}
return null;
}
}

View File

@@ -1,464 +1,495 @@
/*
* 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.instancemanager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.tasks.StartMovingTask;
import com.l2jmobius.gameserver.model.L2NpcWalkerNode;
import com.l2jmobius.gameserver.model.L2WalkRoute;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.WalkInfo;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.tasks.npc.walker.ArrivedTask;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMoveNodeArrived;
import com.l2jmobius.gameserver.model.holders.NpcRoutesHolder;
import com.l2jmobius.gameserver.network.NpcStringId;
import com.l2jmobius.gameserver.network.serverpackets.NpcSay;
import com.l2jmobius.gameserver.util.Broadcast;
import com.l2jmobius.util.data.xml.IXmlReader;
/**
* This class manages walking monsters.
* @author GKR
*/
public final class WalkingManager implements IXmlReader
{
// Repeat style:
// -1 - no repeat
// 0 - go back
// 1 - go to first point (circle style)
// 2 - teleport to first point (conveyor style)
// 3 - random walking between points.
public static final byte NO_REPEAT = -1;
public static final byte REPEAT_GO_BACK = 0;
public static final byte REPEAT_GO_FIRST = 1;
public static final byte REPEAT_TELE_FIRST = 2;
public static final byte REPEAT_RANDOM = 3;
private final Map<String, L2WalkRoute> _routes = new HashMap<>(); // all available routes
private final Map<Integer, WalkInfo> _activeRoutes = new HashMap<>(); // each record represents NPC, moving by predefined route from _routes, and moving progress
private final Map<Integer, NpcRoutesHolder> _routesToAttach = new HashMap<>(); // each record represents NPC and all available routes for it
protected WalkingManager()
{
load();
}
@Override
public final void load()
{
parseDatapackFile("Routes.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _routes.size() + " walking routes.");
}
@Override
public void parseDocument(Document doc)
{
for (Node d = doc.getFirstChild().getFirstChild(); d != null; d = d.getNextSibling())
{
if (d.getNodeName().equals("route"))
{
final String routeName = parseString(d.getAttributes(), "name");
final boolean repeat = parseBoolean(d.getAttributes(), "repeat");
final String repeatStyle = d.getAttributes().getNamedItem("repeatStyle").getNodeValue().toLowerCase();
final byte repeatType;
switch (repeatStyle)
{
case "back":
{
repeatType = REPEAT_GO_BACK;
break;
}
case "cycle":
{
repeatType = REPEAT_GO_FIRST;
break;
}
case "conveyor":
{
repeatType = REPEAT_TELE_FIRST;
break;
}
case "random":
{
repeatType = REPEAT_RANDOM;
break;
}
default:
{
repeatType = NO_REPEAT;
break;
}
}
final List<L2NpcWalkerNode> list = new ArrayList<>();
for (Node r = d.getFirstChild(); r != null; r = r.getNextSibling())
{
if (r.getNodeName().equals("point"))
{
final NamedNodeMap attrs = r.getAttributes();
final int x = parseInteger(attrs, "X");
final int y = parseInteger(attrs, "Y");
final int z = parseInteger(attrs, "Z");
final int delay = parseInteger(attrs, "delay");
final boolean run = parseBoolean(attrs, "run");
NpcStringId npcString = null;
String chatString = null;
Node node = attrs.getNamedItem("string");
if (node != null)
{
chatString = node.getNodeValue();
}
else
{
node = attrs.getNamedItem("npcString");
if (node != null)
{
npcString = NpcStringId.getNpcStringId(node.getNodeValue());
if (npcString == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Unknown npcString '" + node.getNodeValue() + "' for route '" + routeName + "'");
continue;
}
}
else
{
node = attrs.getNamedItem("npcStringId");
if (node != null)
{
npcString = NpcStringId.getNpcStringId(Integer.parseInt(node.getNodeValue()));
if (npcString == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Unknown npcString '" + node.getNodeValue() + "' for route '" + routeName + "'");
continue;
}
}
}
}
list.add(new L2NpcWalkerNode(x, y, z, delay, run, npcString, chatString));
}
else if (r.getNodeName().equals("target"))
{
final NamedNodeMap attrs = r.getAttributes();
try
{
final int npcId = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
final int x = Integer.parseInt(attrs.getNamedItem("spawnX").getNodeValue());
final int y = Integer.parseInt(attrs.getNamedItem("spawnY").getNodeValue());
final int z = Integer.parseInt(attrs.getNamedItem("spawnZ").getNodeValue());
final NpcRoutesHolder holder = _routesToAttach.containsKey(npcId) ? _routesToAttach.get(npcId) : new NpcRoutesHolder();
holder.addRoute(routeName, new Location(x, y, z));
_routesToAttach.put(npcId, holder);
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Error in target definition for route '" + routeName + "'");
}
}
}
_routes.put(routeName, new L2WalkRoute(routeName, list, repeat, false, repeatType));
}
}
}
/**
* @param npc NPC to check
* @return {@code true} if given NPC, or its leader is controlled by Walking Manager and moves currently.
*/
public boolean isOnWalk(L2Npc npc)
{
final L2MonsterInstance monster = npc.isMonster() ? ((L2MonsterInstance) npc).getLeader() == null ? (L2MonsterInstance) npc : ((L2MonsterInstance) npc).getLeader() : null;
if (((monster != null) && !isRegistered(monster)) || !isRegistered(npc))
{
return false;
}
final WalkInfo walk = monster != null ? _activeRoutes.get(monster.getObjectId()) : _activeRoutes.get(npc.getObjectId());
return !walk.isStoppedByAttack() && !walk.isSuspended();
}
public L2WalkRoute getRoute(String route)
{
return _routes.get(route);
}
/**
* @param npc NPC to check
* @return {@code true} if given NPC controlled by Walking Manager.
*/
public boolean isRegistered(L2Npc npc)
{
return _activeRoutes.containsKey(npc.getObjectId());
}
/**
* @param npc
* @return name of route
*/
public String getRouteName(L2Npc npc)
{
return _activeRoutes.containsKey(npc.getObjectId()) ? _activeRoutes.get(npc.getObjectId()).getRoute().getName() : "";
}
/**
* Start to move given NPC by given route
* @param npc NPC to move
* @param routeName name of route to move by
*/
public void startMoving(L2Npc npc, String routeName)
{
if (_routes.containsKey(routeName) && (npc != null) && !npc.isDead()) // check, if these route and NPC present
{
if (!_activeRoutes.containsKey(npc.getObjectId())) // new walk task
{
// only if not already moved / not engaged in battle... should not happens if called on spawn
if ((npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE) || (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE))
{
final WalkInfo walk = new WalkInfo(routeName);
if (npc.isDebug())
{
walk.setLastAction(System.currentTimeMillis());
}
L2NpcWalkerNode node = walk.getCurrentNode();
// adjust next waypoint, if NPC spawns at first waypoint
if ((npc.getX() == node.getX()) && (npc.getY() == node.getY()))
{
walk.calculateNextNode(npc);
node = walk.getCurrentNode();
npc.sendDebugMessage("Route '" + routeName + "': spawn point is same with first waypoint, adjusted to next");
}
if (!npc.isInsideRadius(node, 3000, true, false))
{
final String message = "Route '" + routeName + "': NPC (id=" + npc.getId() + ", x=" + npc.getX() + ", y=" + npc.getY() + ", z=" + npc.getZ() + ") is too far from starting point (node x=" + node.getX() + ", y=" + node.getY() + ", z=" + node.getZ() + ", range=" + npc.calculateDistance(node, true, true) + "), walking will not start";
LOGGER.warning(getClass().getSimpleName() + ": " + message);
npc.sendDebugMessage(message);
return;
}
npc.sendDebugMessage("Starting to move at route '" + routeName + "'");
npc.setIsRunning(node.runToLocation());
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, node);
walk.setWalkCheckTask(ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new StartMovingTask(npc, routeName), 60000, 60000)); // start walk check task, for resuming walk after fight
npc.getKnownList().startTrackingTask();
_activeRoutes.put(npc.getObjectId(), walk); // register route
}
else
{
npc.sendDebugMessage("Failed to start moving along route '" + routeName + "', scheduled");
ThreadPoolManager.getInstance().scheduleGeneral(new StartMovingTask(npc, routeName), 60000);
}
}
// walk was stopped due to some reason (arrived to node, script action, fight or something else), resume it
else if (_activeRoutes.containsKey(npc.getObjectId()) && ((npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE) || (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)))
{
final WalkInfo walk = _activeRoutes.get(npc.getObjectId());
if (walk == null)
{
return;
}
// Prevent call simultaneously from scheduled task and onArrived() or temporarily stop walking for resuming in future
if (walk.isBlocked() || walk.isSuspended())
{
npc.sendDebugMessage("Failed to continue moving along route '" + routeName + "' (operation is blocked)");
return;
}
walk.setBlocked(true);
final L2NpcWalkerNode node = walk.getCurrentNode();
npc.sendDebugMessage("Route '" + routeName + "', continuing to node " + walk.getCurrentNodeId());
npc.setIsRunning(node.runToLocation());
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, node);
walk.setBlocked(false);
walk.setStoppedByAttack(false);
}
else
{
npc.sendDebugMessage("Failed to continue moving along route '" + routeName + "' (wrong AI state - " + npc.getAI().getIntention() + ")");
}
}
}
/**
* Cancel NPC moving permanently
* @param npc NPC to cancel
*/
public synchronized void cancelMoving(L2Npc npc)
{
final WalkInfo walk = _activeRoutes.remove(npc.getObjectId());
if (walk == null)
{
return;
}
walk.getWalkCheckTask().cancel(true);
npc.getKnownList().stopTrackingTask();
}
/**
* Resumes previously stopped moving
* @param npc NPC to resume
*/
public void resumeMoving(L2Npc npc)
{
final WalkInfo walk = _activeRoutes.get(npc.getObjectId());
if (walk == null)
{
return;
}
walk.setSuspended(false);
walk.setStoppedByAttack(false);
startMoving(npc, walk.getRoute().getName());
}
/**
* Pause NPC moving until it will be resumed
* @param npc NPC to pause moving
* @param suspend {@code true} if moving was temporarily suspended for some reasons of AI-controlling script
* @param stoppedByAttack {@code true} if moving was suspended because of NPC was attacked or desired to attack
*/
public void stopMoving(L2Npc npc, boolean suspend, boolean stoppedByAttack)
{
final L2MonsterInstance monster = npc.isMonster() ? ((L2MonsterInstance) npc).getLeader() == null ? (L2MonsterInstance) npc : ((L2MonsterInstance) npc).getLeader() : null;
if (((monster != null) && !isRegistered(monster)) || !isRegistered(npc))
{
return;
}
final WalkInfo walk = monster != null ? _activeRoutes.get(monster.getObjectId()) : _activeRoutes.get(npc.getObjectId());
walk.setSuspended(suspend);
walk.setStoppedByAttack(stoppedByAttack);
if (monster != null)
{
monster.stopMove(null);
monster.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
else
{
npc.stopMove(null);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
}
/**
* Manage "node arriving"-related tasks: schedule move to next node; send ON_NODE_ARRIVED event to Quest script
* @param npc NPC to manage
*/
public void onArrived(L2Npc npc)
{
if (!_activeRoutes.containsKey(npc.getObjectId()))
{
return;
}
// Notify quest
EventDispatcher.getInstance().notifyEventAsync(new OnNpcMoveNodeArrived(npc), npc);
final WalkInfo walk = _activeRoutes.get(npc.getObjectId());
// Opposite should not happen... but happens sometime
if ((walk.getCurrentNodeId() < 0) || (walk.getCurrentNodeId() >= walk.getRoute().getNodesCount()))
{
return;
}
final L2NpcWalkerNode node = walk.getRoute().getNodeList().get(walk.getCurrentNodeId());
if (!npc.isInsideRadius(node, 10, false, false))
{
return;
}
npc.sendDebugMessage("Route '" + walk.getRoute().getName() + "', arrived to node " + walk.getCurrentNodeId());
npc.sendDebugMessage("Done in " + ((System.currentTimeMillis() - walk.getLastAction()) / 1000) + " s");
walk.calculateNextNode(npc);
walk.setBlocked(true); // prevents to be ran from walk check task, if there is delay in this node.
if (node.getNpcString() != null)
{
Broadcast.toKnownPlayers(npc, new NpcSay(npc, ChatType.NPC_GENERAL, node.getNpcString()));
}
else if (!node.getChatText().isEmpty())
{
Broadcast.toKnownPlayers(npc, new NpcSay(npc, ChatType.NPC_GENERAL, node.getChatText()));
}
if (npc.isDebug())
{
walk.setLastAction(System.currentTimeMillis());
}
ThreadPoolManager.getInstance().scheduleGeneral(new ArrivedTask(npc, walk), 100 + (node.getDelay() * 1000L));
}
/**
* Manage "on death"-related tasks: permanently cancel moving of died NPC
* @param npc NPC to manage
*/
public void onDeath(L2Npc npc)
{
cancelMoving(npc);
}
/**
* Manage "on spawn"-related tasks: start NPC moving, if there is route attached to its spawn point
* @param npc NPC to manage
*/
public void onSpawn(L2Npc npc)
{
if (_routesToAttach.containsKey(npc.getId()))
{
final String routeName = _routesToAttach.get(npc.getId()).getRouteName(npc);
if (!routeName.isEmpty())
{
startMoving(npc, routeName);
}
}
}
public static WalkingManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final WalkingManager _instance = new WalkingManager();
}
/*
* 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.instancemanager;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ai.CtrlIntention;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.instancemanager.tasks.StartMovingTask;
import com.l2jmobius.gameserver.model.L2NpcWalkerNode;
import com.l2jmobius.gameserver.model.L2WalkRoute;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.WalkInfo;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2MonsterInstance;
import com.l2jmobius.gameserver.model.actor.tasks.npc.walker.ArrivedTask;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMoveNodeArrived;
import com.l2jmobius.gameserver.model.holders.NpcRoutesHolder;
import com.l2jmobius.gameserver.network.NpcStringId;
/**
* This class manages walking monsters.
* @author GKR
*/
public final class WalkingManager implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(WalkingManager.class.getName());
// Repeat style:
// 0 - go back
// 1 - go to first point (circle style)
// 2 - teleport to first point (conveyor style)
// 3 - random walking between points.
public static final byte REPEAT_GO_BACK = 0;
public static final byte REPEAT_GO_FIRST = 1;
public static final byte REPEAT_TELE_FIRST = 2;
public static final byte REPEAT_RANDOM = 3;
private final Map<String, L2WalkRoute> _routes = new HashMap<>(); // all available routes
private final Map<Integer, WalkInfo> _activeRoutes = new HashMap<>(); // each record represents NPC, moving by predefined route from _routes, and moving progress
private final Map<Integer, NpcRoutesHolder> _routesToAttach = new HashMap<>(); // each record represents NPC and all available routes for it
protected WalkingManager()
{
load();
}
@Override
public final void load()
{
parseDatapackFile("data/Routes.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _routes.size() + " walking routes.");
}
@Override
public void parseDocument(Document doc, File f)
{
final Node n = doc.getFirstChild();
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if (d.getNodeName().equals("route"))
{
final String routeName = parseString(d.getAttributes(), "name");
final boolean repeat = parseBoolean(d.getAttributes(), "repeat");
final String repeatStyle = d.getAttributes().getNamedItem("repeatStyle").getNodeValue();
byte repeatType;
if (repeatStyle.equalsIgnoreCase("back"))
{
repeatType = REPEAT_GO_BACK;
}
else if (repeatStyle.equalsIgnoreCase("cycle"))
{
repeatType = REPEAT_GO_FIRST;
}
else if (repeatStyle.equalsIgnoreCase("conveyor"))
{
repeatType = REPEAT_TELE_FIRST;
}
else if (repeatStyle.equalsIgnoreCase("random"))
{
repeatType = REPEAT_RANDOM;
}
else
{
repeatType = -1;
}
final List<L2NpcWalkerNode> list = new ArrayList<>();
for (Node r = d.getFirstChild(); r != null; r = r.getNextSibling())
{
if (r.getNodeName().equals("point"))
{
final NamedNodeMap attrs = r.getAttributes();
final int x = parseInteger(attrs, "X");
final int y = parseInteger(attrs, "Y");
final int z = parseInteger(attrs, "Z");
final int delay = parseInteger(attrs, "delay");
final boolean run = parseBoolean(attrs, "run");
NpcStringId npcString = null;
String chatString = null;
Node node = attrs.getNamedItem("string");
if (node != null)
{
chatString = node.getNodeValue();
}
else
{
node = attrs.getNamedItem("npcString");
if (node != null)
{
npcString = NpcStringId.getNpcStringId(node.getNodeValue());
if (npcString == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Unknown npcString '" + node.getNodeValue() + "' for route '" + routeName + "'");
continue;
}
}
else
{
node = attrs.getNamedItem("npcStringId");
if (node != null)
{
npcString = NpcStringId.getNpcStringId(Integer.parseInt(node.getNodeValue()));
if (npcString == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Unknown npcString '" + node.getNodeValue() + "' for route '" + routeName + "'");
continue;
}
}
}
}
list.add(new L2NpcWalkerNode(x, y, z, delay, run, npcString, chatString));
}
else if (r.getNodeName().equals("target"))
{
final NamedNodeMap attrs = r.getAttributes();
try
{
final int npcId = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
final int x = Integer.parseInt(attrs.getNamedItem("spawnX").getNodeValue());
final int y = Integer.parseInt(attrs.getNamedItem("spawnY").getNodeValue());
final int z = Integer.parseInt(attrs.getNamedItem("spawnZ").getNodeValue());
final NpcRoutesHolder holder = _routesToAttach.containsKey(npcId) ? _routesToAttach.get(npcId) : new NpcRoutesHolder();
holder.addRoute(routeName, new Location(x, y, z));
_routesToAttach.put(npcId, holder);
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Error in target definition for route '" + routeName + "'");
}
}
}
_routes.put(routeName, new L2WalkRoute(routeName, list, repeat, false, repeatType));
}
}
}
/**
* @param npc NPC to check
* @return {@code true} if given NPC, or its leader is controlled by Walking Manager and moves currently.
*/
public boolean isOnWalk(L2Npc npc)
{
L2MonsterInstance monster = null;
if (npc.isMonster())
{
if (((L2MonsterInstance) npc).getLeader() == null)
{
monster = (L2MonsterInstance) npc;
}
else
{
monster = ((L2MonsterInstance) npc).getLeader();
}
}
if (((monster != null) && !isRegistered(monster)) || !isRegistered(npc))
{
return false;
}
final WalkInfo walk = monster != null ? _activeRoutes.get(monster.getObjectId()) : _activeRoutes.get(npc.getObjectId());
if (walk.isStoppedByAttack() || walk.isSuspended())
{
return false;
}
return true;
}
public L2WalkRoute getRoute(String route)
{
return _routes.get(route);
}
/**
* @param npc NPC to check
* @return {@code true} if given NPC controlled by Walking Manager.
*/
public boolean isRegistered(L2Npc npc)
{
return _activeRoutes.containsKey(npc.getObjectId());
}
/**
* @param npc
* @return name of route
*/
public String getRouteName(L2Npc npc)
{
return _activeRoutes.containsKey(npc.getObjectId()) ? _activeRoutes.get(npc.getObjectId()).getRoute().getName() : "";
}
/**
* Start to move given NPC by given route
* @param npc NPC to move
* @param routeName name of route to move by
*/
public void startMoving(L2Npc npc, String routeName)
{
if (_routes.containsKey(routeName) && (npc != null) && !npc.isDead()) // check, if these route and NPC present
{
if (!_activeRoutes.containsKey(npc.getObjectId())) // new walk task
{
// only if not already moved / not engaged in battle... should not happens if called on spawn
if ((npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE) || (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE))
{
final WalkInfo walk = new WalkInfo(routeName);
if (npc.isDebug())
{
walk.setLastAction(System.currentTimeMillis());
}
L2NpcWalkerNode node = walk.getCurrentNode();
// adjust next waypoint, if NPC spawns at first waypoint
if ((npc.getX() == node.getX()) && (npc.getY() == node.getY()))
{
walk.calculateNextNode(npc);
node = walk.getCurrentNode();
npc.sendDebugMessage("Route '" + routeName + "': spawn point is same with first waypoint, adjusted to next");
}
if (!npc.isInsideRadius(node, 3000, true, false))
{
final String message = "Route '" + routeName + "': NPC (id=" + npc.getId() + ", x=" + npc.getX() + ", y=" + npc.getY() + ", z=" + npc.getZ() + ") is too far from starting point (node x=" + node.getX() + ", y=" + node.getY() + ", z=" + node.getZ() + ", range=" + npc.calculateDistance(node, true, true) + "), walking will not start";
LOGGER.warning(message);
npc.sendDebugMessage(message);
return;
}
npc.sendDebugMessage("Starting to move at route '" + routeName + "'");
npc.setIsRunning(node.runToLocation());
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, node);
walk.setWalkCheckTask(ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new StartMovingTask(npc, routeName), 60000, 60000)); // start walk check task, for resuming walk after fight
_activeRoutes.put(npc.getObjectId(), walk); // register route
}
else
{
npc.sendDebugMessage("Failed to start moving along route '" + routeName + "', scheduled");
ThreadPoolManager.getInstance().scheduleGeneral(new StartMovingTask(npc, routeName), 60000);
}
}
else
// walk was stopped due to some reason (arrived to node, script action, fight or something else), resume it
{
if (_activeRoutes.containsKey(npc.getObjectId()) && ((npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_ACTIVE) || (npc.getAI().getIntention() == CtrlIntention.AI_INTENTION_IDLE)))
{
final WalkInfo walk = _activeRoutes.get(npc.getObjectId());
if (walk == null)
{
return;
}
// Prevent call simultaneously from scheduled task and onArrived() or temporarily stop walking for resuming in future
if (walk.isBlocked() || walk.isSuspended())
{
npc.sendDebugMessage("Failed to continue moving along route '" + routeName + "' (operation is blocked)");
return;
}
walk.setBlocked(true);
final L2NpcWalkerNode node = walk.getCurrentNode();
npc.sendDebugMessage("Route '" + routeName + "', continuing to node " + walk.getCurrentNodeId());
npc.setIsRunning(node.runToLocation());
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, node);
walk.setBlocked(false);
walk.setStoppedByAttack(false);
}
else
{
npc.sendDebugMessage("Failed to continue moving along route '" + routeName + "' (wrong AI state - " + npc.getAI().getIntention() + ")");
}
}
}
}
/**
* Cancel NPC moving permanently
* @param npc NPC to cancel
*/
public synchronized void cancelMoving(L2Npc npc)
{
final WalkInfo walk = _activeRoutes.remove(npc.getObjectId());
if (walk != null)
{
walk.getWalkCheckTask().cancel(true);
}
}
/**
* Resumes previously stopped moving
* @param npc NPC to resume
*/
public void resumeMoving(L2Npc npc)
{
final WalkInfo walk = _activeRoutes.get(npc.getObjectId());
if (walk != null)
{
walk.setSuspended(false);
walk.setStoppedByAttack(false);
startMoving(npc, walk.getRoute().getName());
}
}
/**
* Pause NPC moving until it will be resumed
* @param npc NPC to pause moving
* @param suspend {@code true} if moving was temporarily suspended for some reasons of AI-controlling script
* @param stoppedByAttack {@code true} if moving was suspended because of NPC was attacked or desired to attack
*/
public void stopMoving(L2Npc npc, boolean suspend, boolean stoppedByAttack)
{
L2MonsterInstance monster = null;
if (npc.isMonster())
{
if (((L2MonsterInstance) npc).getLeader() == null)
{
monster = (L2MonsterInstance) npc;
}
else
{
monster = ((L2MonsterInstance) npc).getLeader();
}
}
if (((monster != null) && !isRegistered(monster)) || !isRegistered(npc))
{
return;
}
final WalkInfo walk = monster != null ? _activeRoutes.get(monster.getObjectId()) : _activeRoutes.get(npc.getObjectId());
walk.setSuspended(suspend);
walk.setStoppedByAttack(stoppedByAttack);
if (monster != null)
{
monster.stopMove(null);
monster.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
else
{
npc.stopMove(null);
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
}
}
/**
* Manage "node arriving"-related tasks: schedule move to next node; send ON_NODE_ARRIVED event to Quest script
* @param npc NPC to manage
*/
public void onArrived(L2Npc npc)
{
if (_activeRoutes.containsKey(npc.getObjectId()))
{
// Notify quest
EventDispatcher.getInstance().notifyEventAsync(new OnNpcMoveNodeArrived(npc), npc);
final WalkInfo walk = _activeRoutes.get(npc.getObjectId());
// Opposite should not happen... but happens sometime
if ((walk.getCurrentNodeId() >= 0) && (walk.getCurrentNodeId() < walk.getRoute().getNodesCount()))
{
final L2NpcWalkerNode node = walk.getRoute().getNodeList().get(walk.getCurrentNodeId());
if (npc.isInsideRadius(node, 10, false, false))
{
npc.sendDebugMessage("Route '" + walk.getRoute().getName() + "', arrived to node " + walk.getCurrentNodeId());
npc.sendDebugMessage("Done in " + ((System.currentTimeMillis() - walk.getLastAction()) / 1000) + " s");
if (!walk.calculateNextNode(npc))
{
return;
}
walk.setBlocked(true); // prevents to be ran from walk check task, if there is delay in this node.
if (node.getNpcString() != null)
{
npc.broadcastSay(ChatType.NPC_GENERAL, node.getNpcString());
}
else if (!node.getChatText().isEmpty())
{
npc.broadcastSay(ChatType.NPC_GENERAL, node.getChatText());
}
if (npc.isDebug())
{
walk.setLastAction(System.currentTimeMillis());
}
if (_activeRoutes.containsKey(npc.getObjectId()))
{
if (node.getDelay() > 0)
{
ThreadPoolManager.getInstance().scheduleGeneral(new ArrivedTask(npc, walk), node.getDelay() * 1000L);
}
else
{
walk.setBlocked(false);
WalkingManager.getInstance().startMoving(npc, walk.getRoute().getName());
}
}
}
}
}
}
/**
* Manage "on death"-related tasks: permanently cancel moving of died NPC
* @param npc NPC to manage
*/
public void onDeath(L2Npc npc)
{
cancelMoving(npc);
}
/**
* Manage "on spawn"-related tasks: start NPC moving, if there is route attached to its spawn point
* @param npc NPC to manage
*/
public void onSpawn(L2Npc npc)
{
if (_routesToAttach.containsKey(npc.getId()))
{
final String routeName = _routesToAttach.get(npc.getId()).getRouteName(npc);
if (!routeName.isEmpty())
{
startMoving(npc, routeName);
}
}
}
public static WalkingManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final WalkingManager _instance = new WalkingManager();
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.instancemanager;
import java.util.concurrent.ConcurrentHashMap;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.actor.L2Character;
import com.l2jmobius.gameserver.model.holders.WarpedSpaceHolder;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
import com.l2jmobius.gameserver.util.Util;
/**
* @author Sdw
*/
public class WarpedSpaceManager
{
private volatile ConcurrentHashMap<L2Character, WarpedSpaceHolder> _warpedSpace = null;
public void addWarpedSpace(L2Character creature, int radius)
{
if (_warpedSpace == null)
{
synchronized (this)
{
if (_warpedSpace == null)
{
_warpedSpace = new ConcurrentHashMap<>();
}
}
}
_warpedSpace.put(creature, new WarpedSpaceHolder(creature, radius));
}
public void removeWarpedSpace(L2Character creature)
{
_warpedSpace.remove(creature);
}
public boolean checkForWarpedSpace(AbstractNodeLoc start, AbstractNodeLoc end, Instance instance)
{
return checkForWarpedSpace(new Location(start.getX(), start.getY(), start.getZ()), new Location(end.getX(), end.getY(), end.getZ()), instance);
}
public boolean checkForWarpedSpace(Location origin, Location destination, Instance instance)
{
if (_warpedSpace != null)
{
for (WarpedSpaceHolder holder : _warpedSpace.values())
{
final L2Character creature = holder.getCreature();
if (creature.getInstanceWorld() != instance)
{
continue;
}
final int radius = creature.getTemplate().getCollisionRadius();
final boolean originInRange = Util.calculateDistance(creature, origin, false, false) <= (holder.getRange() + radius);
final boolean destinationInRange = Util.calculateDistance(creature, destination, false, false) <= (holder.getRange() + radius);
return destinationInRange ? !originInRange : originInRange;
}
}
return false;
}
public static WarpedSpaceManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final WarpedSpaceManager _instance = new WarpedSpaceManager();
}
}

View File

@@ -1,53 +1,68 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.instancemanager.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change entry time task.
* @author xban1x
*/
public final class FourSepulchersChangeEntryTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(true);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(false);
manager.setIsCoolDownTime(false);
final long interval = manager.isFirstTimeRun() ? manager.getEntrytTimeEnd() - Calendar.getInstance().getTimeInMillis() : Config.FS_TIME_ENTRY * 60000L;
// launching saying process...
ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersManagerSayTask(), 0);
manager.setChangeWarmUpTimeTask(ThreadPoolManager.getInstance().scheduleEffect(new FourSepulchersChangeWarmUpTimeTask(), interval));
final ScheduledFuture<?> changeEntryTimeTask = manager.getChangeEntryTimeTask();
if (changeEntryTimeTask != null)
{
changeEntryTimeTask.cancel(true);
manager.setChangeEntryTimeTask(null);
}
}
}
/*
* 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.instancemanager.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change entry time task.
* @author xban1x
*/
public final class FourSepulchersChangeEntryTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(true);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(false);
manager.setIsCoolDownTime(false);
long interval = 0;
// if this is first launch - search time whFourSepulchersManager_inEntryTime = true;naFourSepulchersManager_inEntryTime = true;maen entry time will be
// ended:
// counting difference between time when entry time ends and current
// time
// and then launching change time task
if (manager.isFirstTimeRun())
{
interval = manager.getEntrytTimeEnd() - Calendar.getInstance().getTimeInMillis();
}
else
{
interval = Config.FS_TIME_ENTRY * 60000L; // else use stupid
// method
}
// launching saying process...
ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersManagerSayTask(), 0);
manager.setChangeWarmUpTimeTask(ThreadPoolManager.getInstance().scheduleEffect(new FourSepulchersChangeWarmUpTimeTask(), interval));
final ScheduledFuture<?> changeEntryTimeTask = manager.getChangeEntryTimeTask();
if (changeEntryTimeTask != null)
{
changeEntryTimeTask.cancel(true);
manager.setChangeEntryTimeTask(null);
}
}
}

View File

@@ -1,51 +1,64 @@
/*
* 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.instancemanager.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change warm up time task.
* @author xban1x
*/
public final class FourSepulchersChangeWarmUpTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(true);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(false);
manager.setIsCoolDownTime(false);
final long interval = manager.isFirstTimeRun() ? manager.getWarmUpTimeEnd() - Calendar.getInstance().getTimeInMillis() : Config.FS_TIME_WARMUP * 60000L;
manager.setChangeAttackTimeTask(ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersChangeAttackTimeTask(), interval));
final ScheduledFuture<?> changeWarmUpTimeTask = manager.getChangeWarmUpTimeTask();
if (changeWarmUpTimeTask != null)
{
changeWarmUpTimeTask.cancel(true);
manager.setChangeWarmUpTimeTask(null);
}
}
}
/*
* 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.instancemanager.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change warm up time task.
* @author xban1x
*/
public final class FourSepulchersChangeWarmUpTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(true);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(false);
manager.setIsCoolDownTime(false);
long interval = 0;
// searching time when warmup time will be ended:
// counting difference between time when warmup time ends and
// current time
// and then launching change time task
if (manager.isFirstTimeRun())
{
interval = manager.getWarmUpTimeEnd() - Calendar.getInstance().getTimeInMillis();
}
else
{
interval = Config.FS_TIME_WARMUP * 60000L;
}
manager.setChangeAttackTimeTask(ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersChangeAttackTimeTask(), interval));
final ScheduledFuture<?> changeWarmUpTimeTask = manager.getChangeWarmUpTimeTask();
if (changeWarmUpTimeTask != null)
{
changeWarmUpTimeTask.cancel(true);
manager.setChangeWarmUpTimeTask(null);
}
}
}

View File

@@ -1,84 +1,86 @@
/*
* 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.instancemanager.tasks;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.instancemanager.MailManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Message;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* Message deletion task.
* @author xban1x
*/
public final class MessageDeletionTask implements Runnable
{
private static final Logger _log = Logger.getLogger(MessageDeletionTask.class.getName());
final int _msgId;
public MessageDeletionTask(int msgId)
{
_msgId = msgId;
}
@Override
public void run()
{
final Message msg = MailManager.getInstance().getMessage(_msgId);
if (msg == null)
{
return;
}
if (msg.hasAttachments())
{
try
{
final L2PcInstance sender = L2World.getInstance().getPlayer(msg.getSenderId());
if (sender != null)
{
msg.getAttachments().returnToWh(sender.getWarehouse());
sender.sendPacket(SystemMessageId.THE_MAIL_WAS_RETURNED_DUE_TO_THE_EXCEEDED_WAITING_TIME);
}
else
{
msg.getAttachments().returnToWh(null);
}
msg.getAttachments().deleteMe();
msg.removeAttachments();
final L2PcInstance receiver = L2World.getInstance().getPlayer(msg.getReceiverId());
if (receiver != null)
{
receiver.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_MAIL_WAS_RETURNED_DUE_TO_THE_EXCEEDED_WAITING_TIME));
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error returning items:" + e.getMessage(), e);
}
}
MailManager.getInstance().deleteMessageInDb(msg.getId());
}
}
/*
* 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.instancemanager.tasks;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.gameserver.instancemanager.MailManager;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.Message;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* Message deletion task.
* @author xban1x
*/
public final class MessageDeletionTask implements Runnable
{
private static final Logger _log = Logger.getLogger(MessageDeletionTask.class.getName());
final int _msgId;
public MessageDeletionTask(int msgId)
{
_msgId = msgId;
}
@Override
public void run()
{
final Message msg = MailManager.getInstance().getMessage(_msgId);
if (msg == null)
{
return;
}
if (msg.hasAttachments())
{
try
{
final L2PcInstance sender = L2World.getInstance().getPlayer(msg.getSenderId());
if (sender != null)
{
msg.getAttachments().returnToWh(sender.getWarehouse());
sender.sendPacket(SystemMessageId.THE_MAIL_WAS_RETURNED_DUE_TO_THE_EXCEEDED_WAITING_TIME);
}
else
{
msg.getAttachments().returnToWh(null);
}
msg.getAttachments().deleteMe();
msg.removeAttachments();
final L2PcInstance receiver = L2World.getInstance().getPlayer(msg.getReceiverId());
if (receiver != null)
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.THE_MAIL_WAS_RETURNED_DUE_TO_THE_EXCEEDED_WAITING_TIME);
// sm.addString(msg.getReceiverName());
receiver.sendPacket(sm);
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error returning items:" + e.getMessage(), e);
}
}
MailManager.getInstance().deleteMessageInDb(msg.getId());
}
}