actual freya branch

This commit is contained in:
2026-09-12 15:41:31 +00:00
parent 8049e0a882
commit 68c1cd27d4
3510 changed files with 336689 additions and 302906 deletions
@@ -0,0 +1,366 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntObjectHashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.VehiclePathPoint;
import com.l2jserver.gameserver.model.actor.instance.L2AirShipInstance;
import com.l2jserver.gameserver.model.actor.instance.L2ControllableAirShipInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.ExAirShipTeleportList;
import com.l2jserver.gameserver.templates.StatsSet;
import com.l2jserver.gameserver.templates.chars.L2CharTemplate;
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 TIntObjectHashMap<StatsSet> _airShipsInfo = new TIntObjectHashMap<>();
private final TIntObjectHashMap<L2AirShipInstance> _airShips = new TIntObjectHashMap<>();
private final TIntObjectHashMap<AirShipTeleportList> _teleports = new TIntObjectHashMap<>();
public static final AirShipManager getInstance()
{
return SingletonHolder._instance;
}
private AirShipManager()
{
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(IdFactory.getInstance().getNextId(), _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(IdFactory.getInstance().getNextId(), _airShipTemplate, ownerId);
_airShips.put(ownerId, airShip);
airShip.setMaxFuel(600);
airShip.setFuel(info.getInteger("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.contains(ownerId);
}
public void registerLicense(int ownerId)
{
if (!_airShipsInfo.contains(ownerId))
{
final StatsSet info = new StatsSet();
info.set("fuel", 600);
_airShipsInfo.put(ownerId, info);
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(ADD_DB);
statement.setInt(1, ownerId);
statement.setInt(2, info.getInteger("fuel"));
statement.executeUpdate();
statement.close();
}
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);
}
finally
{
L2DatabaseFactory.close(con);
}
}
}
public boolean hasAirShip(int ownerId)
{
final L2AirShipInstance ship = _airShips.get(ownerId);
if ((ship == null) || !(ship.isVisible() || 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;
}
int dockId = ship.getDockId();
if (!_teleports.contains(dockId))
{
return;
}
final AirShipTeleportList all = _teleports.get(dockId);
player.sendPacket(new ExAirShipTeleportList(all.location, all.routes, all.fuel));
}
public VehiclePathPoint[] getTeleportDestination(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
if (all == null)
{
return null;
}
if ((index < -1) || (index >= all.routes.length))
{
return null;
}
return all.routes[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.fuel.length))
{
return 0;
}
return all.fuel[index + 1];
}
private void load()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(LOAD_DB);
ResultSet rset = statement.executeQuery();
while (rset.next())
{
StatsSet info = new StatsSet();
info.set("fuel", rset.getInt("fuel"));
_airShipsInfo.put(rset.getInt("owner_id"), info);
info = null;
}
rset.close();
statement.close();
}
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);
}
finally
{
L2DatabaseFactory.close(con);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _airShipsInfo.size() + " private airships");
}
private void storeInDb(int ownerId)
{
StatsSet info = _airShipsInfo.get(ownerId);
if (info == null)
{
return;
}
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(UPDATE_DB);
statement.setInt(1, info.getInteger("fuel"));
statement.setInt(2, ownerId);
statement.executeUpdate();
statement.close();
}
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);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private static class AirShipTeleportList
{
public int location;
public int[] fuel;
public VehiclePathPoint[][] routes;
public AirShipTeleportList(int loc, int[] f, VehiclePathPoint[][] r)
{
location = loc;
fuel = f;
routes = r;
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final AirShipManager _instance = new AirShipManager();
}
}
@@ -0,0 +1,337 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntObjectHashMap;
import gnu.trove.TObjectProcedure;
import java.util.Map;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.L2GameClient;
public class AntiFeedManager
{
public static final int GAME_ID = 0;
public static final int OLYMPIAD_ID = 1;
public static final int TVT_ID = 2;
private final Map<Integer, Long> _lastDeathTimes;
private final TIntObjectHashMap<Map<Integer, Connections>> _eventIPs;
public static final AntiFeedManager getInstance()
{
return SingletonHolder._instance;
}
private AntiFeedManager()
{
_lastDeathTimes = new FastMap<Integer, Long>().shared();
_eventIPs = new TIntObjectHashMap<>();
}
/**
* 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.L2JMOD_ANTIFEED_ENABLE)
{
return true;
}
if (target == null)
{
return false;
}
final L2PcInstance targetPlayer = target.getActingPlayer();
if (targetPlayer == null)
{
return false;
}
if ((Config.L2JMOD_ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId()))
{
return (System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) > Config.L2JMOD_ANTIFEED_INTERVAL;
}
if (Config.L2JMOD_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.L2JMOD_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)
{
if (!_eventIPs.containsKey(eventId))
{
_eventIPs.put(eventId, new FastMap<Integer, Connections>());
}
}
/**
* If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true. Returns false if number of all simultaneous connections from player's IP address higher than max.
* @param eventId
* @param player
* @param max
* @return
*/
public final boolean tryAddPlayer(int eventId, L2PcInstance player, int max)
{
return tryAddClient(eventId, player.getClient(), max);
}
/**
* If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true. Returns false if number of all simultaneous connections from player's IP address higher than max.
* @param eventId
* @param player
* @param max
* @return
*/
public final boolean tryAddClient(int eventId, L2GameClient client, int max)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, Connections> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
int limit = Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash);
limit = limit < 0 ? Integer.MAX_VALUE : limit + max;
Connections conns;
synchronized (event)
{
conns = event.get(addrHash);
if (conns == null)
{
conns = new Connections();
event.put(addrHash, conns);
}
}
return conns.testAndIncrement(limit);
}
/**
* Decreasing number of active connection from player's IP address Returns true if success and false if any problem detected.
* @param eventId
* @param player
* @return
*/
public final boolean removePlayer(int eventId, L2PcInstance player)
{
final L2GameClient client = player.getClient();
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, Connections> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
Connections conns = event.get(addrHash);
if (conns == null)
{
return false; // address not registered
}
synchronized (event)
{
if (conns.testAndDecrement())
{
event.remove(addrHash);
}
}
return true;
}
/**
* Remove player connection IP address from all registered events lists.
* @param player
*/
public final void onDisconnect(L2GameClient client)
{
if (client == null)
{
return;
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
_eventIPs.forEachValue(new DisconnectProcedure(addrHash));
}
/**
* Clear all entries for this eventId.
* @param eventId
*/
public final void clear(int eventId)
{
final Map<Integer, Connections> event = _eventIPs.get(eventId);
if (event != null)
{
event.clear();
}
}
/**
* Returns maximum number of allowed connections (whitelist + max)
* @param player
* @param max
* @return
*/
public final int getLimit(L2PcInstance player, int max)
{
return getLimit(player.getClient(), max);
}
/**
* Returns maximum number of allowed connections (whitelist + max)
* @param client
* @param max
* @return
*/
public final int getLimit(L2GameClient client, int max)
{
if (client == null)
{
return max;
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
final int limit = Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash);
return limit < 0 ? 0 : limit + max;
}
protected static final class Connections
{
private int _num = 0;
/**
* Returns true if successfully incremented number of connections and false if maximum number is reached.
*/
public final synchronized boolean testAndIncrement(int max)
{
if (_num < max)
{
_num++;
return true;
}
return false;
}
/**
* Returns true if all connections are removed
*/
public final synchronized boolean testAndDecrement()
{
if (_num > 0)
{
_num--;
}
return _num == 0;
}
}
private static final class DisconnectProcedure implements TObjectProcedure<Map<Integer, Connections>>
{
private final Integer _addrHash;
public DisconnectProcedure(Integer addrHash)
{
_addrHash = addrHash;
}
@Override
public final boolean execute(Map<Integer, Connections> event)
{
final Connections conns = event.get(_addrHash);
if (conns != null)
{
synchronized (event)
{
if (conns.testAndDecrement())
{
event.remove(_addrHash);
}
}
}
return true;
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final AntiFeedManager _instance = new AntiFeedManager();
}
}
@@ -0,0 +1,233 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.entity.Auction;
public class AuctionManager
{
protected static final Logger _log = Logger.getLogger(AuctionManager.class.getName());
private final List<Auction> _auctions;
private static final String[] ITEM_INIT_DATA =
{
"(22, 0, 'NPC', 'NPC Clan', 'ClanHall', 22, 0, 'Moonstone Hall', 1, 20000000, 0, 1164841200000)",
"(23, 0, 'NPC', 'NPC Clan', 'ClanHall', 23, 0, 'Onyx Hall', 1, 20000000, 0, 1164841200000)",
"(24, 0, 'NPC', 'NPC Clan', 'ClanHall', 24, 0, 'Topaz Hall', 1, 20000000, 0, 1164841200000)",
"(25, 0, 'NPC', 'NPC Clan', 'ClanHall', 25, 0, 'Ruby Hall', 1, 20000000, 0, 1164841200000)",
"(26, 0, 'NPC', 'NPC Clan', 'ClanHall', 26, 0, 'Crystal Hall', 1, 20000000, 0, 1164841200000)",
"(27, 0, 'NPC', 'NPC Clan', 'ClanHall', 27, 0, 'Onyx Hall', 1, 20000000, 0, 1164841200000)",
"(28, 0, 'NPC', 'NPC Clan', 'ClanHall', 28, 0, 'Sapphire Hall', 1, 20000000, 0, 1164841200000)",
"(29, 0, 'NPC', 'NPC Clan', 'ClanHall', 29, 0, 'Moonstone Hall', 1, 20000000, 0, 1164841200000)",
"(30, 0, 'NPC', 'NPC Clan', 'ClanHall', 30, 0, 'Emerald Hall', 1, 20000000, 0, 1164841200000)",
"(31, 0, 'NPC', 'NPC Clan', 'ClanHall', 31, 0, 'The Atramental Barracks', 1, 8000000, 0, 1164841200000)",
"(32, 0, 'NPC', 'NPC Clan', 'ClanHall', 32, 0, 'The Scarlet Barracks', 1, 8000000, 0, 1164841200000)",
"(33, 0, 'NPC', 'NPC Clan', 'ClanHall', 33, 0, 'The Viridian Barracks', 1, 8000000, 0, 1164841200000)",
"(36, 0, 'NPC', 'NPC Clan', 'ClanHall', 36, 0, 'The Golden Chamber', 1, 50000000, 0, 1164841200000)",
"(37, 0, 'NPC', 'NPC Clan', 'ClanHall', 37, 0, 'The Silver Chamber', 1, 50000000, 0, 1164841200000)",
"(38, 0, 'NPC', 'NPC Clan', 'ClanHall', 38, 0, 'The Mithril Chamber', 1, 50000000, 0, 1164841200000)",
"(39, 0, 'NPC', 'NPC Clan', 'ClanHall', 39, 0, 'Silver Manor', 1, 50000000, 0, 1164841200000)",
"(40, 0, 'NPC', 'NPC Clan', 'ClanHall', 40, 0, 'Gold Manor', 1, 50000000, 0, 1164841200000)",
"(41, 0, 'NPC', 'NPC Clan', 'ClanHall', 41, 0, 'The Bronze Chamber', 1, 50000000, 0, 1164841200000)",
"(42, 0, 'NPC', 'NPC Clan', 'ClanHall', 42, 0, 'The Golden Chamber', 1, 50000000, 0, 1164841200000)",
"(43, 0, 'NPC', 'NPC Clan', 'ClanHall', 43, 0, 'The Silver Chamber', 1, 50000000, 0, 1164841200000)",
"(44, 0, 'NPC', 'NPC Clan', 'ClanHall', 44, 0, 'The Mithril Chamber', 1, 50000000, 0, 1164841200000)",
"(45, 0, 'NPC', 'NPC Clan', 'ClanHall', 45, 0, 'The Bronze Chamber', 1, 50000000, 0, 1164841200000)",
"(46, 0, 'NPC', 'NPC Clan', 'ClanHall', 46, 0, 'Silver Manor', 1, 50000000, 0, 1164841200000)",
"(47, 0, 'NPC', 'NPC Clan', 'ClanHall', 47, 0, 'Moonstone Hall', 1, 50000000, 0, 1164841200000)",
"(48, 0, 'NPC', 'NPC Clan', 'ClanHall', 48, 0, 'Onyx Hall', 1, 50000000, 0, 1164841200000)",
"(49, 0, 'NPC', 'NPC Clan', 'ClanHall', 49, 0, 'Emerald Hall', 1, 50000000, 0, 1164841200000)",
"(50, 0, 'NPC', 'NPC Clan', 'ClanHall', 50, 0, 'Sapphire Hall', 1, 50000000, 0, 1164841200000)",
"(51, 0, 'NPC', 'NPC Clan', 'ClanHall', 51, 0, 'Mont Chamber', 1, 50000000, 0, 1164841200000)",
"(52, 0, 'NPC', 'NPC Clan', 'ClanHall', 52, 0, 'Astaire Chamber', 1, 50000000, 0, 1164841200000)",
"(53, 0, 'NPC', 'NPC Clan', 'ClanHall', 53, 0, 'Aria Chamber', 1, 50000000, 0, 1164841200000)",
"(54, 0, 'NPC', 'NPC Clan', 'ClanHall', 54, 0, 'Yiana Chamber', 1, 50000000, 0, 1164841200000)",
"(55, 0, 'NPC', 'NPC Clan', 'ClanHall', 55, 0, 'Roien Chamber', 1, 50000000, 0, 1164841200000)",
"(56, 0, 'NPC', 'NPC Clan', 'ClanHall', 56, 0, 'Luna Chamber', 1, 50000000, 0, 1164841200000)",
"(57, 0, 'NPC', 'NPC Clan', 'ClanHall', 57, 0, 'Traban Chamber', 1, 50000000, 0, 1164841200000)",
"(58, 0, 'NPC', 'NPC Clan', 'ClanHall', 58, 0, 'Eisen Hall', 1, 50000000, 0, 1164841200000)",
"(59, 0, 'NPC', 'NPC Clan', 'ClanHall', 59, 0, 'Heavy Metal Hall', 1, 50000000, 0, 1164841200000)",
"(60, 0, 'NPC', 'NPC Clan', 'ClanHall', 60, 0, 'Molten Ore Hall', 1, 50000000, 0, 1164841200000)",
"(61, 0, 'NPC', 'NPC Clan', 'ClanHall', 61, 0, 'Titan Hall', 1, 50000000, 0, 1164841200000)"
};
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
};
public static final AuctionManager getInstance()
{
return SingletonHolder._instance;
}
private AuctionManager()
{
_log.info("Initializing AuctionManager");
_auctions = new FastList<>();
load();
}
public void reload()
{
_auctions.clear();
load();
}
private final void load()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id FROM auction ORDER BY id");
ResultSet rs = statement.executeQuery();
while (rs.next())
{
_auctions.add(new Auction(rs.getInt("id")));
}
rs.close();
statement.close();
_log.info("Loaded: " + getAuctions().size() + " auction(s)");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: AuctionManager.load(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final Auction getAuction(int auctionId)
{
int index = getAuctionIndex(auctionId);
if (index >= 0)
{
return getAuctions().get(index);
}
return null;
}
public final int getAuctionIndex(int auctionId)
{
Auction auction;
for (int i = 0; i < getAuctions().size(); i++)
{
auction = getAuctions().get(i);
if ((auction != null) && (auction.getId() == auctionId))
{
return i;
}
}
return -1;
}
public final List<Auction> getAuctions()
{
return _auctions;
}
/** Init Clan NPC aution */
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("Clan Hall auction not found for Id :" + id);
return;
}
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO `auction` VALUES " + ITEM_INIT_DATA[i]);
statement.execute();
statement.close();
_auctions.add(new Auction(id));
_log.info("Created auction for ClanHall: " + id);
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: Auction.initNPC(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final AuctionManager _instance = new AuctionManager();
}
}
@@ -0,0 +1,229 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.util.Collection;
import java.util.Map;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.VehiclePathPoint;
import com.l2jserver.gameserver.model.actor.instance.L2BoatInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.templates.StatsSet;
import com.l2jserver.gameserver.templates.chars.L2CharTemplate;
public class BoatManager
{
private final Map<Integer, L2BoatInstance> _boats = new FastMap<>();
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 final BoatManager getInstance()
{
return SingletonHolder._instance;
}
private 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;
}
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);
L2CharTemplate template = new L2CharTemplate(npcDat);
L2BoatInstance boat = new L2BoatInstance(IdFactory.getInstance().getNextId(), 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
*/
public void broadcastPacket(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket packet)
{
double dx, dy;
final Collection<L2PcInstance> players = L2World.getInstance().getAllPlayers().values();
for (L2PcInstance player : players)
{
if (player == null)
{
continue;
}
dx = (double) player.getX() - point1.x;
dy = (double) player.getY() - point1.y;
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
player.sendPacket(packet);
}
else
{
dx = (double) player.getX() - point2.x;
dy = (double) player.getY() - point2.y;
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
player.sendPacket(packet);
}
}
}
}
/**
* Broadcast several packets in both path points
*/
public void broadcastPackets(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket... packets)
{
double dx, dy;
final Collection<L2PcInstance> players = L2World.getInstance().getAllPlayers().values();
for (L2PcInstance player : players)
{
if (player == null)
{
continue;
}
dx = (double) player.getX() - point1.x;
dy = (double) player.getY() - point1.y;
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (L2GameServerPacket p : packets)
{
player.sendPacket(p);
}
}
else
{
dx = (double) player.getX() - point2.x;
dy = (double) player.getY() - point2.y;
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (L2GameServerPacket p : packets)
{
player.sendPacket(p);
}
}
}
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final BoatManager _instance = new BoatManager();
}
}
@@ -0,0 +1,356 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.InstanceListManager;
import com.l2jserver.gameserver.SevenSigns;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2ClanMember;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
public class CastleManager implements InstanceListManager
{
protected static final Logger _log = Logger.getLogger(CastleManager.class.getName());
public static final CastleManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// =========================================================
// Data Field
private List<Castle> _castles;
// =========================================================
// Constructor
private static final int _castleCirclets[] =
{
0,
6838,
6835,
6839,
6837,
6840,
6834,
6836,
8182,
8183
};
private CastleManager()
{
}
// =========================================================
// Method - Public
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 < getCastles().size(); i++)
{
castle = getCastles().get(i);
if (castle == null)
{
continue;
}
distance = castle.getDistance(obj);
if (maxDistance > distance)
{
maxDistance = (long) distance;
index = i;
}
}
}
return index;
}
// =========================================================
// Property - Public
public final Castle getCastleById(int castleId)
{
for (Castle temp : getCastles())
{
if (temp.getCastleId() == castleId)
{
return temp;
}
}
return null;
}
public final Castle getCastleByOwner(L2Clan clan)
{
for (Castle temp : getCastles())
{
if (temp.getOwnerId() == clan.getClanId())
{
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 int getCastleIndex(int castleId)
{
Castle castle;
for (int i = 0; i < getCastles().size(); i++)
{
castle = getCastles().get(i);
if ((castle != null) && (castle.getCastleId() == 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 < getCastles().size(); i++)
{
castle = getCastles().get(i);
if ((castle != null) && castle.checkIfInZone(x, y, z))
{
return i;
}
}
return -1;
}
public final List<Castle> getCastles()
{
if (_castles == null)
{
_castles = new FastList<>();
}
return _castles;
}
public final void validateTaxes(int sealStrifeOwner)
{
int maxTax;
switch (sealStrifeOwner)
{
case SevenSigns.CABAL_DUSK:
maxTax = 5;
break;
case SevenSigns.CABAL_DAWN:
maxTax = 25;
break;
default: // no owner
maxTax = 15;
break;
}
for (Castle castle : _castles)
{
if (castle.getTaxPercent() > maxTax)
{
castle.setTaxPercent(maxTax);
}
}
}
int _castleId = 1; // from this castle
public int getCirclet()
{
return getCircletByCastleId(_castleId);
}
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;
}
L2PcInstance player = member.getPlayerInstance();
int circletId = getCircletByCastleId(castleId);
if (circletId != 0)
{
// online-player circlet removal
if (player != null)
{
try
{
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
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM items WHERE owner_id = ? and item_id = ?");
statement.setInt(1, member.getObjectId());
statement.setInt(2, circletId);
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Failed to remove castle circlets offline for player " + member.getName() + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
}
@Override
public void loadInstances()
{
_log.info("Initializing CastleManager");
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id FROM castle ORDER BY id");
ResultSet rs = statement.executeQuery();
while (rs.next())
{
getCastles().add(new Castle(rs.getInt("id")));
}
statement.close();
_log.info("Loaded: " + getCastles().size() + " castles");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadCastleData(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (final Castle castle : _castles)
{
castle.activateInstance();
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final CastleManager _instance = new CastleManager();
}
}
@@ -0,0 +1,625 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.model.ClanWarehouse;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Manor;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.itemcontainer.ItemContainer;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
/**
* Class For Castle Manor Manager Load manor data from DB Update/Reload/Delete Handles all schedule for manor
* @author l3x
*/
public class CastleManorManager
{
protected static final Logger _log = Logger.getLogger(CastleManorManager.class.getName());
public static final int PERIOD_CURRENT = 0;
public static final int PERIOD_NEXT = 1;
private static final String CASTLE_MANOR_LOAD_PROCURE = "SELECT * FROM castle_manor_procure WHERE castle_id=?";
private static final String CASTLE_MANOR_LOAD_PRODUCTION = "SELECT * FROM castle_manor_production WHERE castle_id=?";
private static final int NEXT_PERIOD_APPROVE = Config.ALT_MANOR_APPROVE_TIME; // 6:00
private static final int NEXT_PERIOD_APPROVE_MIN = Config.ALT_MANOR_APPROVE_MIN; //
private static final int MANOR_REFRESH = Config.ALT_MANOR_REFRESH_TIME; // 20:00
private static final int MANOR_REFRESH_MIN = Config.ALT_MANOR_REFRESH_MIN; //
protected static final long MAINTENANCE_PERIOD = Config.ALT_MANOR_MAINTENANCE_PERIOD; // 6 mins
private Calendar _manorRefresh;
private Calendar _periodApprove;
private boolean _underMaintenance;
private boolean _disabled;
protected ScheduledFuture<?> _scheduledManorRefresh;
protected ScheduledFuture<?> _scheduledMaintenanceEnd;
protected ScheduledFuture<?> _scheduledNextPeriodapprove;
public static final CastleManorManager getInstance()
{
return SingletonHolder._instance;
}
public static class CropProcure
{
final int _cropId;
long _buyResidual;
final int _rewardType;
final long _buy;
final long _price;
public CropProcure(int id)
{
_cropId = id;
_buyResidual = 0;
_rewardType = 0;
_buy = 0;
_price = 0;
}
public CropProcure(int id, long amount, int type, long buy, long price)
{
_cropId = id;
_buyResidual = amount;
_rewardType = type;
_buy = buy;
_price = price;
}
public int getReward()
{
return _rewardType;
}
public int getId()
{
return _cropId;
}
public long getAmount()
{
return _buyResidual;
}
public long getStartAmount()
{
return _buy;
}
public long getPrice()
{
return _price;
}
public void setAmount(long amount)
{
_buyResidual = amount;
}
}
public static class SeedProduction
{
final int _seedId;
long _residual;
final long _price;
final long _sales;
public SeedProduction(int id)
{
_seedId = id;
_residual = 0;
_price = 0;
_sales = 0;
}
public SeedProduction(int id, long amount, long price, long sales)
{
_seedId = id;
_residual = amount;
_price = price;
_sales = sales;
}
public int getId()
{
return _seedId;
}
public long getCanProduce()
{
return _residual;
}
public long getPrice()
{
return _price;
}
public long getStartProduce()
{
return _sales;
}
public void setCanProduce(long amount)
{
_residual = amount;
}
}
private CastleManorManager()
{
_log.info("Initializing CastleManorManager");
load(); // load data from database
init(); // schedule all manor related events
_underMaintenance = false;
_disabled = !Config.ALLOW_MANOR;
boolean isApproved;
if (_periodApprove.getTimeInMillis() > _manorRefresh.getTimeInMillis())
{
// Next approve period already scheduled
isApproved = (_manorRefresh.getTimeInMillis() > Calendar.getInstance().getTimeInMillis());
}
else
{
isApproved = ((_periodApprove.getTimeInMillis() < Calendar.getInstance().getTimeInMillis()) && (_manorRefresh.getTimeInMillis() > Calendar.getInstance().getTimeInMillis()));
}
for (Castle c : CastleManager.getInstance().getCastles())
{
c.setNextPeriodApproved(isApproved);
}
}
private void load()
{
Connection con = null;
ResultSet rs;
try
{
// Get Connection
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statementProduction = con.prepareStatement(CASTLE_MANOR_LOAD_PRODUCTION);
PreparedStatement statementProcure = con.prepareStatement(CASTLE_MANOR_LOAD_PROCURE);
for (Castle castle : CastleManager.getInstance().getCastles())
{
FastList<SeedProduction> production = new FastList<>();
FastList<SeedProduction> productionNext = new FastList<>();
FastList<CropProcure> procure = new FastList<>();
FastList<CropProcure> procureNext = new FastList<>();
// restore seed production info
statementProduction.setInt(1, castle.getCastleId());
rs = statementProduction.executeQuery();
statementProduction.clearParameters();
while (rs.next())
{
int seedId = rs.getInt("seed_id");
int canProduce = rs.getInt("can_produce");
int startProduce = rs.getInt("start_produce");
int price = rs.getInt("seed_price");
int period = rs.getInt("period");
if (period == PERIOD_CURRENT)
{
production.add(new SeedProduction(seedId, canProduce, price, startProduce));
}
else
{
productionNext.add(new SeedProduction(seedId, canProduce, price, startProduce));
}
}
rs.close();
castle.setSeedProduction(production, PERIOD_CURRENT);
castle.setSeedProduction(productionNext, PERIOD_NEXT);
// restore procure info
statementProcure.setInt(1, castle.getCastleId());
rs = statementProcure.executeQuery();
statementProcure.clearParameters();
while (rs.next())
{
int cropId = rs.getInt("crop_id");
int canBuy = rs.getInt("can_buy");
int startBuy = rs.getInt("start_buy");
int rewardType = rs.getInt("reward_type");
int price = rs.getInt("price");
int period = rs.getInt("period");
if (period == PERIOD_CURRENT)
{
procure.add(new CropProcure(cropId, canBuy, rewardType, startBuy, price));
}
else
{
procureNext.add(new CropProcure(cropId, canBuy, rewardType, startBuy, price));
}
}
rs.close();
castle.setCropProcure(procure, PERIOD_CURRENT);
castle.setCropProcure(procureNext, PERIOD_NEXT);
if (!procure.isEmpty() || !procureNext.isEmpty() || !production.isEmpty() || !productionNext.isEmpty())
{
_log.info(castle.getName() + ": Data loaded");
}
}
statementProduction.close();
statementProcure.close();
}
catch (Exception e)
{
_log.info("Error restoring manor data: " + e.getMessage());
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void init()
{
_manorRefresh = Calendar.getInstance();
_manorRefresh.set(Calendar.HOUR_OF_DAY, MANOR_REFRESH);
_manorRefresh.set(Calendar.MINUTE, MANOR_REFRESH_MIN);
_periodApprove = Calendar.getInstance();
_periodApprove.set(Calendar.HOUR_OF_DAY, NEXT_PERIOD_APPROVE);
_periodApprove.set(Calendar.MINUTE, NEXT_PERIOD_APPROVE_MIN);
updateManorRefresh();
updatePeriodApprove();
}
public void updateManorRefresh()
{
_log.info("Manor System: Manor refresh updated");
_scheduledManorRefresh = ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (!isDisabled())
{
setUnderMaintenance(true);
_log.info("Manor System: Under maintenance mode started");
_scheduledMaintenanceEnd = ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
_log.info("Manor System: Next period started");
setNextPeriod();
try
{
save();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Manor System: Failed to save manor data: " + e.getMessage(), e);
}
setUnderMaintenance(false);
}, MAINTENANCE_PERIOD);
}
updateManorRefresh();
}, getMillisToManorRefresh());
}
public void updatePeriodApprove()
{
_log.info("Manor System: Manor period approve updated");
_scheduledNextPeriodapprove = ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (!isDisabled())
{
approveNextPeriod();
_log.info("Manor System: Next period approved");
}
updatePeriodApprove();
}, getMillisToNextPeriodApprove());
}
public long getMillisToManorRefresh()
{
// use safe interval 120s to prevent double run
if ((_manorRefresh.getTimeInMillis() - Calendar.getInstance().getTimeInMillis()) < 120000)
{
setNewManorRefresh();
}
_log.info("Manor System: New Schedule for manor refresh @ " + _manorRefresh.getTime());
return (_manorRefresh.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
}
public void setNewManorRefresh()
{
_manorRefresh = Calendar.getInstance();
_manorRefresh.set(Calendar.HOUR_OF_DAY, MANOR_REFRESH);
_manorRefresh.set(Calendar.MINUTE, MANOR_REFRESH_MIN);
_manorRefresh.set(Calendar.SECOND, 0);
_manorRefresh.add(Calendar.HOUR_OF_DAY, 24);
}
public long getMillisToNextPeriodApprove()
{
// use safe interval 120s to prevent double run
if ((_periodApprove.getTimeInMillis() - Calendar.getInstance().getTimeInMillis()) < 120000)
{
setNewPeriodApprove();
}
_log.info("Manor System: New Schedule for period approve @ " + _periodApprove.getTime());
return (_periodApprove.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
}
public void setNewPeriodApprove()
{
_periodApprove = Calendar.getInstance();
_periodApprove.set(Calendar.HOUR_OF_DAY, NEXT_PERIOD_APPROVE);
_periodApprove.set(Calendar.MINUTE, NEXT_PERIOD_APPROVE_MIN);
_periodApprove.set(Calendar.SECOND, 0);
_periodApprove.add(Calendar.HOUR_OF_DAY, 24);
}
public void setNextPeriod()
{
for (Castle c : CastleManager.getInstance().getCastles())
{
if (c.getOwnerId() <= 0)
{
continue;
}
L2Clan clan = ClanTable.getInstance().getClan(c.getOwnerId());
if (clan == null)
{
continue;
}
ItemContainer cwh = clan.getWarehouse();
if (!(cwh instanceof ClanWarehouse))
{
_log.info("Can't get clan warehouse for clan " + ClanTable.getInstance().getClan(c.getOwnerId()));
continue;
}
for (CropProcure crop : c.getCropProcure(PERIOD_CURRENT))
{
if (crop.getStartAmount() == 0)
{
continue;
}
// adding bought crops to clan warehouse
if ((crop.getStartAmount() - crop.getAmount()) > 0)
{
long count = crop.getStartAmount() - crop.getAmount();
count = (count * 90) / 100;
if (count < 1)
{
if (Rnd.nextInt(99) < 90)
{
count = 1;
}
}
if (count > 0)
{
cwh.addItem("Manor", L2Manor.getInstance().getMatureCrop(crop.getId()), count, null, null);
}
}
// reserved and not used money giving back to treasury
if (crop.getAmount() > 0)
{
c.addToTreasuryNoTax(crop.getAmount() * crop.getPrice());
}
}
c.setSeedProduction(c.getSeedProduction(PERIOD_NEXT), PERIOD_CURRENT);
c.setCropProcure(c.getCropProcure(PERIOD_NEXT), PERIOD_CURRENT);
if (c.getTreasury() < c.getManorCost(PERIOD_CURRENT))
{
c.setSeedProduction(getNewSeedsList(c.getCastleId()), PERIOD_NEXT);
c.setCropProcure(getNewCropsList(c.getCastleId()), PERIOD_NEXT);
}
else
{
FastList<SeedProduction> production = new FastList<>();
for (SeedProduction s : c.getSeedProduction(PERIOD_CURRENT))
{
s.setCanProduce(s.getStartProduce());
production.add(s);
}
c.setSeedProduction(production, PERIOD_NEXT);
FastList<CropProcure> procure = new FastList<>();
for (CropProcure cr : c.getCropProcure(PERIOD_CURRENT))
{
cr.setAmount(cr.getStartAmount());
procure.add(cr);
}
c.setCropProcure(procure, PERIOD_NEXT);
}
if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
c.saveCropData();
c.saveSeedData();
}
// Sending notification to a clan leader
L2PcInstance clanLeader = null;
clanLeader = L2World.getInstance().getPlayer(clan.getLeader().getName());
if (clanLeader != null)
{
clanLeader.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_MANOR_INFORMATION_HAS_BEEN_UPDATED));
}
c.setNextPeriodApproved(false);
}
}
public void approveNextPeriod()
{
for (Castle c : CastleManager.getInstance().getCastles())
{
boolean notFunc = false;
if (c.getOwnerId() <= 0)
{ // Castle has no owner
c.setCropProcure(new FastList<CropProcure>(), PERIOD_NEXT);
c.setSeedProduction(new FastList<SeedProduction>(), PERIOD_NEXT);
}
else if (c.getTreasury() < c.getManorCost(PERIOD_NEXT))
{
notFunc = true;
_log.info("Manor for castle " + c.getName() + " disabled, not enough adena in treasury: " + c.getTreasury() + ", " + c.getManorCost(PERIOD_NEXT) + " required.");
c.setSeedProduction(getNewSeedsList(c.getCastleId()), PERIOD_NEXT);
c.setCropProcure(getNewCropsList(c.getCastleId()), PERIOD_NEXT);
}
else
{
ItemContainer cwh = ClanTable.getInstance().getClan(c.getOwnerId()).getWarehouse();
if (!(cwh instanceof ClanWarehouse))
{
_log.info("Can't get clan warehouse for clan " + ClanTable.getInstance().getClan(c.getOwnerId()));
continue;
}
int slots = 0;
for (CropProcure crop : c.getCropProcure(PERIOD_NEXT))
{
if (crop.getStartAmount() > 0)
{
if (cwh.getItemByItemId(L2Manor.getInstance().getMatureCrop(crop.getId())) == null)
{
slots++;
}
}
}
if (!cwh.validateCapacity(slots))
{
notFunc = true;
_log.info("Manor for castle " + c.getName() + " disabled, not enough free slots in clan warehouse: " + (Config.WAREHOUSE_SLOTS_CLAN - cwh.getSize()) + ", but " + slots + " required.");
c.setSeedProduction(getNewSeedsList(c.getCastleId()), PERIOD_NEXT);
c.setCropProcure(getNewCropsList(c.getCastleId()), PERIOD_NEXT);
}
}
c.setNextPeriodApproved(true);
c.addToTreasuryNoTax((-1) * c.getManorCost(PERIOD_NEXT));
if (notFunc)
{
L2Clan clan = ClanTable.getInstance().getClan(c.getOwnerId());
L2PcInstance clanLeader = null;
if (clan != null)
{
clanLeader = L2World.getInstance().getPlayer(clan.getLeaderId());
}
if (clanLeader != null)
{
clanLeader.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THE_AMOUNT_IS_NOT_SUFFICIENT_AND_SO_THE_MANOR_IS_NOT_IN_OPERATION));
}
}
}
}
private FastList<SeedProduction> getNewSeedsList(int castleId)
{
FastList<SeedProduction> seeds = new FastList<>();
FastList<Integer> seedsIds = L2Manor.getInstance().getSeedsForCastle(castleId);
for (int sd : seedsIds)
{
seeds.add(new SeedProduction(sd));
}
return seeds;
}
private FastList<CropProcure> getNewCropsList(int castleId)
{
FastList<CropProcure> crops = new FastList<>();
FastList<Integer> cropsIds = L2Manor.getInstance().getCropsForCastle(castleId);
for (int cr : cropsIds)
{
crops.add(new CropProcure(cr));
}
return crops;
}
public boolean isUnderMaintenance()
{
return _underMaintenance;
}
public void setUnderMaintenance(boolean mode)
{
_underMaintenance = mode;
}
public boolean isDisabled()
{
return _disabled;
}
public void setDisabled(boolean mode)
{
_disabled = mode;
}
public SeedProduction getNewSeedProduction(int id, long amount, long price, long sales)
{
return new SeedProduction(id, amount, price, sales);
}
public CropProcure getNewCropProcure(int id, long amount, int type, long price, long buy)
{
return new CropProcure(id, amount, type, buy, price);
}
public void save()
{
for (Castle c : CastleManager.getInstance().getCastles())
{
c.saveSeedData();
c.saveCropData();
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final CastleManorManager _instance = new CastleManorManager();
}
}
@@ -0,0 +1,248 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.ClanTable;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.entity.Auction;
import com.l2jserver.gameserver.model.entity.ClanHall;
import com.l2jserver.gameserver.model.zone.type.L2ClanHallZone;
/**
* @author Steuf
*/
public class ClanHallManager
{
protected static final Logger _log = Logger.getLogger(ClanHallManager.class.getName());
private final Map<Integer, ClanHall> _clanHall;
private final Map<Integer, ClanHall> _freeClanHall;
private final Map<Integer, ClanHall> _allClanHalls;
private boolean _loaded = false;
public static ClanHallManager getInstance()
{
return SingletonHolder._instance;
}
public boolean loaded()
{
return _loaded;
}
private ClanHallManager()
{
_log.info("Initializing ClanHallManager");
_clanHall = new FastMap<>();
_freeClanHall = new FastMap<>();
_allClanHalls = new FastMap<>();
load();
}
/** Reload All Clan Hall */
/*
* public final void reload() Cant reload atm - would loose zone info { _clanHall.clear(); _freeClanHall.clear(); load(); }
*/
/** Load All Clan Hall */
private final void load()
{
Connection con = null;
try
{
int id, ownerId, lease, grade = 0;
String Name, Desc, Location;
long paidUntil = 0;
boolean paid = false;
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM clanhall ORDER BY id");
ResultSet rs = statement.executeQuery();
while (rs.next())
{
id = rs.getInt("id");
Name = rs.getString("name");
ownerId = rs.getInt("ownerId");
lease = rs.getInt("lease");
Desc = rs.getString("desc");
Location = rs.getString("location");
paidUntil = rs.getLong("paidUntil");
grade = rs.getInt("Grade");
paid = rs.getBoolean("paid");
ClanHall ch = new ClanHall(id, Name, ownerId, lease, Desc, Location, paidUntil, grade, paid);
_allClanHalls.put(id, ch);
if (ownerId > 0)
{
final L2Clan owner = ClanTable.getInstance().getClan(ownerId);
if (owner != null)
{
_clanHall.put(id, ch);
owner.setHasHideout(id);
continue;
}
ch.free();
}
_freeClanHall.put(id, ch);
Auction auc = AuctionManager.getInstance().getAuction(id);
if ((auc == null) && (lease > 0))
{
AuctionManager.getInstance().initNPC(id);
}
}
rs.close();
statement.close();
_log.info("Loaded: " + getClanHalls().size() + " clan halls");
_log.info("Loaded: " + getFreeClanHalls().size() + " free clan halls");
_loaded = true;
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: ClanHallManager.load(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/** Get Map with all FreeClanHalls */
public final Map<Integer, ClanHall> getFreeClanHalls()
{
return _freeClanHall;
}
/** Get Map with all ClanHalls that have owner */
public final Map<Integer, ClanHall> getClanHalls()
{
return _clanHall;
}
/** Get Map with all ClanHalls */
public final Map<Integer, ClanHall> getAllClanHalls()
{
return _allClanHalls;
}
/** Check is free ClanHall */
public final boolean isFree(int chId)
{
if (_freeClanHall.containsKey(chId))
{
return true;
}
return false;
}
/** Free a ClanHall */
public final synchronized void setFree(int chId)
{
_freeClanHall.put(chId, _clanHall.get(chId));
ClanTable.getInstance().getClan(_freeClanHall.get(chId).getOwnerId()).setHasHideout(0);
_freeClanHall.get(chId).free();
_clanHall.remove(chId);
}
/** Set ClanHallOwner */
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.getClanId()).setHasHideout(chId);
_clanHall.get(chId).setOwner(clan);
}
/** Get Clan Hall by Id */
public final ClanHall getClanHallById(int clanHallId)
{
if (_clanHall.containsKey(clanHallId))
{
return _clanHall.get(clanHallId);
}
if (_freeClanHall.containsKey(clanHallId))
{
return _freeClanHall.get(clanHallId);
}
_log.warning("Clan hall id " + clanHallId + " not found in clanhall table!");
return null;
}
/** Get Clan Hall by x,y,z */
/*
* public final ClanHall getClanHall(int x, int y, int z) { for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet()) if (ch.getValue().getZone().isInsideZone(x, y, z)) return ch.getValue(); for (Map.Entry<Integer, ClanHall> ch : _freeClanHall.entrySet()) if
* (ch.getValue().getZone().isInsideZone(x, y, z)) return ch.getValue(); return null; }
*/
public final ClanHall getNearbyClanHall(int x, int y, int maxDist)
{
L2ClanHallZone zone = null;
for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
{
zone = ch.getValue().getZone();
if ((zone != null) && (zone.getDistanceToZone(x, y) < maxDist))
{
return ch.getValue();
}
}
for (Map.Entry<Integer, ClanHall> ch : _freeClanHall.entrySet())
{
zone = ch.getValue().getZone();
if ((zone != null) && (zone.getDistanceToZone(x, y) < maxDist))
{
return ch.getValue();
}
}
return null;
}
/** Get Clan Hall by Owner */
public final ClanHall getClanHallByOwner(L2Clan clan)
{
for (Map.Entry<Integer, ClanHall> ch : _clanHall.entrySet())
{
if (clan.getClanId() == ch.getValue().getOwnerId())
{
return ch.getValue();
}
}
return null;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final ClanHallManager _instance = new ClanHallManager();
}
}
@@ -0,0 +1,181 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Couple;
/**
* @author evill33t
*/
public class CoupleManager
{
private static final Logger _log = Logger.getLogger(CoupleManager.class.getName());
private CoupleManager()
{
_log.info("L2JMOD: Initializing CoupleManager");
load();
}
public static final CoupleManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// =========================================================
// Data Field
private FastList<Couple> _couples;
// =========================================================
// Method - Public
public void reload()
{
getCouples().clear();
load();
}
// =========================================================
// Method - Private
private final void load()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("Select id from mods_wedding order by id");
ResultSet rs = statement.executeQuery();
while (rs.next())
{
getCouples().add(new Couple(rs.getInt("id")));
}
rs.close();
statement.close();
_log.info("Loaded: " + getCouples().size() + " couples(s)");
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: CoupleManager.load(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
// =========================================================
// Property - Public
public final Couple getCouple(int coupleId)
{
int index = getCoupleIndex(coupleId);
if (index >= 0)
{
return getCouples().get(index);
}
return null;
}
public void createCouple(L2PcInstance player1, L2PcInstance player2)
{
if ((player1 != null) && (player2 != null))
{
if ((player1.getPartnerId() == 0) && (player2.getPartnerId() == 0))
{
int _player1id = player1.getObjectId();
int _player2id = player2.getObjectId();
Couple _new = new Couple(player1, player2);
getCouples().add(_new);
player1.setPartnerId(_player2id);
player2.setPartnerId(_player1id);
player1.setCoupleId(_new.getId());
player2.setCoupleId(_new.getId());
}
}
}
public void deleteCouple(int coupleId)
{
int index = getCoupleIndex(coupleId);
Couple couple = getCouples().get(index);
if (couple != null)
{
L2PcInstance player1 = L2World.getInstance().getPlayer(couple.getPlayer1Id());
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 FastList<Couple> getCouples()
{
if (_couples == null)
{
_couples = new FastList<>();
}
return _couples;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final CoupleManager _instance = new CoupleManager();
}
}
@@ -0,0 +1,523 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javolution.util.FastMap;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.CursedWeapon;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2DefenderInstance;
import com.l2jserver.gameserver.model.actor.instance.L2FeedableBeastInstance;
import com.l2jserver.gameserver.model.actor.instance.L2FestivalMonsterInstance;
import com.l2jserver.gameserver.model.actor.instance.L2FortCommanderInstance;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2GuardInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2RiftInvaderInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.util.Broadcast;
/**
* @author Micht
*/
public class CursedWeaponsManager
{
private static final Logger _log = Logger.getLogger(CursedWeaponsManager.class.getName());
public static final CursedWeaponsManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Data Field
private Map<Integer, CursedWeapon> _cursedWeapons;
// =========================================================
// Constructor
private CursedWeaponsManager()
{
init();
}
private void init()
{
_log.info("Initializing CursedWeaponsManager");
_cursedWeapons = new FastMap<>();
if (!Config.ALLOW_CURSED_WEAPONS)
{
return;
}
load();
restore();
controlPlayers();
_log.info("Loaded : " + _cursedWeapons.size() + " cursed weapon(s).");
}
// =========================================================
// Method - Private
public final void reload()
{
init();
}
private final void load()
{
if (Config.DEBUG)
{
_log.info(" Parsing ... ");
}
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
File file = new File(Config.DATAPACK_ROOT + "/data/cursedWeapons.xml");
if (!file.exists())
{
if (Config.DEBUG)
{
_log.info("NO FILE");
}
return;
}
Document doc = factory.newDocumentBuilder().parse(file);
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();
int id = Integer.parseInt(attrs.getNamedItem("id").getNodeValue());
int skillId = Integer.parseInt(attrs.getNamedItem("skillId").getNodeValue());
String name = attrs.getNamedItem("name").getNodeValue();
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);
}
}
}
}
if (Config.DEBUG)
{
_log.info("OK");
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error parsing cursed weapons file.", e);
return;
}
}
private final void restore()
{
if (Config.DEBUG)
{
_log.info(" Restoring ... ");
}
Connection con = null;
try
{
// Retrieve the L2PcInstance from the characters table of the database
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT itemId, charId, playerKarma, playerPkKills, nbKills, endTime FROM cursed_weapons");
ResultSet rset = statement.executeQuery();
while (rset.next())
{
int itemId = rset.getInt("itemId");
int playerId = rset.getInt("charId");
int playerKarma = rset.getInt("playerKarma");
int playerPkKills = rset.getInt("playerPkKills");
int nbKills = rset.getInt("nbKills");
long endTime = rset.getLong("endTime");
CursedWeapon cw = _cursedWeapons.get(itemId);
cw.setPlayerId(playerId);
cw.setPlayerKarma(playerKarma);
cw.setPlayerPkKills(playerPkKills);
cw.setNbKills(nbKills);
cw.setEndTime(endTime);
cw.reActivate();
}
rset.close();
statement.close();
if (Config.DEBUG)
{
_log.info("OK");
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not restore CursedWeapons data: " + e.getMessage(), e);
return;
}
finally
{
L2DatabaseFactory.close(con);
}
}
private final void controlPlayers()
{
if (Config.DEBUG)
{
_log.info(" Checking players ... ");
}
Connection con = null;
try
{
// Retrieve the L2PcInstance from the characters table of the database
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = null;
ResultSet rset = null;
// 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 cursedweapons 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
int itemId = cw.getItemId();
try
{
statement = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?");
statement.setInt(1, itemId);
rset = statement.executeQuery();
if (rset.next())
{
// A player has the cursed weapon in his inventory ...
int playerId = rset.getInt("owner_id");
_log.info("PROBLEM : Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
// Delete the item
statement.close();
statement = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?");
statement.setInt(1, playerId);
statement.setInt(2, itemId);
if (statement.executeUpdate() != 1)
{
_log.warning("Error while deleting cursed weapon " + itemId + " from userId " + playerId);
}
statement.close();
// Delete the skill
/*
* statement = con.prepareStatement("DELETE FROM character_skills WHERE charId=? AND skill_id="); statement.setInt(1, playerId); statement.setInt(2, cw.getSkillId()); if (statement.executeUpdate() != 1) {
* _log.warning("Error while deleting cursed weapon "+itemId+" skill from userId "+playerId); }
*/
// Restore the player's old karma and pk count
statement = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE charId=?");
statement.setInt(1, cw.getPlayerKarma());
statement.setInt(2, cw.getPlayerPkKills());
statement.setInt(3, playerId);
if (statement.executeUpdate() != 1)
{
_log.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
}
// clean up the cursedweapons table.
removeFromDb(itemId);
}
rset.close();
statement.close();
}
catch (SQLException sqlE)
{
}
}
}
catch (Exception e)
{
if (Config.DEBUG)
{
_log.log(Level.WARNING, "Could not check CursedWeapons data: " + e.getMessage(), e);
}
return;
}
finally
{
L2DatabaseFactory.close(con);
}
if (Config.DEBUG)
{
_log.info("DONE");
}
}
// =========================================================
// Properties - Public
public synchronized void checkDrop(L2Attackable attackable, L2PcInstance player)
{
if ((attackable instanceof L2DefenderInstance) || (attackable instanceof L2RiftInvaderInstance) || (attackable instanceof L2FestivalMonsterInstance) || (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)
{
CursedWeapon cw = _cursedWeapons.get(item.getItemId());
if (player.isCursedWeaponEquipped()) // cannot own 2 cursed swords
{
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)
{
CursedWeapon cw = _cursedWeapons.get(itemId);
cw.dropIt(killer);
}
public void increaseKills(int itemId)
{
CursedWeapon cw = _cursedWeapons.get(itemId);
cw.increaseKills();
}
public int getLevel(int itemId)
{
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());
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S2_MINUTE_OF_USAGE_TIME_ARE_LEFT_FOR_S1);
sm.addString(cw.getName());
// sm.addItemName(cw.getItemId());
sm.addNumber((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)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
// Delete datas
PreparedStatement statement = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?");
statement.setInt(1, itemId);
statement.executeUpdate();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.SEVERE, "CursedWeaponsManager: Failed to remove data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
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)
{
/***/
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final CursedWeaponsManager _instance = new CursedWeaponsManager();
}
}
@@ -0,0 +1,264 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.gameserver.GameTimeController;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
/**
* @version $Revision: $ $Date: $
* @author godson
*/
public class DayNightSpawnManager
{
private static Logger _log = Logger.getLogger(DayNightSpawnManager.class.getName());
private final List<L2Spawn> _dayCreatures;
private final List<L2Spawn> _nightCreatures;
private final Map<L2Spawn, L2RaidBossInstance> _bosses;
// private static int _currentState; // 0 = Day, 1 = Night
public static DayNightSpawnManager getInstance()
{
return SingletonHolder._instance;
}
private DayNightSpawnManager()
{
_dayCreatures = new ArrayList<>();
_nightCreatures = new ArrayList<>();
_bosses = new FastMap<>();
_log.info("DayNightSpawnManager: Day/Night handler initialized");
}
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 Arg 1 : List with spawns must be unspawned Arg 2 : List with spawns must be spawned Arg 3 : String for log info for unspawned L2NpcInstance Arg 4 : 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();
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())
{
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
{
if (GameTimeController.getInstance().isNowNight())
{
changeMode(1);
}
else
{
changeMode(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
{
for (L2Spawn spawn : _bosses.keySet())
{
L2RaidBossInstance boss = _bosses.get(spawn);
if ((boss == null) && (mode == 1))
{
boss = (L2RaidBossInstance) spawn.doSpawn();
RaidBossSpawnManager.getInstance().notifySpawnNightBoss(boss);
_bosses.remove(spawn);
_bosses.put(spawn, boss);
continue;
}
if ((boss == null) || (mode == 0))
{
continue;
}
if ((boss.getNpcId() == 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("DayNightSpawnManager: Deleting Hellman raidboss");
break;
case 1:
boss.spawnMe();
_log.info("DayNightSpawnManager: Spawning Hellman raidboss");
break;
}
}
public L2RaidBossInstance handleBoss(L2Spawn spawnDat)
{
if (_bosses.containsKey(spawnDat))
{
return _bosses.get(spawnDat);
}
if (GameTimeController.getInstance().isNowNight())
{
L2RaidBossInstance raidboss = (L2RaidBossInstance) spawnDat.doSpawn();
_bosses.put(spawnDat, raidboss);
return raidboss;
}
_bosses.put(spawnDat, null);
return null;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final DayNightSpawnManager _instance = new DayNightSpawnManager();
}
}
@@ -0,0 +1,607 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TByteObjectHashMap;
import java.awt.Polygon;
import java.awt.Shape;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javolution.util.FastList;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.DimensionalRift;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
import com.l2jserver.gameserver.util.Util;
import com.l2jserver.util.Rnd;
/**
* Thanks to L2Fortress and balancer.ru - kombat
*/
public class DimensionalRiftManager
{
private static Logger _log = Logger.getLogger(DimensionalRiftManager.class.getName());
private final TByteObjectHashMap<TByteObjectHashMap<DimensionalRiftRoom>> _rooms = new TByteObjectHashMap<>(7);
private final int DIMENSIONAL_FRAGMENT_ITEM_ID = 7079;
public static DimensionalRiftManager getInstance()
{
return SingletonHolder._instance;
}
private DimensionalRiftManager()
{
loadRooms();
loadSpawns();
new Quest(635, "RiftQuest", "Dummy Quest shown in players' questlist when inside the rift");
}
public DimensionalRiftRoom getRoom(byte type, byte room)
{
return _rooms.get(type) == null ? null : _rooms.get(type).get(room);
}
private void loadRooms()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM dimensional_rift");
ResultSet rs = statement.executeQuery();
while (rs.next())
{
// 0 waiting room, 1 recruit, 2 soldier, 3 officer, 4 captain , 5 commander, 6 hero
byte type = rs.getByte("type");
byte room_id = rs.getByte("room_id");
// coords related
int xMin = rs.getInt("xMin");
int xMax = rs.getInt("xMax");
int yMin = rs.getInt("yMin");
int yMax = rs.getInt("yMax");
int z1 = rs.getInt("zMin");
int z2 = rs.getInt("zMax");
int xT = rs.getInt("xT");
int yT = rs.getInt("yT");
int zT = rs.getInt("zT");
boolean isBossRoom = rs.getByte("boss") > 0;
if (!_rooms.containsKey(type))
{
_rooms.put(type, new TByteObjectHashMap<DimensionalRiftRoom>(9));
}
_rooms.get(type).put(room_id, new DimensionalRiftRoom(type, room_id, xMin, xMax, yMin, yMax, z1, z2, xT, yT, zT, isBossRoom));
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Can't load Dimension Rift zones. " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
int typeSize = _rooms.keys().length;
int roomSize = 0;
for (byte b : _rooms.keys())
{
roomSize += _rooms.get(b).keys().length;
}
_log.info("DimensionalRiftManager: Loaded " + typeSize + " room types with " + roomSize + " rooms.");
}
public void loadSpawns()
{
int countGood = 0, countBad = 0;
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
File file = new File(Config.DATAPACK_ROOT + "/data/dimensionalRift.xml");
if (!file.exists())
{
throw new IOException();
}
Document doc = factory.newDocumentBuilder().parse(file);
NamedNodeMap attrs;
byte type, roomId;
int mobId, x, y, z, delay, count;
L2Spawn spawnDat;
L2NpcTemplate template;
for (Node rift = doc.getFirstChild(); rift != null; rift = rift.getNextSibling())
{
if ("rift".equalsIgnoreCase(rift.getNodeName()))
{
for (Node area = rift.getFirstChild(); area != null; area = area.getNextSibling())
{
if ("area".equalsIgnoreCase(area.getNodeName()))
{
attrs = area.getAttributes();
type = Byte.parseByte(attrs.getNamedItem("type").getNodeValue());
for (Node room = area.getFirstChild(); room != null; room = room.getNextSibling())
{
if ("room".equalsIgnoreCase(room.getNodeName()))
{
attrs = room.getAttributes();
roomId = Byte.parseByte(attrs.getNamedItem("id").getNodeValue());
for (Node spawn = room.getFirstChild(); spawn != null; spawn = spawn.getNextSibling())
{
if ("spawn".equalsIgnoreCase(spawn.getNodeName()))
{
attrs = spawn.getAttributes();
mobId = Integer.parseInt(attrs.getNamedItem("mobId").getNodeValue());
delay = Integer.parseInt(attrs.getNamedItem("delay").getNodeValue());
count = Integer.parseInt(attrs.getNamedItem("count").getNodeValue());
template = NpcTable.getInstance().getTemplate(mobId);
if (template == null)
{
_log.warning("Template " + mobId + " not found!");
}
if (!_rooms.containsKey(type))
{
_log.warning("Type " + type + " not found!");
}
else if (!_rooms.get(type).containsKey(roomId))
{
_log.warning("Room " + roomId + " in Type " + type + " not found!");
}
for (int i = 0; i < count; i++)
{
DimensionalRiftRoom riftRoom = _rooms.get(type).get(roomId);
x = riftRoom.getRandomX();
y = riftRoom.getRandomY();
z = riftRoom.getTeleportCoords()[2];
if ((template != null) && _rooms.containsKey(type) && _rooms.get(type).containsKey(roomId))
{
spawnDat = new L2Spawn(template);
spawnDat.setAmount(1);
spawnDat.setLocx(x);
spawnDat.setLocy(y);
spawnDat.setLocz(z);
spawnDat.setHeading(-1);
spawnDat.setRespawnDelay(delay);
SpawnTable.getInstance().addNewSpawn(spawnDat, false);
_rooms.get(type).get(roomId).getSpawns().add(spawnDat);
countGood++;
}
else
{
countBad++;
}
}
}
}
}
}
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error on loading dimensional rift spawns: " + e.getMessage(), e);
}
_log.info("DimensionalRiftManager: Loaded " + countGood + " dimensional rift spawns, " + countBad + " errors.");
}
public void reload()
{
for (byte b : _rooms.keys())
{
for (byte i : _rooms.get(b).keys())
{
_rooms.get(b).get(i).getSpawns().clear();
}
_rooms.get(b).clear();
}
_rooms.clear();
loadRooms();
loadSpawns();
}
public boolean checkIfInRiftZone(int x, int y, int z, boolean ignorePeaceZone)
{
if (ignorePeaceZone)
{
return _rooms.get((byte) 0).get((byte) 1).checkIfInZone(x, y, z);
}
return _rooms.get((byte) 0).get((byte) 1).checkIfInZone(x, y, z) && !_rooms.get((byte) 0).get((byte) 0).checkIfInZone(x, y, z);
}
public boolean checkIfInPeaceZone(int x, int y, int z)
{
return _rooms.get((byte) 0).get((byte) 0).checkIfInZone(x, y, z);
}
public void teleportToWaitingRoom(L2PcInstance player)
{
int[] coords = getRoom((byte) 0, (byte) 0).getTeleportCoords();
player.teleToLocation(coords[0], coords[1], coords[2]);
}
public synchronized void start(L2PcInstance player, byte type, L2Npc npc)
{
boolean canPass = true;
if (!player.isInParty())
{
showHtmlFile(player, "data/html/seven_signs/rift/NoParty.htm", npc);
return;
}
if (player.getParty().getPartyLeaderOID() != player.getObjectId())
{
showHtmlFile(player, "data/html/seven_signs/rift/NotPartyLeader.htm", npc);
return;
}
if (player.getParty().isInDimensionalRift())
{
handleCheat(player, npc);
return;
}
if (player.getParty().getMemberCount() < Config.RIFT_MIN_PARTY_SIZE)
{
NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/seven_signs/rift/SmallParty.htm");
html.replace("%npc_name%", npc.getName());
html.replace("%count%", Integer.toString(Config.RIFT_MIN_PARTY_SIZE));
player.sendPacket(html);
return;
}
// max parties inside is rooms count - 1
if (!isAllowedEnter(type))
{
player.sendMessage("Rift is full. Try later.");
return;
}
for (L2PcInstance p : player.getParty().getPartyMembers())
{
if (!checkIfInPeaceZone(p.getX(), p.getY(), p.getZ()))
{
canPass = false;
break;
}
}
if (!canPass)
{
showHtmlFile(player, "data/html/seven_signs/rift/NotInWaitingRoom.htm", npc);
return;
}
L2ItemInstance i;
int count = getNeededItems(type);
for (L2PcInstance p : player.getParty().getPartyMembers())
{
i = p.getInventory().getItemByItemId(DIMENSIONAL_FRAGMENT_ITEM_ID);
if (i == null)
{
canPass = false;
break;
}
if (i.getCount() > 0)
{
if (i.getCount() < getNeededItems(type))
{
canPass = false;
break;
}
}
else
{
canPass = false;
break;
}
}
if (!canPass)
{
NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/seven_signs/rift/NoFragments.htm");
html.replace("%npc_name%", npc.getName());
html.replace("%count%", Integer.toString(count));
player.sendPacket(html);
return;
}
for (L2PcInstance p : player.getParty().getPartyMembers())
{
i = p.getInventory().getItemByItemId(DIMENSIONAL_FRAGMENT_ITEM_ID);
if (!p.destroyItem("RiftEntrance", i, count, null, false))
{
NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
html.setFile(player.getHtmlPrefix(), "data/html/seven_signs/rift/NoFragments.htm");
html.replace("%npc_name%", npc.getName());
html.replace("%count%", Integer.toString(count));
player.sendPacket(html);
return;
}
}
byte room;
FastList<Byte> emptyRooms;
do
{
emptyRooms = getFreeRooms(type);
room = emptyRooms.get(Rnd.get(1, emptyRooms.size()) - 1);
}
// find empty room
while (_rooms.get(type).get(room).ispartyInside());
new DimensionalRift(player.getParty(), type, room);
}
public void killRift(DimensionalRift d)
{
if (d.getTeleportTimerTask() != null)
{
d.getTeleportTimerTask().cancel();
}
d.setTeleportTimerTask(null);
if (d.getTeleportTimer() != null)
{
d.getTeleportTimer().cancel();
}
d.setTeleportTimer(null);
if (d.getSpawnTimerTask() != null)
{
d.getSpawnTimerTask().cancel();
}
d.setSpawnTimerTask(null);
if (d.getSpawnTimer() != null)
{
d.getSpawnTimer().cancel();
}
d.setSpawnTimer(null);
}
public static class DimensionalRiftRoom
{
protected final byte _type;
protected final byte _room;
private final int _xMin;
private final int _xMax;
private final int _yMin;
private final int _yMax;
private final int _zMin;
private final int _zMax;
private final int[] _teleportCoords;
private final Shape _s;
private final boolean _isBossRoom;
private final FastList<L2Spawn> _roomSpawns;
protected final FastList<L2Npc> _roomMobs;
private boolean _partyInside = false;
public DimensionalRiftRoom(byte type, byte room, int xMin, int xMax, int yMin, int yMax, int zMin, int zMax, int xT, int yT, int zT, boolean isBossRoom)
{
_type = type;
_room = room;
_xMin = (xMin + 128);
_xMax = (xMax - 128);
_yMin = (yMin + 128);
_yMax = (yMax - 128);
_zMin = zMin;
_zMax = zMax;
_teleportCoords = new int[]
{
xT,
yT,
zT
};
_isBossRoom = isBossRoom;
_roomSpawns = new FastList<>();
_roomMobs = new FastList<>();
_s = new Polygon(new int[]
{
xMin,
xMax,
xMax,
xMin
}, new int[]
{
yMin,
yMin,
yMax,
yMax
}, 4);
}
public int getRandomX()
{
return Rnd.get(_xMin, _xMax);
}
public int getRandomY()
{
return Rnd.get(_yMin, _yMax);
}
public int[] getTeleportCoords()
{
return _teleportCoords;
}
public boolean checkIfInZone(int x, int y, int z)
{
return _s.contains(x, y) && (z >= _zMin) && (z <= _zMax);
}
public boolean isBossRoom()
{
return _isBossRoom;
}
public FastList<L2Spawn> getSpawns()
{
return _roomSpawns;
}
public void spawn()
{
for (L2Spawn spawn : _roomSpawns)
{
spawn.doSpawn();
spawn.startRespawn();
}
}
public DimensionalRiftRoom unspawn()
{
for (L2Spawn spawn : _roomSpawns)
{
spawn.stopRespawn();
if (spawn.getLastSpawn() != null)
{
spawn.getLastSpawn().deleteMe();
}
}
return this;
}
/**
* @return the _partyInside
*/
public boolean ispartyInside()
{
return _partyInside;
}
public void setPartyInside(boolean partyInside)
{
_partyInside = partyInside;
}
}
private int getNeededItems(byte type)
{
switch (type)
{
case 1:
return Config.RIFT_ENTER_COST_RECRUIT;
case 2:
return Config.RIFT_ENTER_COST_SOLDIER;
case 3:
return Config.RIFT_ENTER_COST_OFFICER;
case 4:
return Config.RIFT_ENTER_COST_CAPTAIN;
case 5:
return Config.RIFT_ENTER_COST_COMMANDER;
case 6:
return Config.RIFT_ENTER_COST_HERO;
default:
throw new IndexOutOfBoundsException();
}
}
public void showHtmlFile(L2PcInstance player, String file, L2Npc npc)
{
NpcHtmlMessage html = new NpcHtmlMessage(npc.getObjectId());
html.setFile(player.getHtmlPrefix(), file);
html.replace("%npc_name%", npc.getName());
player.sendPacket(html);
}
public void handleCheat(L2PcInstance player, L2Npc npc)
{
showHtmlFile(player, "data/html/seven_signs/rift/Cheater.htm", npc);
if (!player.isGM())
{
_log.warning("Player " + player.getName() + "(" + player.getObjectId() + ") was cheating in dimension rift area!");
Util.handleIllegalPlayerAction(player, "Warning!! Character " + player.getName() + " tried to cheat in dimensional rift.", Config.DEFAULT_PUNISH);
}
}
public boolean isAllowedEnter(byte type)
{
int count = 0;
for (Object room : _rooms.get(type).getValues())
{
if (((DimensionalRiftRoom) room).ispartyInside())
{
count++;
}
}
return (count < (_rooms.get(type).size() - 1));
}
public FastList<Byte> getFreeRooms(byte type)
{
FastList<Byte> list = new FastList<>();
for (Object room : _rooms.get(type).getValues())
{
if (!((DimensionalRiftRoom) room).ispartyInside())
{
list.add(((DimensionalRiftRoom) room)._room);
}
}
return list;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final DimensionalRiftManager _instance = new DimensionalRiftManager();
}
}
@@ -0,0 +1,249 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.gameserver.model.L2Effect;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Duel;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
public class DuelManager
{
private static final Logger _log = Logger.getLogger(DuelManager.class.getName());
public static final DuelManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Data Field
private final FastList<Duel> _duels;
private int _currentDuelId = 0x90;
// =========================================================
// Constructor
private DuelManager()
{
_log.info("Initializing DuelManager");
_duels = new FastList<>();
}
// =========================================================
// Method - Private
private int getNextDuelId()
{
// In case someone wants to run the server forever :)
if (++_currentDuelId >= 2147483640)
{
_currentDuelId = 1;
}
return _currentDuelId;
}
// =========================================================
// Method - Public
public Duel getDuel(int duelId)
{
for (FastList.Node<Duel> e = _duels.head(), end = _duels.tail(); (e = e.getNext()) != end;)
{
if (e.getValue().getId() == duelId)
{
return e.getValue();
}
}
return null;
}
public void addDuel(L2PcInstance playerA, L2PcInstance playerB, int partyDuel)
{
if ((playerA == null) || (playerB == null))
{
return;
}
// return if a player has PvPFlag
String engagedInPvP = "The duel was canceled because a duelist engaged in PvP combat.";
if (partyDuel == 1)
{
boolean playerInPvP = false;
for (L2PcInstance temp : playerA.getParty().getPartyMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
if (!playerInPvP)
{
for (L2PcInstance temp : playerB.getParty().getPartyMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
}
// A player has PvP flag
if (playerInPvP)
{
for (L2PcInstance temp : playerA.getParty().getPartyMembers())
{
temp.sendMessage(engagedInPvP);
}
for (L2PcInstance temp : playerB.getParty().getPartyMembers())
{
temp.sendMessage(engagedInPvP);
}
return;
}
}
else
{
if ((playerA.getPvpFlag() != 0) || (playerB.getPvpFlag() != 0))
{
playerA.sendMessage(engagedInPvP);
playerB.sendMessage(engagedInPvP);
return;
}
}
Duel duel = new Duel(playerA, playerB, partyDuel, getNextDuelId());
_duels.add(duel);
}
public void removeDuel(Duel duel)
{
_duels.remove(duel);
}
public void doSurrender(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
Duel duel = getDuel(player.getDuelId());
duel.doSurrender(player);
}
/**
* Updates player states.
* @param player - the dieing player
*/
public void onPlayerDefeat(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onPlayerDefeat(player);
}
}
/**
* Registers a debuff which will be removed if the duel ends
* @param player
* @param debuff
*/
public void onBuff(L2PcInstance player, L2Effect buff)
{
if ((player == null) || !player.isInDuel() || (buff == null))
{
return;
}
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;
}
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, L2GameServerPacket packet)
{
if ((player == null) || !player.isInDuel())
{
return;
}
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().getPartyMembers().contains(player))
{
duel.broadcastToTeam2(packet);
}
else if ((duel.getPlayerB().getParty() != null) && duel.getPlayerB().getParty().getPartyMembers().contains(player))
{
duel.broadcastToTeam1(packet);
}
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final DuelManager _instance = new DuelManager();
}
}
@@ -0,0 +1,233 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.InstanceListManager;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.entity.Fort;
public class FortManager implements InstanceListManager
{
protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
public static final FortManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Data Field
private List<Fort> _forts;
// =========================================================
// Constructor
private FortManager()
{
}
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 < getForts().size(); i++)
{
fort = getForts().get(i);
if (fort == null)
{
continue;
}
distance = fort.getDistance(obj);
if (maxDistance > distance)
{
maxDistance = (long) distance;
index = i;
}
}
}
return index;
}
// =========================================================
// Property - Public
public final Fort getFortById(int fortId)
{
for (Fort f : getForts())
{
if (f.getFortId() == 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 int getFortIndex(int fortId)
{
Fort fort;
for (int i = 0; i < getForts().size(); i++)
{
fort = getForts().get(i);
if ((fort != null) && (fort.getFortId() == 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 < getForts().size(); i++)
{
fort = getForts().get(i);
if ((fort != null) && fort.checkIfInZone(x, y, z))
{
return i;
}
}
return -1;
}
public final List<Fort> getForts()
{
if (_forts == null)
{
_forts = new FastList<>();
}
return _forts;
}
@Override
public void loadInstances()
{
_log.info("Initializing FortManager");
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT id FROM fort ORDER BY id");
ResultSet rs = statement.executeQuery();
while (rs.next())
{
getForts().add(new Fort(rs.getInt("id")));
}
rs.close();
statement.close();
_log.info("Loaded: " + getForts().size() + " fortress");
for (Fort fort : getForts())
{
fort.getSiege().getSiegeGuardManager().loadSiegeGuard();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortData(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (final Fort fort : _forts)
{
fort.activateInstance();
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final FortManager _instance = new FortManager();
}
}
@@ -0,0 +1,169 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.instance.L2FortBallistaInstance;
import com.l2jserver.gameserver.model.entity.Fort;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
public class FortSiegeGuardManager
{
private static final Logger _log = Logger.getLogger(FortSiegeGuardManager.class.getName());
private final Fort _fort;
protected FastMap<Integer, FastList<L2Spawn>> _siegeGuards = new FastMap<>();
protected FastList<L2Spawn> _siegeGuardsSpawns;
public FortSiegeGuardManager(Fort fort)
{
_fort = fort;
}
/**
* Spawn guards.<BR>
* <BR>
*/
public void spawnSiegeGuard()
{
try
{
FastList<L2Spawn> monsterList = getSiegeGuardSpawn().get(getFort().getFortId());
if (monsterList != null)
{
for (L2Spawn spawnDat : monsterList)
{
spawnDat.doSpawn();
if (spawnDat.getLastSpawn() instanceof L2FortBallistaInstance)
{
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.<BR>
* <BR>
*/
public void unspawnSiegeGuard()
{
try
{
FastList<L2Spawn> monsterList = getSiegeGuardSpawn().get(getFort().getFortId());
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.<BR>
* <BR>
*/
void loadSiegeGuard()
{
_siegeGuards.clear();
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM fort_siege_guards Where fortId = ? ");
statement.setInt(1, getFort().getFortId());
ResultSet rs = statement.executeQuery();
L2Spawn spawn1;
L2NpcTemplate template1;
_siegeGuardsSpawns = new FastList<>();
while (rs.next())
{
int fortId = rs.getInt("fortId");
template1 = NpcTable.getInstance().getTemplate(rs.getInt("npcId"));
if (template1 != null)
{
spawn1 = new L2Spawn(template1);
spawn1.setAmount(1);
spawn1.setLocx(rs.getInt("x"));
spawn1.setLocy(rs.getInt("y"));
spawn1.setLocz(rs.getInt("z"));
spawn1.setHeading(rs.getInt("heading"));
spawn1.setRespawnDelay(rs.getInt("respawnDelay"));
spawn1.setLocation(0);
_siegeGuardsSpawns.add(spawn1);
}
else
{
_log.warning("Missing npc data in npc table for id: " + rs.getInt("npcId"));
}
_siegeGuards.put(fortId, _siegeGuardsSpawns);
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error loading siege guard for fort " + getFort().getName() + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final Fort getFort()
{
return _fort;
}
public final FastMap<Integer, FastList<L2Spawn>> getSiegeGuardSpawn()
{
return _siegeGuards;
}
}
@@ -0,0 +1,463 @@
/*
* 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.l2jserver.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.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.model.CombatFlag;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Fort;
import com.l2jserver.gameserver.model.entity.FortSiege;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
public class FortSiegeManager
{
private static final Logger _log = Logger.getLogger(FortSiegeManager.class.getName());
public static final FortSiegeManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Data Field
private int _attackerMaxClans = 500; // Max number of clans
// Fort Siege settings
private FastMap<Integer, FastList<SiegeSpawn>> _commanderSpawnList;
private FastMap<Integer, FastList<CombatFlag>> _flagList;
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;
// =========================================================
// Constructor
private FortSiegeManager()
{
_log.info("Initializing FortSiegeManager");
load();
}
// =========================================================
// Method - Public
public final void addSiegeSkills(L2PcInstance character)
{
character.addSkill(SkillTable.FrequentSkill.SEAL_OF_RULER.getSkill(), false);
character.addSkill(SkillTable.FrequentSkill.BUILD_HEADQUARTERS.getSkill(), false);
}
/**
* Return true if character summon<BR>
* <BR>
* @param activeChar The L2Character of the character can summon
*/
public final boolean checkIfOkToSummon(L2Character activeChar, boolean isCheckOnly)
{
if (!(activeChar instanceof L2PcInstance))
{
return false;
}
String text = "";
L2PcInstance player = (L2PcInstance) activeChar;
Fort fort = FortManager.getInstance().getFort(player);
if ((fort == null) || (fort.getFortId() <= 0))
{
text = "You must be on fort ground to summon this";
}
else if (!fort.getSiege().getIsInProgress())
{
text = "You can only summon this during a siege.";
}
else if ((player.getClanId() != 0) && (fort.getSiege().getAttackerClan(player.getClanId()) == null))
{
text = "You can only summon this as a registered attacker.";
}
else
{
return true;
}
if (!isCheckOnly)
{
player.sendMessage(text);
}
return false;
}
/**
* Return true if the clan is registered or owner of a fort<BR>
* <BR>
* @param clan The L2Clan of the player
*/
public final boolean checkIsRegistered(L2Clan clan, int fortid)
{
if (clan == null)
{
return false;
}
Connection con = null;
boolean register = false;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM fortsiege_clans where clan_id=? and fort_id=?");
statement.setInt(1, clan.getClanId());
statement.setInt(2, fortid);
ResultSet rs = statement.executeQuery();
while (rs.next())
{
register = true;
break;
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: checkIsRegistered(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
return register;
}
public final void removeSiegeSkills(L2PcInstance character)
{
character.removeSkill(SkillTable.FrequentSkill.SEAL_OF_RULER.getSkill());
character.removeSkill(SkillTable.FrequentSkill.BUILD_HEADQUARTERS.getSkill());
}
// =========================================================
// Method - Private
private final void load()
{
try (InputStream is = new FileInputStream(new File(Config.FORTSIEGE_CONFIGURATION_FILE)))
{
Properties siegeSettings = new Properties();
siegeSettings.load(is);
// Siege setting
_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 FastMap<>();
_flagList = new FastMap<>();
for (Fort fort : FortManager.getInstance().getForts())
{
FastList<SiegeSpawn> _commanderSpawns = new FastList<>();
FastList<CombatFlag> _flagSpawns = new FastList<>();
for (int i = 1; i < 5; i++)
{
String _spawnParams = siegeSettings.getProperty(fort.getName().replace(" ", "") + "Commander" + i, "");
if (_spawnParams.length() == 0)
{
break;
}
StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int z = Integer.parseInt(st.nextToken());
int heading = Integer.parseInt(st.nextToken());
int npc_id = Integer.parseInt(st.nextToken());
_commanderSpawns.add(new SiegeSpawn(fort.getFortId(), x, y, z, heading, npc_id, i));
}
catch (Exception e)
{
_log.warning("Error while loading commander(s) for " + fort.getName() + " fort.");
}
}
_commanderSpawnList.put(fort.getFortId(), _commanderSpawns);
for (int i = 1; i < 4; i++)
{
String _spawnParams = siegeSettings.getProperty(fort.getName().replace(" ", "") + "Flag" + i, "");
if (_spawnParams.length() == 0)
{
break;
}
StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int z = Integer.parseInt(st.nextToken());
int flag_id = Integer.parseInt(st.nextToken());
_flagSpawns.add(new CombatFlag(fort.getFortId(), x, y, z, 0, flag_id));
}
catch (Exception e)
{
_log.warning("Error while loading flag(s) for " + fort.getName() + " fort.");
}
}
_flagList.put(fort.getFortId(), _flagSpawns);
}
}
catch (Exception e)
{
// _initialized = false;
_log.log(Level.WARNING, "Error while loading fortsiege data." + e.getMessage(), e);
}
}
// =========================================================
// Property - Public
public final FastList<SiegeSpawn> getCommanderSpawnList(int _fortId)
{
return _commanderSpawnList.get(_fortId);
}
public final FastList<CombatFlag> getFlagList(int _fortId)
{
return _flagList.get(_fortId);
}
public final int getAttackerMaxClans()
{
return _attackerMaxClans;
}
public final int getFlagMaxCount()
{
return _flagMaxCount;
}
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 FastList<>();
}
return _sieges;
}
public final void addSiege(FortSiege fortSiege)
{
if (_sieges == null)
{
_sieges = new FastList<>();
}
_sieges.add(fortSiege);
}
public boolean isCombat(int itemId)
{
return (itemId == 9819);
}
public boolean activateCombatFlag(L2PcInstance player, L2ItemInstance item)
{
if (!checkIfCanPickup(player))
{
return false;
}
Fort fort = FortManager.getInstance().getFort(player);
FastList<CombatFlag> fcf = _flagList.get(fort.getFortId());
for (CombatFlag cf : fcf)
{
if (cf.itemInstance == item)
{
cf.activate(player, item);
}
}
return true;
}
public boolean checkIfCanPickup(L2PcInstance player)
{
SystemMessage sm;
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
Fort fort = FortManager.getInstance().getFort(player);
if ((fort == null) || (fort.getFortId() <= 0))
{
player.sendPacket(sm);
return false;
}
else if (!fort.getSiege().getIsInProgress())
{
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)
{
Fort fort = FortManager.getInstance().getFortById(fortId);
FastList<CombatFlag> fcf = _flagList.get(fort.getFortId());
for (CombatFlag cf : fcf)
{
if (cf.playerId == player.getObjectId())
{
cf.dropIt();
if (fort.getSiege().getIsInProgress())
{
cf.spawnMe();
}
}
}
}
public static class SiegeSpawn
{
Location _location;
private final int _npcId;
private final int _heading;
private final int _fortId;
private final int _id;
public SiegeSpawn(int fort_id, int x, int y, int z, int heading, int npc_id, int id)
{
_fortId = fort_id;
_location = new Location(x, y, z, heading);
_heading = heading;
_npcId = npc_id;
_id = id;
}
public int getFortId()
{
return _fortId;
}
public int getNpcId()
{
return _npcId;
}
public int getHeading()
{
return _heading;
}
public int getId()
{
return _id;
}
public Location getLocation()
{
return _location;
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final FortSiegeManager _instance = new FortSiegeManager();
}
}
@@ -0,0 +1,128 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
public class GlobalVariablesManager
{
private static final Logger _log = Logger.getLogger(GlobalVariablesManager.class.getName());
private static final String LOAD_VAR = "SELECT var,value FROM global_variables";
private static final String SAVE_VAR = "INSERT INTO global_variables (var,value) VALUES (?,?) ON DUPLICATE KEY UPDATE value=?";
private final Map<String, String> _variablesMap;
private GlobalVariablesManager()
{
_variablesMap = new FastMap<>();
loadVars();
}
private final void loadVars()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(LOAD_VAR);
ResultSet rset = statement.executeQuery();
String var, value;
while (rset.next())
{
var = rset.getString(1);
value = rset.getString(2);
_variablesMap.put(var, value);
}
rset.close();
statement.close();
}
catch (Exception e)
{
_log.warning("GlobalVariablesManager: problem while loading variables: " + e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void saveVars()
{
Connection con = null;
PreparedStatement statement = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement(SAVE_VAR);
for (String var : _variablesMap.keySet())
{
statement.setString(1, var);
statement.setString(2, _variablesMap.get(var));
statement.setString(3, _variablesMap.get(var));
statement.execute();
}
statement.close();
_log.info("GlobalVariablesManager: Database updated.");
}
catch (Exception e)
{
_log.warning("GlobalVariablesManager: problem while saving variables: " + e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public void storeVariable(String var, String value)
{
_variablesMap.put(var, value);
}
public boolean isVariableStored(String var)
{
return _variablesMap.containsKey(var);
}
public String getStoredVariable(String var)
{
return _variablesMap.get(var);
}
public static final GlobalVariablesManager getInstance()
{
return SingletonHolder._instance;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final GlobalVariablesManager _instance = new GlobalVariablesManager();
}
}
@@ -0,0 +1,208 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.util.Calendar;
import java.util.logging.Logger;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.quest.Quest;
public class GraciaSeedsManager
{
private static final Logger _log = Logger.getLogger(GraciaSeedsManager.class.getName());
public static String qn = "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()
{
_log.info(getClass().getSimpleName() + ": Initializing");
_SoDLastStateChangeDate = Calendar.getInstance();
loadData();
handleSodStages();
}
public void saveData(byte seedType)
{
switch (seedType)
{
case SODTYPE:
// Seed of Destruction
GlobalVariablesManager.getInstance().storeVariable("SoDState", String.valueOf(_SoDState));
GlobalVariablesManager.getInstance().storeVariable("SoDTiatKilled", String.valueOf(_SoDTiatKilled));
GlobalVariablesManager.getInstance().storeVariable("SoDLSCDate", String.valueOf(_SoDLastStateChangeDate.getTimeInMillis()));
break;
case SOITYPE:
// Seed of Infinity
break;
case SOATYPE:
// Seed of Annihilation
break;
default:
_log.warning("GraciaSeedManager: Unknown SeedType in SaveData: " + seedType);
break;
}
}
public void loadData()
{
// Seed of Destruction variables
if (GlobalVariablesManager.getInstance().isVariableStored("SoDState"))
{
_SoDState = Integer.parseInt(GlobalVariablesManager.getInstance().getStoredVariable("SoDState"));
_SoDTiatKilled = Integer.parseInt(GlobalVariablesManager.getInstance().getStoredVariable("SoDTiatKilled"));
_SoDLastStateChangeDate.setTimeInMillis(Long.parseLong(GlobalVariablesManager.getInstance().getStoredVariable("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
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(() ->
{
setSoDState(1, true);
Quest esQuest = QuestManager.getInstance().getQuest(qn);
if (esQuest == null)
{
_log.warning("GraciaSeedManager: missing EnergySeeds Quest!");
}
else
{
esQuest.notifyEvent("StopSoDAi", null, null);
}
}, Config.SOD_STAGE_2_LENGTH - timePast);
}
break;
case 3:
// not implemented
setSoDState(1, true);
break;
default:
_log.warning("GraciaSeedManager: Unknown Seed of Destruction state(" + _SoDState + ")! ");
}
}
public void increaseSoDTiatKilled()
{
if (_SoDState == 1)
{
_SoDTiatKilled++;
if (_SoDTiatKilled >= Config.SOD_TIAT_KILL_COUNT)
{
setSoDState(2, false);
}
saveData(SODTYPE);
Quest esQuest = QuestManager.getInstance().getQuest(qn);
if (esQuest == null)
{
_log.warning("GraciaSeedManager: missing EnergySeeds Quest!");
}
else
{
esQuest.notifyEvent("StartSoDAi", null, null);
}
}
}
public int getSoDTiatKilled()
{
return _SoDTiatKilled;
}
public void setSoDState(int value, boolean doSave)
{
_log.info("GraciaSeedManager: 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;
}
public static final GraciaSeedsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final GraciaSeedsManager _instance = new GraciaSeedsManager();
}
}
@@ -0,0 +1,473 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntIntHashMap;
import gnu.trove.TIntObjectHashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.zone.type.L2BossZone;
import com.l2jserver.gameserver.templates.StatsSet;
import com.l2jserver.util.L2FastList;
/**
* @author DaRkRaGe Revised by Emperorc
*/
public class GrandBossManager
{
/*
* ========================================================= This class handles all Grand Bosses: <ul> <li>25333-25338 Anakazel</li> <li>29001 Queen Ant</li> <li>29006 Core</li> <li>29014 Orfen</li> <li>29019 Antharas</li> <li>29020 Baium</li> <li>29022 Zaken</li> <li>29028 Valakas</li>
* <li>29045 Frintezza</li> <li>29046-29047 Scarlet van Halisha</li> </ul> It handles the saving of hp, mp, location, and status of all Grand Bosses. It also manages the zones associated with the Grand Bosses. NOTE: The current version does NOT spawn the Grand Bosses, it just stores and
* retrieves the values on reboot/startup, for AI scripts to utilize as needed.
*/
/**
* DELETE FROM grandboss_list
*/
private static final String DELETE_GRAND_BOSS_LIST = "DELETE FROM grandboss_list";
/**
* INSERT INTO grandboss_list (player_id,zone) VALUES (?,?)
*/
private static final String INSERT_GRAND_BOSS_LIST = "INSERT INTO grandboss_list (player_id,zone) VALUES (?,?)";
/**
* 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_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;
protected static TIntObjectHashMap<StatsSet> _storedInfo;
private TIntIntHashMap _bossStatus;
private L2FastList<L2BossZone> _zones;
public static GrandBossManager getInstance()
{
return SingletonHolder._instance;
}
private GrandBossManager()
{
_log.info("Initializing GrandBossManager");
init();
}
private void init()
{
_zones = new L2FastList<>();
_bosses = new FastMap<>();
_storedInfo = new TIntObjectHashMap<>();
_bossStatus = new TIntIntHashMap();
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * from grandboss_data ORDER BY boss_id");
ResultSet rset = statement.executeQuery();
while (rset.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
StatsSet info = new StatsSet();
int bossId = rset.getInt("boss_id");
info.set("loc_x", rset.getInt("loc_x"));
info.set("loc_y", rset.getInt("loc_y"));
info.set("loc_z", rset.getInt("loc_z"));
info.set("heading", rset.getInt("heading"));
info.set("respawn_time", rset.getLong("respawn_time"));
double HP = rset.getDouble("currentHP"); // jython doesn't recognize doubles
int true_HP = (int) HP; // so use java's ability to type cast
info.set("currentHP", true_HP); // to convert double to int
double MP = rset.getDouble("currentMP");
int true_MP = (int) MP;
info.set("currentMP", true_MP);
int status = rset.getInt("status");
_bossStatus.put(bossId, status);
_storedInfo.put(bossId, info);
_log.info("GrandBossManager: " + NpcTable.getInstance().getTemplate(bossId).getName() + "(" + bossId + ") status is " + status + ".");
if (status > 0)
{
_log.info("GrandBossManager: Next spawn date of " + NpcTable.getInstance().getTemplate(bossId).getName() + " is " + new Date(info.getLong("respawn_time")) + ".");
}
info = null;
}
_log.info("GrandBossManager: Loaded " + _storedInfo.size() + " Instances");
rset.close();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "GrandBossManager: Could not load grandboss_data table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while initializing GrandBossManager: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/**
* Zone Functions
*/
public void initZones()
{
Connection con = null;
FastMap<Integer, L2FastList<Integer>> zones = new FastMap<>();
if (_zones == null)
{
_log.warning("GrandBossManager: Could not read Grand Boss zone data");
return;
}
for (L2BossZone zone : _zones)
{
if (zone == null)
{
continue;
}
zones.put(zone.getId(), new L2FastList<Integer>());
}
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * from grandboss_list ORDER BY player_id");
ResultSet rset = statement.executeQuery();
while (rset.next())
{
int id = rset.getInt("player_id");
int zone_id = rset.getInt("zone");
zones.get(zone_id).add(id);
}
rset.close();
statement.close();
_log.info("GrandBossManager: Initialized " + _zones.size() + " Grand Boss Zones");
}
catch (SQLException e)
{
_log.log(Level.WARNING, "GrandBossManager: Could not load grandboss_list table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while initializing GrandBoss zones: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
for (L2BossZone zone : _zones)
{
if (zone == null)
{
continue;
}
zone.setAllowedPlayers(zones.get(zone.getId()));
}
zones.clear();
}
public void addZone(L2BossZone zone)
{
if (_zones != null)
{
_zones.add(zone);
}
}
public final L2BossZone getZone(L2Character character)
{
if (_zones != null)
{
for (L2BossZone temp : _zones)
{
if (temp.isCharacterInZone(character))
{
return temp;
}
}
}
return null;
}
public final L2BossZone getZone(int x, int y, int z)
{
if (_zones != null)
{
for (L2BossZone temp : _zones)
{
if (temp.isInsideZone(x, y, z))
{
return temp;
}
}
}
return null;
}
public boolean checkIfInZone(String zoneType, L2Object obj)
{
L2BossZone temp = getZone(obj.getX(), obj.getY(), obj.getZ());
if (temp == null)
{
return false;
}
return temp.getName().equalsIgnoreCase(zoneType);
}
public boolean checkIfInZone(L2PcInstance player)
{
if (player == null)
{
return false;
}
L2BossZone temp = getZone(player.getX(), player.getY(), player.getZ());
if (temp == null)
{
return false;
}
return true;
}
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 " + NpcTable.getInstance().getTemplate(bossId).getName() + "(" + bossId + ") status to " + status);
updateDb(bossId, true);
}
/**
* Adds a L2GrandBossInstance to the list of bosses.
*/
public void addBoss(L2GrandBossInstance boss)
{
if (boss != null)
{
_bosses.put(boss.getNpcId(), 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);
}
private void storeToDb()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_GRAND_BOSS_LIST);
statement.executeUpdate();
statement.close();
statement = con.prepareStatement(INSERT_GRAND_BOSS_LIST);
for (L2BossZone zone : _zones)
{
if (zone == null)
{
continue;
}
Integer id = zone.getId();
L2FastList<Integer> list = zone.getAllowedPlayers();
if ((list == null) || list.isEmpty())
{
continue;
}
for (Integer player : list)
{
statement.setInt(1, player);
statement.setInt(2, id);
statement.executeUpdate();
statement.clearParameters();
}
}
statement.close();
for (Integer bossId : _storedInfo.keys())
{
final L2GrandBossInstance boss = _bosses.get(bossId);
StatsSet info = _storedInfo.get(bossId);
if ((boss == null) || (info == null))
{
statement = con.prepareStatement(UPDATE_GRAND_BOSS_DATA2);
statement.setInt(1, _bossStatus.get(bossId));
statement.setInt(2, bossId);
}
else
{
statement = con.prepareStatement(UPDATE_GRAND_BOSS_DATA);
statement.setInt(1, boss.getX());
statement.setInt(2, boss.getY());
statement.setInt(3, boss.getZ());
statement.setInt(4, boss.getHeading());
statement.setLong(5, info.getLong("respawn_time"));
double hp = boss.getCurrentHp();
double mp = boss.getCurrentMp();
if (boss.isDead())
{
hp = boss.getMaxHp();
mp = boss.getMaxMp();
}
statement.setDouble(6, hp);
statement.setDouble(7, mp);
statement.setInt(8, _bossStatus.get(bossId));
statement.setInt(9, bossId);
}
statement.executeUpdate();
statement.clearParameters();
statement.close();
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "GrandBossManager: Couldn't store grandbosses to database:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private void updateDb(int bossId, boolean statusOnly)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = null;
L2GrandBossInstance boss = _bosses.get(bossId);
StatsSet info = _storedInfo.get(bossId);
if (statusOnly || (boss == null) || (info == null))
{
statement = con.prepareStatement(UPDATE_GRAND_BOSS_DATA2);
statement.setInt(1, _bossStatus.get(bossId));
statement.setInt(2, bossId);
}
else
{
statement = con.prepareStatement(UPDATE_GRAND_BOSS_DATA);
statement.setInt(1, boss.getX());
statement.setInt(2, boss.getY());
statement.setInt(3, boss.getZ());
statement.setInt(4, boss.getHeading());
statement.setLong(5, info.getLong("respawn_time"));
double hp = boss.getCurrentHp();
double mp = boss.getCurrentMp();
if (boss.isDead())
{
hp = boss.getMaxHp();
mp = boss.getMaxMp();
}
statement.setDouble(6, hp);
statement.setDouble(7, mp);
statement.setInt(8, _bossStatus.get(bossId));
statement.setInt(9, bossId);
}
statement.executeUpdate();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "GrandBossManager: Couldn't update grandbosses to database:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/**
* Saves all Grand Boss info and then clears all info from memory, including all schedules.
*/
public void cleanUp()
{
storeToDb();
_bosses.clear();
_storedInfo.clear();
_bossStatus.clear();
_zones.clear();
}
public L2FastList<L2BossZone> getZones()
{
return _zones;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final GrandBossManager _instance = new GrandBossManager();
}
}
@@ -0,0 +1,540 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntIntHashMap;
import java.util.ArrayList;
import java.util.List;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.BlockCheckerEngine;
import com.l2jserver.gameserver.model.entity.TvTEvent;
import com.l2jserver.gameserver.model.itemcontainer.PcInventory;
import com.l2jserver.gameserver.model.olympiad.OlympiadManager;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExCubeGameAddPlayer;
import com.l2jserver.gameserver.network.serverpackets.ExCubeGameChangeTeam;
import com.l2jserver.gameserver.network.serverpackets.ExCubeGameRemovePlayer;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
/**
* @author BiggBoss
*/
public final class HandysBlockCheckerManager
{
/*
* This class manage the player add/remove, team change and event arena status, as the clearance of the participants list or liberate the arena
*/
// All the participants and their team classifed by arena
private static ArenaParticipantsHolder[] _arenaPlayers;
// Arena votes to start the game
private static TIntIntHashMap _arenaVotes = new TIntIntHashMap();
// Arena Status, True = is being used, otherwise, False
private static FastMap<Integer, Boolean> _arenaStatus;
// Registration request penalty (10 seconds)
protected static FastList<Integer> _registrationPenalty = new FastList<>();
/**
* Return the number of event-start votes for the spcified 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)
{
int newVotes = _arenaVotes.get(arena) + 1;
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().executeTask(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
if (_arenaStatus == null)
{
_arenaStatus = new FastMap<>();
_arenaStatus.put(0, false);
_arenaStatus.put(1, false);
_arenaStatus.put(2, false);
_arenaStatus.put(3, false);
}
}
/**
* Returns the players holder
* @param arena
* @return ArenaParticipantsHolder
*/
public ArenaParticipantsHolder getHolder(int arena)
{
return _arenaPlayers[arena];
}
/**
* Initializes the participants holder
*/
public void startUpParticipantsQueue()
{
_arenaPlayers = new ArenaParticipantsHolder[4];
for (int i = 0; i < 4; ++i)
{
_arenaPlayers[i] = new ArenaParticipantsHolder(i);
}
}
/**
* Add the player to the specified arena (throught the specified arena manager) and send the needed server -> client packets
* @param player
* @param arenaId
*/
public boolean addPlayerToArena(L2PcInstance player, int arenaId)
{
ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
synchronized (holder)
{
boolean isRed;
for (int i = 0; i < 4; i++)
{
if (_arenaPlayers[i].getAllPlayers().contains(player))
{
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(SystemMessage.getSystemMessage(SystemMessageId.CANNOT_REGISTER_PROCESSING_CURSED_WEAPON));
return false;
}
if (TvTEvent.isPlayerParticipant(player.getObjectId()) || player.isInOlympiadMode())
{
player.sendMessage("Couldnt register you due other event participation");
return false;
}
if (OlympiadManager.getInstance().isRegistered(player))
{
OlympiadManager.getInstance().unRegisterNoble(player);
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.COLISEUM_OLYMPIAD_KRATEIS_APPLICANTS_CANNOT_PARTICIPATE));
}
/*
* if(UnderGroundColiseum.getInstance().isRegisteredPlayer(player)) { UngerGroundColiseum.getInstance().removeParticipant(player); player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.COLISEUM_OLYMPIAD_KRATEIS_APPLICANTS_CANNOT_PARTICIPATE)); }
* if(KrateiCubeManager.getInstance().isRegisteredPlayer(player)) { KrateiCubeManager.getInstance().removeParticipant(player); player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.COLISEUM_OLYMPIAD_KRATEIS_APPLICANTS_CANNOT_PARTICIPATE)); }
*/
if (_registrationPenalty.contains(player.getObjectId()))
{
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CANNOT_REQUEST_REGISTRATION_10_SECS_AFTER));
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
*/
public void removePlayer(L2PcInstance player, int arenaId, int team)
{
ArenaParticipantsHolder holder = _arenaPlayers[arenaId];
synchronized (holder)
{
boolean isRed = team == 0 ? true : false;
holder.removePlayer(player, team);
holder.broadCastPacketToTeam(new ExCubeGameRemovePlayer(player, isRed));
// End event if theres an empty team
int teamSize = isRed ? holder.getRedTeamSize() : holder.getBlueTeamSize();
if (teamSize == 0)
{
holder.getEvent().endEventAbnormally();
}
Integer objId = player.getObjectId();
if (!_registrationPenalty.contains(objId))
{
_registrationPenalty.add(objId);
}
schedulePenaltyRemoval(objId);
}
}
/**
* 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)
{
ArenaParticipantsHolder holder = _arenaPlayers[arena];
synchronized (holder)
{
boolean isFromRed = holder._redPlayers.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;
}
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 L2PcInstance player
*/
public void onDisconnect(L2PcInstance player)
{
int arena = player.getBlockCheckerArena();
int team = getHolder(arena).getPlayerTeam(player);
HandysBlockCheckerManager.getInstance().removePlayer(player, arena, team);
if (player.getTeam() > 0)
{
player.stopAllEffects();
// Remove team aura
player.setTeam(0);
// Remove the event items
PcInventory inv = player.getInventory();
if (inv.getItemByItemId(13787) != null)
{
long count = inv.getInventoryItemCount(13787, 0);
inv.destroyItemByItemId("Handys Block Checker", 13787, count, player, player);
}
if (inv.getItemByItemId(13788) != null)
{
long count = inv.getInventoryItemCount(13788, 0);
inv.destroyItemByItemId("Handys Block Checker", 13788, count, player, player);
}
player.setInsideZone(L2Character.ZONE_PVP, false);
// Teleport Back
player.teleToLocation(-57478, -60367, -2370);
}
}
public static HandysBlockCheckerManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final HandysBlockCheckerManager _instance = new HandysBlockCheckerManager();
}
public class ArenaParticipantsHolder
{
int _arena;
List<L2PcInstance> _redPlayers;
List<L2PcInstance> _bluePlayers;
BlockCheckerEngine _engine;
public ArenaParticipantsHolder(int arena)
{
_arena = arena;
_redPlayers = new ArrayList<>(6);
_bluePlayers = new ArrayList<>(6);
_engine = new BlockCheckerEngine(this, _arena);
}
public List<L2PcInstance> getRedPlayers()
{
return _redPlayers;
}
public List<L2PcInstance> getBluePlayers()
{
return _bluePlayers;
}
public ArrayList<L2PcInstance> getAllPlayers()
{
ArrayList<L2PcInstance> all = new ArrayList<>(12);
all.addAll(_redPlayers);
all.addAll(_bluePlayers);
return all;
}
public void addPlayer(L2PcInstance player, int team)
{
if (team == 0)
{
_redPlayers.add(player);
}
else
{
_bluePlayers.add(player);
}
}
public void removePlayer(L2PcInstance player, int team)
{
if (team == 0)
{
_redPlayers.remove(player);
}
else
{
_bluePlayers.remove(player);
}
}
public int getPlayerTeam(L2PcInstance player)
{
if (_redPlayers.contains(player))
{
return 0;
}
else if (_bluePlayers.contains(player))
{
return 1;
}
else
{
return -1;
}
}
public int getRedTeamSize()
{
return _redPlayers.size();
}
public int getBlueTeamSize()
{
return _bluePlayers.size();
}
public void broadCastPacketToTeam(L2GameServerPacket packet)
{
for (L2PcInstance p : _redPlayers)
{
p.sendPacket(packet);
}
for (L2PcInstance p : _bluePlayers)
{
p.sendPacket(packet);
}
}
public void clearPlayers()
{
_redPlayers.clear();
_bluePlayers.clear();
}
public BlockCheckerEngine getEvent()
{
return _engine;
}
public void updateEvent()
{
_engine.updatePlayersOnStart(this);
}
protected void checkAndShuffle()
{
int redSize = _redPlayers.size();
int blueSize = _bluePlayers.size();
if (redSize > (blueSize + 1))
{
broadCastPacketToTeam(SystemMessage.getSystemMessage(SystemMessageId.TEAM_ADJUSTED_BECAUSE_WRONG_POPULATION_RATIO));
int needed = redSize - (blueSize + 1);
for (int i = 0; i < (needed + 1); i++)
{
L2PcInstance plr = _redPlayers.get(i);
if (plr == null)
{
continue;
}
changePlayerToTeam(plr, _arena, 1);
}
}
else if (blueSize > (redSize + 1))
{
broadCastPacketToTeam(SystemMessage.getSystemMessage(SystemMessageId.TEAM_ADJUSTED_BECAUSE_WRONG_POPULATION_RATIO));
int needed = blueSize - (redSize + 1);
for (int i = 0; i < (needed + 1); i++)
{
L2PcInstance plr = _bluePlayers.get(i);
if (plr == null)
{
continue;
}
changePlayerToTeam(plr, _arena, 0);
}
}
}
}
private void schedulePenaltyRemoval(int objId)
{
ThreadPoolManager.getInstance().scheduleGeneral(new PenaltyRemove(objId), 10000);
}
private class PenaltyRemove implements Runnable
{
Integer objectId;
public PenaltyRemove(Integer id)
{
objectId = id;
}
@Override
public void run()
{
try
{
_registrationPenalty.remove(objectId);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
@@ -0,0 +1,60 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.util.logging.Logger;
public class HellboundManager
{
private static final Logger _log = Logger.getLogger(HellboundManager.class.getName());
private HellboundManager()
{
_log.info(getClass().getSimpleName() + ": Initializing");
init();
}
private void init()
{
_log.info(getClass().getSimpleName() + ": Mode: dummy");
if (isLocked())
{
_log.info(getClass().getSimpleName() + ": State: locked");
}
else
{
_log.info(getClass().getSimpleName() + ": State: unlocked");
}
}
/**
* Returns true if Hellbound is locked
*/
public boolean isLocked()
{
return false;
}
public static final HellboundManager getInstance()
{
return SingletonHolder._instance;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final HellboundManager _instance = new HellboundManager();
}
}
@@ -0,0 +1,377 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.io.UTF8StreamReader;
import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.xml.stream.XMLStreamConstants;
import javolution.xml.stream.XMLStreamException;
import javolution.xml.stream.XMLStreamReaderImpl;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Instance;
/**
* @author evill33t, GodKratos
*/
public class InstanceManager
{
private final static Logger _log = Logger.getLogger(InstanceManager.class.getName());
private final FastMap<Integer, Instance> _instanceList = new FastMap<>();
private final FastMap<Integer, InstanceWorld> _instanceWorlds = new FastMap<>();
private int _dynamic = 300000;
// InstanceId Names
private final static Map<Integer, String> _instanceIdNames = new FastMap<>();
private final Map<Integer, Map<Integer, Long>> _playerInstanceTimes = new FastMap<>();
private static final String ADD_INSTANCE_TIME = "INSERT INTO character_instance_time (charId,instanceId,time) values (?,?,?) ON DUPLICATE KEY UPDATE time=?";
private static final String RESTORE_INSTANCE_TIMES = "SELECT instanceId,time FROM character_instance_time WHERE charId=?";
private static final String DELETE_INSTANCE_TIME = "DELETE FROM character_instance_time WHERE charId=? AND instanceId=?";
public long getInstanceTime(int playerObjId, int id)
{
if (!_playerInstanceTimes.containsKey(playerObjId))
{
restoreInstanceTimes(playerObjId);
}
if (_playerInstanceTimes.get(playerObjId).containsKey(id))
{
return _playerInstanceTimes.get(playerObjId).get(id);
}
return -1;
}
public Map<Integer, Long> getAllInstanceTimes(int playerObjId)
{
if (!_playerInstanceTimes.containsKey(playerObjId))
{
restoreInstanceTimes(playerObjId);
}
return _playerInstanceTimes.get(playerObjId);
}
public void setInstanceTime(int playerObjId, int id, long time)
{
if (!_playerInstanceTimes.containsKey(playerObjId))
{
restoreInstanceTimes(playerObjId);
}
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(ADD_INSTANCE_TIME);
statement.setInt(1, playerObjId);
statement.setInt(2, id);
statement.setLong(3, time);
statement.setLong(4, time);
statement.execute();
statement.close();
_playerInstanceTimes.get(playerObjId).put(id, time);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not insert character instance time data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public void deleteInstanceTime(int playerObjId, int id)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(DELETE_INSTANCE_TIME);
statement.setInt(1, playerObjId);
statement.setInt(2, id);
statement.execute();
statement.close();
_playerInstanceTimes.get(playerObjId).remove(id);
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not delete character instance time data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public void restoreInstanceTimes(int playerObjId)
{
if (_playerInstanceTimes.containsKey(playerObjId))
{
return; // already restored
}
_playerInstanceTimes.put(playerObjId, new FastMap<Integer, Long>());
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(RESTORE_INSTANCE_TIMES);
statement.setInt(1, playerObjId);
ResultSet rset = statement.executeQuery();
while (rset.next())
{
int id = rset.getInt("instanceId");
long time = rset.getLong("time");
if (time < System.currentTimeMillis())
{
deleteInstanceTime(playerObjId, id);
}
else
{
_playerInstanceTimes.get(playerObjId).put(id, time);
}
}
rset.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not delete character instance time data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public String getInstanceIdName(int id)
{
if (_instanceIdNames.containsKey(id))
{
return _instanceIdNames.get(id);
}
return ("UnknownInstance");
}
private void loadInstanceNames()
{
try (InputStream in = new FileInputStream(Config.DATAPACK_ROOT + "/data/instancenames.xml"))
{
XMLStreamReaderImpl xpp = new XMLStreamReaderImpl();
xpp.setInput(new UTF8StreamReader().setInput(in));
for (int e = xpp.getEventType(); e != XMLStreamConstants.END_DOCUMENT; e = xpp.next())
{
if (e == XMLStreamConstants.START_ELEMENT)
{
if (xpp.getLocalName().toString().equals("instance"))
{
Integer id = Integer.valueOf(xpp.getAttributeValue(null, "id").toString());
String name = xpp.getAttributeValue(null, "name").toString();
_instanceIdNames.put(id, name);
}
}
}
}
catch (IOException e)
{
_log.warning("instancenames.xml could not be loaded: file not found");
}
catch (XMLStreamException xppe)
{
_log.log(Level.WARNING, "Error while loading instance names: " + xppe.getMessage(), xppe);
}
}
public static class InstanceWorld
{
public int instanceId;
public int templateId = -1;
public FastList<Integer> allowed = new FastList<>();
public volatile int status;
}
public void addWorld(InstanceWorld world)
{
_instanceWorlds.put(world.instanceId, world);
}
public InstanceWorld getWorld(int instanceId)
{
return _instanceWorlds.get(instanceId);
}
public InstanceWorld getPlayerWorld(L2PcInstance player)
{
for (InstanceWorld temp : _instanceWorlds.values())
{
if (temp == null)
{
continue;
}
// check if the player have a World Instance where he/she is allowed to enter
if (temp.allowed.contains(player.getObjectId()))
{
return temp;
}
}
return null;
}
private InstanceManager()
{
_log.info("Initializing InstanceManager");
loadInstanceNames();
_log.info("Loaded " + _instanceIdNames.size() + " instance names");
createWorld();
}
public static final InstanceManager getInstance()
{
return SingletonHolder._instance;
}
private void createWorld()
{
Instance themultiverse = new Instance(-1);
themultiverse.setName("multiverse");
_instanceList.put(-1, themultiverse);
_log.info("Multiverse Instance created");
Instance universe = new Instance(0);
universe.setName("universe");
_instanceList.put(0, universe);
_log.info("Universe Instance created");
}
public void destroyInstance(int instanceid)
{
if (instanceid <= 0)
{
return;
}
Instance temp = _instanceList.get(instanceid);
if (temp != null)
{
temp.removeNpcs();
temp.removePlayers();
temp.removeDoors();
temp.cancelTimer();
_instanceList.remove(instanceid);
if (_instanceWorlds.containsKey(instanceid))
{
_instanceWorlds.remove(instanceid);
}
}
}
public Instance getInstance(int instanceid)
{
return _instanceList.get(instanceid);
}
public FastMap<Integer, Instance> getInstances()
{
return _instanceList;
}
public int getPlayerInstance(int objectId)
{
for (Instance temp : _instanceList.values())
{
if (temp == null)
{
continue;
}
// check if the player is in any active instance
if (temp.containsPlayer(objectId))
{
return temp.getId();
}
}
// 0 is default instance aka the world
return 0;
}
public boolean createInstance(int id)
{
if (getInstance(id) != null)
{
return false;
}
Instance instance = new Instance(id);
_instanceList.put(id, instance);
return true;
}
public boolean createInstanceFromTemplate(int id, String template)
{
if (getInstance(id) != null)
{
return false;
}
Instance instance = new Instance(id);
_instanceList.put(id, instance);
instance.loadInstanceTemplate(template);
return true;
}
/**
* Create a new instance with a dynamic instance id based on a template (or null)
* @param template xml file
* @return
*/
public int createDynamicInstance(String template)
{
while (getInstance(_dynamic) != null)
{
_dynamic++;
if (_dynamic == Integer.MAX_VALUE)
{
_log.warning("InstanceManager: More then " + (Integer.MAX_VALUE - 300000) + " instances created");
_dynamic = 300000;
}
}
Instance instance = new Instance(_dynamic);
_instanceList.put(_dynamic, instance);
if (template != null)
{
instance.loadInstanceTemplate(template);
}
return _dynamic;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final InstanceManager _instance = new InstanceManager();
}
}
@@ -0,0 +1,182 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntObjectHashMap;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
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.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.itemauction.ItemAuctionInstance;
/**
* @author Forsaiken
*/
public final class ItemAuctionManager
{
private static final Logger _log = Logger.getLogger(ItemAuctionManager.class.getName());
public static final ItemAuctionManager getInstance()
{
return SingletonHolder._instance;
}
private final TIntObjectHashMap<ItemAuctionInstance> _managerInstances;
private final AtomicInteger _auctionIds;
private ItemAuctionManager()
{
_managerInstances = new TIntObjectHashMap<>();
_auctionIds = new AtomicInteger(1);
if (!Config.ALT_ITEM_AUCTION_ENABLED)
{
_log.log(Level.INFO, "ItemAuctionManager: Disabled by config.");
return;
}
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT auctionId FROM item_auction ORDER BY auctionId DESC LIMIT 0, 1");
ResultSet rset = statement.executeQuery();
if (rset.next())
{
_auctionIds.set(rset.getInt(1) + 1);
}
rset.close();
statement.close();
}
catch (final SQLException e)
{
_log.log(Level.SEVERE, "ItemAuctionManager: Failed loading auctions.", e);
}
finally
{
L2DatabaseFactory.close(con);
}
final File file = new File(Config.DATAPACK_ROOT + "/data/ItemAuctions.xml");
if (!file.exists())
{
_log.log(Level.WARNING, "ItemAuctionManager: 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);
}
final ItemAuctionInstance instance = new ItemAuctionInstance(instanceId, _auctionIds, nb);
_managerInstances.put(instanceId, instance);
}
}
}
}
_log.log(Level.INFO, "ItemAuctionManager: Loaded " + _managerInstances.size() + " instance(s).");
}
catch (Exception e)
{
_log.log(Level.SEVERE, "ItemAuctionManager: Failed loading auctions from xml.", e);
}
}
public final void shutdown()
{
final ItemAuctionInstance[] instances = _managerInstances.getValues(new ItemAuctionInstance[_managerInstances.size()]);
for (final ItemAuctionInstance instance : instances)
{
instance.shutdown();
}
}
public final ItemAuctionInstance getManagerInstance(final int instanceId)
{
return _managerInstances.get(instanceId);
}
public final int getNextAuctionId()
{
return _auctionIds.getAndIncrement();
}
public final static void deleteAuction(final int auctionId)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM item_auction WHERE auctionId=?");
statement.setInt(1, auctionId);
statement.execute();
statement.close();
statement = con.prepareStatement("DELETE FROM item_auction_bid WHERE auctionId=?");
statement.setInt(1, auctionId);
statement.execute();
statement.close();
}
catch (final SQLException e)
{
_log.log(Level.SEVERE, "L2ItemAuctionManagerInstance: Failed deleting auction: " + auctionId, e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final ItemAuctionManager _instance = new ItemAuctionManager();
}
}
@@ -0,0 +1,306 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ItemsAutoDestroy;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.templates.item.L2EtcItemType;
/**
* This class manage all items on ground
* @version $Revision: $ $Date: $
* @author DiezelMax - original idea
* @author Enforcer - actual build
*/
public class ItemsOnGroundManager
{
static final Logger _log = Logger.getLogger(ItemsOnGroundManager.class.getName());
protected List<L2ItemInstance> _items = null;
private final StoreInDb _task = new StoreInDb();
private ItemsOnGroundManager()
{
if (Config.SAVE_DROPPED_ITEM)
{
_items = new FastList<>();
}
if (Config.SAVE_DROPPED_ITEM_INTERVAL > 0)
{
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(_task, Config.SAVE_DROPPED_ITEM_INTERVAL, Config.SAVE_DROPPED_ITEM_INTERVAL);
}
load();
}
public static final ItemsOnGroundManager getInstance()
{
return SingletonHolder._instance;
}
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 curently protected will be added to ItemsAutoDestroy
if (Config.DESTROY_DROPPED_PLAYER_ITEM)
{
Connection con = null;
try
{
String str = null;
if (!Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
{
str = "update itemsonground set drop_time=? where drop_time=-1 and equipable=0";
}
else if (Config.DESTROY_EQUIPABLE_PLAYER_ITEM)
{
str = "update itemsonground set drop_time=? where drop_time=-1";
}
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(str);
statement.setLong(1, System.currentTimeMillis());
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error while updating table ItemsOnGround " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
// Add items to world
Connection con = null;
L2ItemInstance item;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT object_id,item_id,count,enchant_level,x,y,z,drop_time,equipable FROM itemsonground");
ResultSet rset;
int count = 0;
rset = statement.executeQuery();
while (rset.next())
{
item = new L2ItemInstance(rset.getInt(1), rset.getInt(2));
L2World.getInstance().storeObject(item);
if (item.isStackable() && (rset.getInt(3) > 1))
{
item.setCount(rset.getInt(3));
}
if (rset.getInt(4) > 0)
{
item.setEnchantLevel(rset.getInt(4));
}
item.getPosition().setWorldPosition(rset.getInt(5), rset.getInt(6), rset.getInt(7));
item.getPosition().setWorldRegion(L2World.getInstance().getRegion(item.getPosition().getWorldPosition()));
item.getPosition().getWorldRegion().addVisibleObject(item);
item.setDropTime(rset.getLong(8));
item.setProtected(rset.getLong(8) == -1);
item.setIsVisible(true);
L2World.getInstance().addVisibleObject(item, item.getPosition().getWorldRegion());
_items.add(item);
count++;
// add to ItemsAutoDestroy only items not protected
if (!Config.LIST_PROTECTED_ITEMS.contains(item.getItemId()))
{
if (rset.getLong(8) > -1)
{
if (((Config.AUTODESTROY_ITEM_AFTER > 0) && (item.getItemType() != L2EtcItemType.HERB)) || ((Config.HERB_AUTO_DESTROY_TIME > 0) && (item.getItemType() == L2EtcItemType.HERB)))
{
ItemsAutoDestroy.getInstance().addItem(item);
}
}
}
}
rset.close();
statement.close();
if (count > 0)
{
_log.info("ItemsOnGroundManager: restored " + count + " items.");
}
else
{
_log.info("Initializing ItemsOnGroundManager.");
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error while loading ItemsOnGround " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
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 != null))
{
_items.remove(item);
}
}
public void saveInDb()
{
_task.run();
}
public void cleanUp()
{
_items.clear();
}
public void emptyTable()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM itemsonground");
statement.execute();
statement.close();
}
catch (Exception e1)
{
_log.log(Level.SEVERE, "Error while cleaning table ItemsOnGround " + e1.getMessage(), e1);
}
finally
{
L2DatabaseFactory.close(con);
}
}
protected class StoreInDb extends Thread
{
@Override
public synchronized void run()
{
if (!Config.SAVE_DROPPED_ITEM)
{
return;
}
emptyTable();
if (_items.isEmpty())
{
if (Config.DEBUG)
{
_log.warning("ItemsOnGroundManager: nothing to save...");
}
return;
}
Connection con = null;
try
{
con = L2DatabaseFactory.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.getItemId()))
{
continue; // Cursed Items not saved to ground, prevent double save
}
try
{
statement.setInt(1, item.getObjectId());
statement.setInt(2, item.getItemId());
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, "Error while inserting into table ItemsOnGround: " + e.getMessage(), e);
}
}
statement.close();
}
catch (SQLException e)
{
_log.log(Level.SEVERE, "SQL error while storing items on ground: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
if (Config.DEBUG)
{
_log.warning("ItemsOnGroundManager: " + _items.size() + " items on ground saved");
}
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final ItemsOnGroundManager _instance = new ItemsOnGroundManager();
}
}
@@ -0,0 +1,388 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Message;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExNoticePostArrived;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
/**
* @author Migi, DS<br>
*/
public class MailManager
{
protected static Logger _log = Logger.getLogger(MailManager.class.getName());
private final Map<Integer, Message> _messages = new FastMap<Integer, Message>().shared();
public static MailManager getInstance()
{
return SingletonHolder._instance;
}
private MailManager()
{
load();
}
private void load()
{
int count = 0;
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM messages ORDER BY expiration");
// stmt2 = con.prepareStatement("SELECT * FROM attachments WHERE messageId = ?");
ResultSet rset1 = statement.executeQuery();
while (rset1.next())
{
Message msg = new Message(rset1);
int msgId = msg.getId();
_messages.put(msgId, msg);
count++;
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());
}
}
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error loading from database:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
_log.info("Mail Manager: Successfully loaded " + count + " messages.");
}
public final Message getMessage(int msgId)
{
return _messages.get(msgId);
}
public final boolean hasUnreadPost(L2PcInstance player)
{
final int objectId = player.getObjectId();
for (Message msg : _messages.values())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && msg.isUnread())
{
return true;
}
}
return false;
}
public final int getInboxSize(int objectId)
{
int size = 0;
for (Message msg : _messages.values())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver())
{
size++;
}
}
return size;
}
public final int getOutboxSize(int objectId)
{
int size = 0;
for (Message msg : _messages.values())
{
if ((msg != null) && (msg.getSenderId() == objectId) && !msg.isDeletedBySender())
{
size++;
}
}
return size;
}
public final List<Message> getInbox(int objectId)
{
List<Message> inbox = new FastList<>();
for (Message msg : _messages.values())
{
if ((msg != null) && (msg.getReceiverId() == objectId) && !msg.isDeletedByReceiver())
{
inbox.add(msg);
}
}
return inbox;
}
public final List<Message> getOutbox(int objectId)
{
List<Message> outbox = new FastList<>();
for (Message msg : _messages.values())
{
if ((msg != null) && (msg.getSenderId() == objectId) && !msg.isDeletedBySender())
{
outbox.add(msg);
}
}
return outbox;
}
public void sendMessage(Message msg)
{
_messages.put(msg.getId(), msg);
Connection con = null;
PreparedStatement stmt = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
stmt = Message.getStatement(msg, con);
stmt.execute();
stmt.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error saving message:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
final L2PcInstance receiver = L2World.getInstance().getPlayer(msg.getReceiverId());
if (receiver != null)
{
receiver.sendPacket(ExNoticePostArrived.valueOf(true));
}
ThreadPoolManager.getInstance().scheduleGeneral(new MessageDeletionTask(msg.getId()), msg.getExpiration() - System.currentTimeMillis());
}
class MessageDeletionTask implements Runnable
{
final int _msgId;
public MessageDeletionTask(int msgId)
{
_msgId = msgId;
}
@Override
public void run()
{
final Message msg = 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(SystemMessage.getSystemMessage(SystemMessageId.MAIL_RETURNED));
}
else
{
msg.getAttachments().returnToWh(null);
}
msg.getAttachments().deleteMe();
msg.removeAttachments();
final L2PcInstance receiver = L2World.getInstance().getPlayer(msg.getReceiverId());
if (receiver != null)
{
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.MAIL_RETURNED);
// sm.addString(msg.getReceiverName());
receiver.sendPacket(sm);
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Mail Manager: Error returning items:" + e.getMessage(), e);
}
}
deleteMessageInDb(msg.getId());
}
}
public final void markAsReadInDb(int msgId)
{
Connection con = null;
PreparedStatement stmt = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
stmt = con.prepareStatement("UPDATE messages SET isUnread = 'false' WHERE messageId = ?");
stmt.setInt(1, msgId);
stmt.execute();
stmt.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error marking as read message:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void markAsDeletedBySenderInDb(int msgId)
{
Connection con = null;
PreparedStatement stmt = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
stmt = con.prepareStatement("UPDATE messages SET isDeletedBySender = 'true' WHERE messageId = ?");
stmt.setInt(1, msgId);
stmt.execute();
stmt.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error marking as deleted by sender message:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void markAsDeletedByReceiverInDb(int msgId)
{
Connection con = null;
PreparedStatement stmt = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
stmt = con.prepareStatement("UPDATE messages SET isDeletedByReceiver = 'true' WHERE messageId = ?");
stmt.setInt(1, msgId);
stmt.execute();
stmt.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error marking as deleted by receiver message:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void removeAttachmentsInDb(int msgId)
{
Connection con = null;
PreparedStatement stmt = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
stmt = con.prepareStatement("UPDATE messages SET hasAttachments = 'false' WHERE messageId = ?");
stmt.setInt(1, msgId);
stmt.execute();
stmt.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error removing attachments in message:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void deleteMessageInDb(int msgId)
{
Connection con = null;
PreparedStatement stmt = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
stmt = con.prepareStatement("DELETE FROM messages WHERE messageId = ?");
stmt.setInt(1, msgId);
stmt.execute();
stmt.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Mail Manager: Error deleting message:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
_messages.remove(msgId);
IdFactory.getInstance().releaseId(msgId);
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final MailManager _instance = new MailManager();
}
}
@@ -0,0 +1,25 @@
/*
* 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.l2jserver.gameserver.instancemanager;
public class Manager
{
public static void reloadAll()
{
AuctionManager.getInstance().reload();
// QuestManager.getInstance().reload();
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,644 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javolution.util.FastList;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.GmListTable;
import com.l2jserver.gameserver.idfactory.IdFactory;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.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;
private static enum PetitionState
{
Pending,
Responder_Cancel,
Responder_Missing,
Responder_Reject,
Responder_Complete,
Petitioner_Cancel,
Petitioner_Missing,
In_Process,
Completed
}
private static enum PetitionType
{
Immobility,
Recovery_Related,
Bug_Report,
Quest_Related,
Bad_User,
Suggestions,
Game_Tip,
Operation_Related,
Other
}
public static PetitionManager getInstance()
{
return SingletonHolder._instance;
}
private class Petition
{
private final long _submitTime = System.currentTimeMillis();
private final int _id;
private final PetitionType _type;
private PetitionState _state = PetitionState.Pending;
private final String _content;
private final List<CreatureSay> _messageLog = new FastList<>();
private final L2PcInstance _petitioner;
private L2PcInstance _responder;
public Petition(L2PcInstance petitioner, String petitionText, int petitionType)
{
petitionType--;
_id = IdFactory.getInstance().getNextId();
if (petitionType >= PetitionType.values().length)
{
_log.warning("PetitionManager:Petition : invalid petition type (received type was +1) : " + petitionType);
}
_type = PetitionType.values()[petitionType];
_content = petitionText;
_petitioner = petitioner;
}
protected boolean addLogMessage(CreatureSay cs)
{
return _messageLog.add(cs);
}
protected List<CreatureSay> getLogMessages()
{
return _messageLog;
}
public boolean endPetitionConsultation(PetitionState endState)
{
setState(endState);
if ((getResponder() != null) && getResponder().isOnline())
{
if (endState == PetitionState.Responder_Reject)
{
getPetitioner().sendMessage("Your petition was rejected. Please try again later.");
}
else
{
// Ending petition consultation with <Player>.
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.PETITION_ENDED_WITH_C1);
sm.addString(getPetitioner().getName());
getResponder().sendPacket(sm);
if (endState == PetitionState.Petitioner_Cancel)
{
// Receipt No. <ID> petition cancelled.
sm = SystemMessage.getSystemMessage(SystemMessageId.RECENT_NO_S1_CANCELED);
sm.addNumber(getId());
getResponder().sendPacket(sm);
}
}
}
// End petition consultation and inform them, if they are still online.
if ((getPetitioner() != null) && getPetitioner().isOnline())
{
getPetitioner().sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THIS_END_THE_PETITION_PLEASE_PROVIDE_FEEDBACK));
}
getCompletedPetitions().put(getId(), this);
return (getPendingPetitions().remove(getId()) != null);
}
public String getContent()
{
return _content;
}
public int getId()
{
return _id;
}
public L2PcInstance getPetitioner()
{
return _petitioner;
}
public L2PcInstance getResponder()
{
return _responder;
}
public long getSubmitTime()
{
return _submitTime;
}
public PetitionState getState()
{
return _state;
}
public String getTypeAsString()
{
return _type.toString().replace("_", " ");
}
public void sendPetitionerPacket(L2GameServerPacket responsePacket)
{
if ((getPetitioner() == null) || !getPetitioner().isOnline())
{
// Allows petitioners to see the results of their petition when
// they log back into the game.
// endPetitionConsultation(PetitionState.Petitioner_Missing);
return;
}
getPetitioner().sendPacket(responsePacket);
}
public void sendResponderPacket(L2GameServerPacket responsePacket)
{
if ((getResponder() == null) || !getResponder().isOnline())
{
endPetitionConsultation(PetitionState.Responder_Missing);
return;
}
getResponder().sendPacket(responsePacket);
}
public void setState(PetitionState state)
{
_state = state;
}
public void setResponder(L2PcInstance respondingAdmin)
{
if (getResponder() != null)
{
return;
}
_responder = respondingAdmin;
}
}
private PetitionManager()
{
_log.info("Initializing PetitionManager");
_pendingPetitions = new FastMap<>();
_completedPetitions = new FastMap<>();
}
public void clearCompletedPetitions()
{
int numPetitions = getPendingPetitionCount();
getCompletedPetitions().clear();
_log.info("PetitionManager: Completed petition data cleared. " + numPetitions + " petition(s) removed.");
}
public void clearPendingPetitions()
{
int numPetitions = getPendingPetitionCount();
getPendingPetitions().clear();
_log.info("PetitionManager: Pending petition queue cleared. " + numPetitions + " petition(s) removed.");
}
public boolean acceptPetition(L2PcInstance respondingAdmin, int petitionId)
{
if (!isValidPetition(petitionId))
{
return false;
}
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_APP_ACCEPTED));
// Petition application accepted. Reciept No. is <ID>
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.PETITION_ACCEPTED_RECENT_NO_S1);
sm.addNumber(currPetition.getId());
currPetition.sendResponderPacket(sm);
// Petition consultation with <Player> underway.
sm = SystemMessage.getSystemMessage(SystemMessageId.STARTING_PETITION_WITH_C1);
sm.addString(currPetition.getPetitioner().getName());
currPetition.sendResponderPacket(sm);
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;
}
protected Map<Integer, Petition> getCompletedPetitions()
{
return _completedPetitions;
}
protected 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;
}
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;
}
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(), Say2.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(), Say2.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>");
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>");
NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0);
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.
Petition newPetition = new Petition(petitioner, petitionText, petitionType);
int newPetitionId = newPetition.getId();
getPendingPetitions().put(newPetitionId, newPetition);
// Notify all GMs that a new petition has been submitted.
String msgContent = petitioner.getName() + " has submitted a new petition."; // (ID: " + newPetitionId + ").";
GmListTable.broadcastToGMs(new CreatureSay(petitioner.getObjectId(), Say2.HERO_VOICE, "Petition System", msgContent));
return newPetitionId;
}
public void viewPetition(L2PcInstance activeChar, int petitionId)
{
if (!activeChar.isGM())
{
return;
}
if (!isValidPetition(petitionId))
{
return;
}
Petition currPetition = getPendingPetitions().get(petitionId);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
NpcHtmlMessage html = new NpcHtmlMessage(0);
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);
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final PetitionManager _instance = new PetitionManager();
}
}
@@ -0,0 +1,201 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.scripting.L2ScriptEngineManager;
import com.l2jserver.gameserver.scripting.ScriptManager;
public class QuestManager extends ScriptManager<Quest>
{
protected static final Logger _log = Logger.getLogger(QuestManager.class.getName());
public static final QuestManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// =========================================================
// Data Field
private final Map<String, Quest> _quests = new FastMap<>();
// =========================================================
// Constructor
private QuestManager()
{
_log.info("Initializing QuestManager");
}
// =========================================================
// Method - Public
public final boolean reload(String questFolder)
{
Quest q = getQuest(questFolder);
if (q == null)
{
return false;
}
return q.reload();
}
/**
* Reloads a the quest given by questId.<BR>
* <B>NOTICE: Will only work if the quest name is equal the quest folder name</B>
* @param questId The id of the quest to be reloaded
* @return true if reload was successful, false otherwise
*/
public final boolean reload(int questId)
{
Quest q = this.getQuest(questId);
if (q == null)
{
return false;
}
return q.reload();
}
public final void reloadAllQuests()
{
_log.info("Reloading Server Scripts");
try
{
// unload all scripts
for (Quest quest : _quests.values())
{
if (quest != null)
{
quest.unload(false);
}
}
_quests.clear();
// now load all scripts
File scripts = new File(Config.DATAPACK_ROOT + "/data/scripts.cfg");
L2ScriptEngineManager.getInstance().executeScriptList(scripts);
QuestManager.getInstance().report();
}
catch (IOException ioe)
{
_log.severe("Failed loading scripts.cfg, no script going to be loaded");
}
}
public final void report()
{
_log.info("Loaded: " + _quests.size() + " quests");
}
public final void save()
{
for (Quest q : _quests.values())
{
q.saveGlobalData();
}
}
// =========================================================
// Property - Public
public final Quest getQuest(String name)
{
return _quests.get(name);
}
public final Quest getQuest(int questId)
{
for (Quest q : _quests.values())
{
if (q.getQuestIntId() == questId)
{
return q;
}
}
return null;
}
public final void addQuest(Quest newQuest)
{
if (newQuest == null)
{
throw new IllegalArgumentException("Quest argument cannot be null");
}
Quest old = _quests.get(newQuest.getName());
// 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...
if (old != null)
{
old.unload();
_log.info("Replaced: (" + old.getName() + ") with a new version (" + newQuest.getName() + ")");
}
_quests.put(newQuest.getName(), newQuest);
}
public final boolean removeQuest(Quest q)
{
return _quests.remove(q.getName()) != null;
}
/**
* @see com.l2jserver.gameserver.scripting.ScriptManager#getAllManagedScripts()
*/
@Override
public Iterable<Quest> getAllManagedScripts()
{
return _quests.values();
}
/**
* @see com.l2jserver.gameserver.scripting.ScriptManager#unload(com.l2jserver.gameserver.scripting.ManagedScript)
*/
@Override
public boolean unload(Quest ms)
{
ms.saveGlobalData();
return removeQuest(ms);
}
/**
* @see com.l2jserver.gameserver.scripting.ScriptManager#getScriptManagerName()
*/
@Override
public String getScriptManagerName()
{
return "QuestManager";
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final QuestManager _instance = new QuestManager();
}
}
@@ -0,0 +1,221 @@
/*
* 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.l2jserver.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.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
/**
* @author Kerberos JIV update 24.8.10
*/
public class RaidBossPointsManager
{
private final static Logger _log = Logger.getLogger(RaidBossPointsManager.class.getName());
private FastMap<Integer, Map<Integer, Integer>> _list;
private final Comparator<Map.Entry<Integer, Integer>> _comparator = (entry, entry1) -> entry.getValue().equals(entry1.getValue()) ? 0 : entry.getValue() < entry1.getValue() ? 1 : -1;
public static final RaidBossPointsManager getInstance()
{
return SingletonHolder._instance;
}
public RaidBossPointsManager()
{
init();
}
private final void init()
{
_list = new FastMap<>();
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT `charId`,`boss_id`,`points` FROM `character_raid_points`");
ResultSet rset = statement.executeQuery();
while (rset.next())
{
int charId = rset.getInt("charId");
int bossId = rset.getInt("boss_id");
int points = rset.getInt("points");
Map<Integer, Integer> values = _list.get(charId);
if (values == null)
{
values = new FastMap<>();
}
values.put(bossId, points);
_list.put(charId, values);
}
rset.close();
statement.close();
_log.info(getClass().getSimpleName() + ": Loaded " + _list.size() + " Characters Raid Points.");
}
catch (SQLException e)
{
_log.log(Level.WARNING, "RaidPointsManager: Couldnt load raid points ", e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void updatePointsInDB(L2PcInstance player, int raidId, int points)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement;
statement = con.prepareStatement("REPLACE INTO character_raid_points (`charId`,`boss_id`,`points`) VALUES (?,?,?)");
statement.setInt(1, player.getObjectId());
statement.setInt(2, raidId);
statement.setInt(3, points);
statement.executeUpdate();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "could not update char raid points:", e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final void addPoints(L2PcInstance player, int bossId, int points)
{
int ownerId = player.getObjectId();
Map<Integer, Integer> tmpPoint = _list.get(ownerId);
if (tmpPoint == null)
{
tmpPoint = new FastMap<>();
tmpPoint.put(bossId, points);
updatePointsInDB(player, bossId, points);
}
else
{
int currentPoins = tmpPoint.containsKey(bossId) ? tmpPoint.get(bossId) : 0;
currentPoins += points;
tmpPoint.put(bossId, currentPoins);
updatePointsInDB(player, bossId, currentPoins);
}
_list.put(ownerId, tmpPoint);
}
public final int getPointsByOwnerId(int ownerId)
{
Map<Integer, Integer> tmpPoint;
tmpPoint = _list.get(ownerId);
int totalPoints = 0;
if ((tmpPoint == null) || tmpPoint.isEmpty())
{
return 0;
}
for (int points : tmpPoint.values())
{
totalPoints += points;
}
return totalPoints;
}
public final Map<Integer, Integer> getList(L2PcInstance player)
{
return _list.get(player.getObjectId());
}
public final void cleanUp()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement;
statement = con.prepareStatement("DELETE from character_raid_points WHERE charId > 0");
statement.executeUpdate();
statement.close();
_list.clear();
}
catch (Exception e)
{
_log.log(Level.WARNING, "could not clean raid points: ", e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public final int calculateRanking(int playerObjId)
{
Map<Integer, Integer> rank = getRankList();
if (rank.containsKey(playerObjId))
{
return rank.get(playerObjId);
}
return 0;
}
public Map<Integer, Integer> getRankList()
{
Map<Integer, Integer> tmpRanking = new FastMap<>();
Map<Integer, Integer> tmpPoints = new FastMap<>();
for (int ownerId : _list.keySet())
{
int totalPoints = getPointsByOwnerId(ownerId);
if (totalPoints != 0)
{
tmpPoints.put(ownerId, totalPoints);
}
}
ArrayList<Entry<Integer, Integer>> list = new ArrayList<>(tmpPoints.entrySet());
Collections.sort(list, _comparator);
int ranking = 1;
for (Map.Entry<Integer, Integer> entry : list)
{
tmpRanking.put(entry.getKey(), ranking++);
}
return tmpRanking;
}
private static class SingletonHolder
{
protected static final RaidBossPointsManager _instance = new RaidBossPointsManager();
}
}
@@ -0,0 +1,562 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastMap;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
import com.l2jserver.gameserver.templates.StatsSet;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
import com.l2jserver.util.Rnd;
/**
* @author godson
*/
public class RaidBossSpawnManager
{
protected static Logger _log = Logger.getLogger(RaidBossSpawnManager.class.getName());
protected static Map<Integer, L2RaidBossInstance> _bosses;
protected static Map<Integer, L2Spawn> _spawns;
protected static Map<Integer, StatsSet> _storedInfo;
protected static Map<Integer, ScheduledFuture<?>> _schedules;
public static enum StatusEnum
{
ALIVE,
DEAD,
UNDEFINED
}
private RaidBossSpawnManager()
{
init();
}
public static RaidBossSpawnManager getInstance()
{
return SingletonHolder._instance;
}
private void init()
{
_bosses = new FastMap<>();
_schedules = new FastMap<>();
_storedInfo = new FastMap<>();
_spawns = new FastMap<>();
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM raidboss_spawnlist ORDER BY boss_id");
ResultSet rset = statement.executeQuery();
L2Spawn spawnDat;
L2NpcTemplate template;
long respawnTime;
while (rset.next())
{
template = getValidTemplate(rset.getInt("boss_id"));
if (template != null)
{
spawnDat = new L2Spawn(template);
spawnDat.setLocx(rset.getInt("loc_x"));
spawnDat.setLocy(rset.getInt("loc_y"));
spawnDat.setLocz(rset.getInt("loc_z"));
spawnDat.setAmount(rset.getInt("amount"));
spawnDat.setHeading(rset.getInt("heading"));
spawnDat.setRespawnMinDelay(rset.getInt("respawn_min_delay"));
spawnDat.setRespawnMaxDelay(rset.getInt("respawn_max_delay"));
respawnTime = rset.getLong("respawn_time");
addNewSpawn(spawnDat, respawnTime, rset.getDouble("currentHP"), rset.getDouble("currentMP"), false);
}
else
{
_log.warning("RaidBossSpawnManager: Could not load raidboss #" + rset.getInt("boss_id") + " from DB");
}
}
_log.info("RaidBossSpawnManager: Loaded " + _bosses.size() + " Instances");
_log.info("RaidBossSpawnManager: Scheduled " + _schedules.size() + " Instances");
rset.close();
statement.close();
}
catch (SQLException e)
{
_log.warning("RaidBossSpawnManager: Couldnt load raidboss_spawnlist table");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while initializing RaidBossSpawnManager: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
private static class spawnSchedule implements Runnable
{
private final int bossId;
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);
StatsSet info = new StatsSet();
info.set("currentHP", raidboss.getCurrentHp());
info.set("currentMP", raidboss.getCurrentMp());
info.set("respawnTime", 0L);
_storedInfo.put(bossId, info);
_log.info("Spawning Raid Boss " + raidboss.getName());
_bosses.put(bossId, raidboss);
}
_schedules.remove(bossId);
}
}
public void updateStatus(L2RaidBossInstance boss, boolean isBossDead)
{
if (!_storedInfo.containsKey(boss.getNpcId()))
{
return;
}
StatsSet info = _storedInfo.get(boss.getNpcId());
if (isBossDead)
{
boss.setRaidStatus(StatusEnum.DEAD);
long respawnTime;
int RespawnMinDelay = boss.getSpawn().getRespawnMinDelay();
int RespawnMaxDelay = boss.getSpawn().getRespawnMaxDelay();
long respawn_delay = Rnd.get((int) (RespawnMinDelay * 1000 * Config.RAID_MIN_RESPAWN_MULTIPLIER), (int) (RespawnMaxDelay * 1000 * Config.RAID_MAX_RESPAWN_MULTIPLIER));
respawnTime = Calendar.getInstance().getTimeInMillis() + respawn_delay;
info.set("currentHP", boss.getMaxHp());
info.set("currentMP", boss.getMaxMp());
info.set("respawnTime", respawnTime);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(respawnTime);
_log.info("RaidBossSpawnManager: Updated " + boss.getName() + " respawn time to " + time.getTime());
if (!_schedules.containsKey(boss.getNpcId()))
{
ScheduledFuture<?> futureSpawn;
futureSpawn = ThreadPoolManager.getInstance().scheduleGeneral(new spawnSchedule(boss.getNpcId()), respawn_delay);
_schedules.put(boss.getNpcId(), futureSpawn);
// To update immediately Database uncomment on the following line, to post the hour of respawn raid boss on your site for example or to envisage a crash landing of the waiter.
updateDb();
}
}
else
{
boss.setRaidStatus(StatusEnum.ALIVE);
info.set("currentHP", boss.getCurrentHp());
info.set("currentMP", boss.getCurrentMp());
info.set("respawnTime", 0L);
}
_storedInfo.put(boss.getNpcId(), info);
}
public void addNewSpawn(L2Spawn spawnDat, long respawnTime, double currentHP, double currentMP, boolean storeInDb)
{
if (spawnDat == null)
{
return;
}
if (_spawns.containsKey(spawnDat.getNpcid()))
{
return;
}
int bossId = spawnDat.getNpcid();
long time = Calendar.getInstance().getTimeInMillis();
SpawnTable.getInstance().addNewSpawn(spawnDat, false);
if ((respawnTime == 0L) || (time > respawnTime))
{
L2RaidBossInstance raidboss = null;
if (bossId == 25328)
{
raidboss = DayNightSpawnManager.getInstance().handleBoss(spawnDat);
}
else
{
raidboss = (L2RaidBossInstance) spawnDat.doSpawn();
}
if (raidboss != null)
{
raidboss.setCurrentHp(currentHP);
raidboss.setCurrentMp(currentMP);
raidboss.setRaidStatus(StatusEnum.ALIVE);
_bosses.put(bossId, raidboss);
StatsSet info = new StatsSet();
info.set("currentHP", currentHP);
info.set("currentMP", currentMP);
info.set("respawnTime", 0L);
_storedInfo.put(bossId, info);
}
}
else
{
ScheduledFuture<?> futureSpawn;
long spawnTime = respawnTime - Calendar.getInstance().getTimeInMillis();
futureSpawn = ThreadPoolManager.getInstance().scheduleGeneral(new spawnSchedule(bossId), spawnTime);
_schedules.put(bossId, futureSpawn);
}
_spawns.put(bossId, spawnDat);
if (storeInDb)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO raidboss_spawnlist (boss_id,amount,loc_x,loc_y,loc_z,heading,respawn_time,currentHp,currentMp) VALUES(?,?,?,?,?,?,?,?,?)");
statement.setInt(1, spawnDat.getNpcid());
statement.setInt(2, spawnDat.getAmount());
statement.setInt(3, spawnDat.getLocx());
statement.setInt(4, spawnDat.getLocy());
statement.setInt(5, spawnDat.getLocz());
statement.setInt(6, spawnDat.getHeading());
statement.setLong(7, respawnTime);
statement.setDouble(8, currentHP);
statement.setDouble(9, currentMP);
statement.execute();
statement.close();
}
catch (Exception e)
{
// problem with storing spawn
_log.log(Level.WARNING, "RaidBossSpawnManager: Could not store raidboss #" + bossId + " in the DB:" + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
}
public void deleteSpawn(L2Spawn spawnDat, boolean updateDb)
{
if (spawnDat == null)
{
return;
}
if (!_spawns.containsKey(spawnDat.getNpcid()))
{
return;
}
int bossId = spawnDat.getNpcid();
SpawnTable.getInstance().deleteSpawn(spawnDat, false);
_spawns.remove(bossId);
if (_bosses.containsKey(bossId))
{
_bosses.remove(bossId);
}
if (_schedules.containsKey(bossId))
{
ScheduledFuture<?> f = _schedules.get(bossId);
f.cancel(true);
_schedules.remove(bossId);
}
if (_storedInfo.containsKey(bossId))
{
_storedInfo.remove(bossId);
}
if (updateDb)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM raidboss_spawnlist WHERE boss_id=?");
statement.setInt(1, bossId);
statement.execute();
statement.close();
}
catch (Exception e)
{
// problem with deleting spawn
_log.log(Level.WARNING, "RaidBossSpawnManager: Could not remove raidboss #" + bossId + " from DB: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
}
private void updateDb()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("UPDATE raidboss_spawnlist SET respawn_time = ?, currentHP = ?, currentMP = ? WHERE boss_id = ?");
for (Integer bossId : _storedInfo.keySet())
{
if (bossId == null)
{
continue;
}
L2RaidBossInstance boss = _bosses.get(bossId);
if (boss == null)
{
continue;
}
if (boss.getRaidStatus().equals(StatusEnum.ALIVE))
{
updateStatus(boss, false);
}
StatsSet info = _storedInfo.get(bossId);
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, bossId);
statement.executeUpdate();
statement.clearParameters();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "RaidBossSpawnManager: Couldnt update raidboss_spawnlist table " + e.getMessage(), e);
}
}
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "SQL error while updating RaidBoss spawn to database: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public String[] getAllRaidBossStatus()
{
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())
{
L2RaidBossInstance boss = _bosses.get(i);
msg[index++] = boss.getName() + ": " + boss.getRaidStatus().name();
}
return msg;
}
public String getRaidBossStatus(int bossId)
{
String msg = "RaidBoss Status....\n";
if (_bosses == null)
{
msg += "None";
return msg;
}
if (_bosses.containsKey(bossId))
{
L2RaidBossInstance boss = _bosses.get(bossId);
msg += boss.getName() + ": " + boss.getRaidStatus().name();
}
return msg;
}
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;
}
}
public L2NpcTemplate getValidTemplate(int bossId)
{
L2NpcTemplate template = NpcTable.getInstance().getTemplate(bossId);
if (template == null)
{
return null;
}
if (!template.type.equalsIgnoreCase("L2RaidBoss"))
{
return null;
}
return template;
}
public void notifySpawnNightBoss(L2RaidBossInstance raidboss)
{
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.getNpcId(), info);
_log.info("Spawning Night Raid Boss " + raidboss.getName());
_bosses.put(raidboss.getNpcId(), raidboss);
}
public boolean isDefined(int bossId)
{
return _spawns.containsKey(bossId);
}
public Map<Integer, L2RaidBossInstance> getBosses()
{
return _bosses;
}
public Map<Integer, L2Spawn> getSpawns()
{
return _spawns;
}
public void reloadBosses()
{
init();
}
/**
* Saves all raidboss status and then clears all info from memory, including all schedules.
*/
public void cleanUp()
{
updateDb();
_bosses.clear();
if (_schedules != null)
{
for (Integer bossId : _schedules.keySet())
{
ScheduledFuture<?> f = _schedules.get(bossId);
f.cancel(true);
}
}
_schedules.clear();
_storedInfo.clear();
_spawns.clear();
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final RaidBossSpawnManager _instance = new RaidBossSpawnManager();
}
}
@@ -0,0 +1,306 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.NpcTable;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
public class SiegeGuardManager
{
private static Logger _log = Logger.getLogger(SiegeGuardManager.class.getName());
// =========================================================
// Data Field
private final Castle _castle;
private final List<L2Spawn> _siegeGuardSpawn = new FastList<>();
// =========================================================
// Constructor
public SiegeGuardManager(Castle castle)
{
_castle = castle;
}
// =========================================================
// Method - Public
/**
* Add guard.<BR>
* <BR>
*/
public void addSiegeGuard(L2PcInstance activeChar, int npcId)
{
if (activeChar == null)
{
return;
}
addSiegeGuard(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
}
/**
* Add guard.<BR>
* <BR>
*/
public void addSiegeGuard(int x, int y, int z, int heading, int npcId)
{
saveSiegeGuard(x, y, z, heading, npcId, 0);
}
/**
* Hire merc.<BR>
* <BR>
*/
public void hireMerc(L2PcInstance activeChar, int npcId)
{
if (activeChar == null)
{
return;
}
hireMerc(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
}
/**
* Hire merc.<BR>
* <BR>
*/
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
*/
public void removeMerc(int npcId, int x, int y, int z)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("Delete From castle_siege_guards Where npcId = ? And x = ? AND y = ? AND z = ? AND isHired = 1");
statement.setInt(1, npcId);
statement.setInt(2, x);
statement.setInt(3, y);
statement.setInt(4, z);
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error deleting hired siege guard at " + x + ',' + y + ',' + z + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/**
* Remove mercs.<BR>
* <BR>
*/
public void removeMercs()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("Delete From castle_siege_guards Where castleId = ? And isHired = 1");
statement.setInt(1, getCastle().getCastleId());
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error deleting hired siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/**
* Spawn guards.<BR>
* <BR>
*/
public void spawnSiegeGuard()
{
try
{
int hiredCount = 0, hiredMax = MercTicketManager.getInstance().getMaxAllowedMerc(_castle.getCastleId());
boolean isHired = (getCastle().getOwnerId() > 0) ? true : false;
loadSiegeGuard();
for (L2Spawn spawn : getSiegeGuardSpawn())
{
if (spawn != null)
{
spawn.init();
if (isHired)
{
spawn.stopRespawn();
if (++hiredCount > hiredMax)
{
return;
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error spawning siege guards for castle " + getCastle().getName(), e);
}
}
/**
* Unspawn guards.<BR>
* <BR>
*/
public void unspawnSiegeGuard()
{
for (L2Spawn spawn : getSiegeGuardSpawn())
{
if (spawn == null)
{
continue;
}
spawn.stopRespawn();
spawn.getLastSpawn().doDie(spawn.getLastSpawn());
}
getSiegeGuardSpawn().clear();
}
// =========================================================
// Method - Private
/**
* Load guards.<BR>
* <BR>
*/
private void loadSiegeGuard()
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT * FROM castle_siege_guards Where castleId = ? And isHired = ?");
statement.setInt(1, getCastle().getCastleId());
if (getCastle().getOwnerId() > 0)
{
statement.setInt(2, 1);
}
else
{
statement.setInt(2, 0);
}
ResultSet rs = statement.executeQuery();
L2Spawn spawn1;
L2NpcTemplate template1;
while (rs.next())
{
template1 = NpcTable.getInstance().getTemplate(rs.getInt("npcId"));
if (template1 != null)
{
spawn1 = new L2Spawn(template1);
spawn1.setAmount(1);
spawn1.setLocx(rs.getInt("x"));
spawn1.setLocy(rs.getInt("y"));
spawn1.setLocz(rs.getInt("z"));
spawn1.setHeading(rs.getInt("heading"));
spawn1.setRespawnDelay(rs.getInt("respawnDelay"));
spawn1.setLocation(0);
_siegeGuardSpawn.add(spawn1);
}
else
{
_log.warning("Missing npc data in npc table for id: " + rs.getInt("npcId"));
}
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error loading siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
/**
* Save guards.<BR>
* <BR>
*/
private void saveSiegeGuard(int x, int y, int z, int heading, int npcId, int isHire)
{
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("Insert Into castle_siege_guards (castleId, npcId, x, y, z, heading, respawnDelay, isHired) Values (?, ?, ?, ?, ?, ?, ?, ?)");
statement.setInt(1, getCastle().getCastleId());
statement.setInt(2, npcId);
statement.setInt(3, x);
statement.setInt(4, y);
statement.setInt(5, z);
statement.setInt(6, heading);
statement.setInt(7, (isHire == 1 ? 0 : 600));
statement.setInt(8, isHire);
statement.execute();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error adding siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
// =========================================================
// Proeprty
public final Castle getCastle()
{
return _castle;
}
public final List<L2Spawn> getSiegeGuardSpawn()
{
return _siegeGuardSpawn;
}
}
@@ -0,0 +1,445 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntObjectHashMap;
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.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javolution.util.FastList;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.datatables.SkillTable;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Skill;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.entity.Siege;
public class SiegeManager
{
private static final Logger _log = Logger.getLogger(SiegeManager.class.getName());
public static final SiegeManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Data Field
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
// Siege settings
private TIntObjectHashMap<FastList<SiegeSpawn>> _artefactSpawnList;
private TIntObjectHashMap<FastList<SiegeSpawn>> _controlTowerSpawnList;
private TIntObjectHashMap<FastList<SiegeSpawn>> _flameTowerSpawnList;
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
// =========================================================
// Constructor
private SiegeManager()
{
_log.info("Initializing SiegeManager");
load();
}
// =========================================================
// Method - Public
public final void addSiegeSkills(L2PcInstance character)
{
for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(character.isNoble(), character.getClan().getHasCastle() > 0))
{
character.addSkill(sk, false);
}
}
/**
* Return true if character summon<BR>
* <BR>
* @param activeChar The L2Character of the character can summon
*/
public final boolean checkIfOkToSummon(L2Character activeChar, boolean isCheckOnly)
{
if (!(activeChar instanceof L2PcInstance))
{
return false;
}
String text = "";
L2PcInstance player = (L2PcInstance) activeChar;
Castle castle = CastleManager.getInstance().getCastle(player);
if ((castle == null) || (castle.getCastleId() <= 0))
{
text = "You must be on castle ground to summon this";
}
else if (!castle.getSiege().getIsInProgress())
{
text = "You can only summon this during a siege.";
}
else if ((player.getClanId() != 0) && (castle.getSiege().getAttackerClan(player.getClanId()) == null))
{
text = "You can only summon this as a registered attacker.";
}
else
{
return true;
}
if (!isCheckOnly)
{
player.sendMessage(text);
}
return false;
}
/**
* Return true if the clan is registered or owner of a castle<BR>
* <BR>
* @param clan The L2Clan of the player
*/
public final boolean checkIsRegistered(L2Clan clan, int castleid)
{
if (clan == null)
{
return false;
}
if (clan.getHasCastle() > 0)
{
return true;
}
Connection con = null;
boolean register = false;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("SELECT clan_id FROM siege_clans where clan_id=? and castle_id=?");
statement.setInt(1, clan.getClanId());
statement.setInt(2, castleid);
ResultSet rs = statement.executeQuery();
while (rs.next())
{
register = true;
break;
}
rs.close();
statement.close();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: checkIsRegistered(): " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
return register;
}
public final void removeSiegeSkills(L2PcInstance character)
{
for (L2Skill sk : SkillTable.getInstance().getSiegeSkills(character.isNoble(), character.getClan().getHasCastle() > 0))
{
character.removeSkill(sk);
}
}
// =========================================================
// Method - Private
private final void load()
{
try (InputStream is = new FileInputStream(new File(Config.SIEGE_CONFIGURATION_FILE)))
{
Properties siegeSettings = new Properties();
siegeSettings.load(is);
// Siege setting
_attackerMaxClans = Integer.decode(siegeSettings.getProperty("AttackerMaxClans", "500"));
_attackerRespawnDelay = Integer.decode(siegeSettings.getProperty("AttackerRespawn", "0"));
_defenderMaxClans = Integer.decode(siegeSettings.getProperty("DefenderMaxClans", "500"));
_flagMaxCount = Integer.decode(siegeSettings.getProperty("MaxFlags", "1"));
_siegeClanMinLevel = Integer.decode(siegeSettings.getProperty("SiegeClanMinLevel", "5"));
_siegeLength = Integer.decode(siegeSettings.getProperty("SiegeLength", "120"));
_bloodAllianceReward = Integer.decode(siegeSettings.getProperty("BloodAllianceReward", "0"));
// Siege spawns settings
_controlTowerSpawnList = new TIntObjectHashMap<>();
_artefactSpawnList = new TIntObjectHashMap<>();
_flameTowerSpawnList = new TIntObjectHashMap<>();
for (Castle castle : CastleManager.getInstance().getCastles())
{
FastList<SiegeSpawn> _controlTowersSpawns = new FastList<>();
for (int i = 1; i < 0xFF; i++)
{
String _spawnParams = siegeSettings.getProperty(castle.getName() + "ControlTower" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int z = Integer.parseInt(st.nextToken());
int npc_id = Integer.parseInt(st.nextToken());
int hp = Integer.parseInt(st.nextToken());
_controlTowersSpawns.add(new SiegeSpawn(castle.getCastleId(), x, y, z, 0, npc_id, hp));
}
catch (Exception e)
{
_log.warning("Error while loading control tower(s) for " + castle.getName() + " castle.");
}
}
FastList<SiegeSpawn> _flameTowersSpawns = new FastList<>();
for (int i = 1; i < 0xFF; i++)
{
String _spawnParams = siegeSettings.getProperty(castle.getName() + "FlameTower" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int z = Integer.parseInt(st.nextToken());
int npc_id = Integer.parseInt(st.nextToken());
int hp = Integer.parseInt(st.nextToken());
_flameTowersSpawns.add(new SiegeSpawn(castle.getCastleId(), x, y, z, 0, npc_id, hp));
}
catch (Exception e)
{
_log.warning("Error while loading artefact(s) for " + castle.getName() + " castle.");
}
}
FastList<SiegeSpawn> _artefactSpawns = new FastList<>();
for (int i = 1; i < 0xFF; i++)
{
String _spawnParams = siegeSettings.getProperty(castle.getName() + "Artefact" + i, "");
if (_spawnParams.isEmpty())
{
break;
}
StringTokenizer st = new StringTokenizer(_spawnParams.trim(), ",");
try
{
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int z = Integer.parseInt(st.nextToken());
int heading = Integer.parseInt(st.nextToken());
int npc_id = Integer.parseInt(st.nextToken());
_artefactSpawns.add(new SiegeSpawn(castle.getCastleId(), x, y, z, heading, npc_id));
}
catch (Exception e)
{
_log.warning("Error while loading artefact(s) for " + castle.getName() + " castle.");
}
}
MercTicketManager.MERCS_MAX_PER_CASTLE[castle.getCastleId() - 1] = Integer.parseInt(siegeSettings.getProperty(castle.getName() + "MaxMercenaries", Integer.toString(MercTicketManager.MERCS_MAX_PER_CASTLE[castle.getCastleId() - 1])).trim());
_controlTowerSpawnList.put(castle.getCastleId(), _controlTowersSpawns);
_artefactSpawnList.put(castle.getCastleId(), _artefactSpawns);
_flameTowerSpawnList.put(castle.getCastleId(), _flameTowersSpawns);
}
}
catch (Exception e)
{
// _initialized = false;
_log.log(Level.WARNING, "Error while loading siege data: " + e.getMessage(), e);
}
}
// =========================================================
// Property - Public
public final FastList<SiegeSpawn> getArtefactSpawnList(int _castleId)
{
return _artefactSpawnList.get(_castleId);
}
public final FastList<SiegeSpawn> getControlTowerSpawnList(int _castleId)
{
return _controlTowerSpawnList.get(_castleId);
}
public final FastList<SiegeSpawn> getFlameTowerSpawnList(int _castleId)
{
return _flameTowerSpawnList.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(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()
{
FastList<Siege> sieges = new FastList<>();
for (Castle castle : CastleManager.getInstance().getCastles())
{
sieges.add(castle.getSiege());
}
return sieges;
}
public static class SiegeSpawn
{
Location _location;
private final int _npcId;
private final int _heading;
private final int _castleId;
private int _hp;
public SiegeSpawn(int castle_id, int x, int y, int z, int heading, int npc_id)
{
_castleId = castle_id;
_location = new Location(x, y, z, heading);
_heading = heading;
_npcId = npc_id;
}
public SiegeSpawn(int castle_id, int x, int y, int z, int heading, int npc_id, int hp)
{
_castleId = castle_id;
_location = new Location(x, y, z, heading);
_heading = heading;
_npcId = npc_id;
_hp = hp;
}
public int getCastleId()
{
return _castleId;
}
public int getNpcId()
{
return _npcId;
}
public int getHeading()
{
return _heading;
}
public int getHp()
{
return _hp;
}
public Location getLocation()
{
return _location;
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final SiegeManager _instance = new SiegeManager();
}
}
@@ -0,0 +1,381 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import com.l2jserver.gameserver.datatables.MapRegionTable;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.model.zone.type.L2TownZone;
public class TownManager
{
// private static final Logger _log = Logger.getLogger(TownManager.class.getName());
// =========================================================
// Property - Public
public final static L2TownZone getClosestTown(L2Object activeObject)
{
switch (MapRegionTable.getInstance().getMapRegion(activeObject.getPosition().getX(), activeObject.getPosition().getY()))
{
case 0:
return getTown(2); // TI
case 1:
return getTown(3); // Elven
case 2:
return getTown(1); // DE
case 3:
return getTown(4); // Orc
case 4:
return getTown(6); // Dwarven
case 5:
return getTown(7); // Gludio
case 6:
return getTown(5); // Gludin
case 7:
return getTown(8); // Dion
case 8:
return getTown(9); // Giran
case 9:
return getTown(10); // Oren
case 10:
return getTown(12); // Aden
case 11:
return getTown(11); // HV
case 12:
return getTown(9); // Giran Harbour
case 13:
return getTown(15); // Heine
case 14:
return getTown(14); // Rune
case 15:
return getTown(13); // Goddard
case 16:
return getTown(17); // Schuttgart
case 17:
return getTown(16); // Floran
case 18:
return getTown(19); // Primeval Isle
case 19:
return getTown(20); // Kamael Village
case 20:
return getTown(21); // South of Wastelands Camp
case 21:
return getTown(22); // Fantasy Island
case 22:
return getTown(23); // Neutral Zone
case 23:
return getTown(24);// Coliseum
case 24:
return getTown(25);// GM Consultation service
case 25:
return getTown(26);// Dimensional Gap
case 26:
return getTown(27);// Cemetery of the Empire
case 27:
return getTown(28);// inside the Steel Citadel
case 28:
return getTown(29);// Steel Citadel Resistance
case 29:
return getTown(30);// Inside Kamaloka
case 30:
return getTown(31);// Inside Nia Kamaloka
case 31:
return getTown(32);// Inside Rim Kamaloka
case 32:
return getTown(33);// near the Keucereus clan association location
case 33:
return getTown(34);// inside the Seed of Infinity
case 34:
return getTown(35);// outside the Seed of Infinity
case 35:
return getTown(36);// inside Aerial Cleft
}
return getTown(16); // Default to floran
}
public final static L2TownZone getSecondClosestTown(L2Object activeObject)
{
switch (MapRegionTable.getInstance().getMapRegion(activeObject.getPosition().getX(), activeObject.getPosition().getY()))
{
case 0:
return getTown(5); // TI
case 1:
return getTown(5); // Elven
case 2:
return getTown(5); // DE
case 3:
return getTown(4); // Orc
case 4:
return getTown(6); // Dwarven
case 5:
return getTown(5); // Gludio
case 6:
return getTown(5); // Gludin
case 7:
return getTown(7); // Dion
case 8:
return getTown(11); // Giran
case 9:
return getTown(11); // Oren
case 10:
return getTown(11); // Aden
case 11:
return getTown(11); // HV
case 12:
return getTown(16); // Giran Harbour
case 13:
return getTown(16); // Heine
case 14:
return getTown(13); // Rune
case 15:
return getTown(12); // Goddard
case 16:
return getTown(6); // Schuttgart
case 17:
return getTown(16); // Floran
case 18:
return getTown(19); // Primeval Isle
case 19:
return getTown(20); // Kamael Village
case 20:
return getTown(21); // South of Wastelands Camp
case 21:
return getTown(22); // Fantasy Island
case 22:
return getTown(23); // Neutral Zone
case 23:
return getTown(24);// Coliseum
case 24:
return getTown(25);// GM Consultation service
case 25:
return getTown(26);// Dimensional Gap
case 26:
return getTown(27);// Cemetery of the Empire
case 27:
return getTown(28);// inside the Steel Citadel
case 28:
return getTown(29);// Steel Citadel Resistance
case 29:
return getTown(30);// Inside Kamaloka
case 30:
return getTown(31);// Inside Nia Kamaloka
case 31:
return getTown(32);// Inside Rim Kamaloka
case 32:
return getTown(33);// near the Keucereus clan association location
case 33:
return getTown(34);// inside the Seed of Infinity
case 34:
return getTown(35);// outside the Seed of Infinity
case 35:
return getTown(36);// inside Aerial Cleft
}
return getTown(16); // Default to floran
}
public final static int getClosestLocation(L2Object activeObject)
{
switch (MapRegionTable.getInstance().getMapRegion(activeObject.getPosition().getX(), activeObject.getPosition().getY()))
{
case 0:
return 1; // TI
case 1:
return 4; // Elven
case 2:
return 3; // DE
case 3:
return 9; // Orc
case 4:
return 9; // Dwarven
case 5:
return 2; // Gludio
case 6:
return 2; // Gludin
case 7:
return 5; // Dion
case 8:
return 6; // Giran
case 9:
return 10; // Oren
case 10:
return 13; // Aden
case 11:
return 11; // HV
case 12:
return 6; // Giran Harbour
case 13:
return 12; // Heine
case 14:
return 14; // Rune
case 15:
return 15; // Goddard
case 16:
return 9; // Schuttgart
/*
* case 17: return getTown(16); // Floran case 18: return getTown(19); //Primeval Isle case 19: return getTown(20); //Kamael Village case 20: return getTown(21); //South of Wastelands Camp case 21: return getTown(22); //Fantasy Island case 22: return 7; //Neutral Zone case 23: return
* getTown(24);//Coliseum case 24: return getTown(25);//GM Consultation service case 25: return getTown(26);//Dimensional Gap case 26: return getTown(27);//Cemetery of the Empire case 27: return getTown(28);//inside the Steel Citadel case 28: return getTown(29);//Steel Citadel
* Resistance case 29: return getTown(30);//Inside Kamaloka case 30: return getTown(31);//Inside Nia Kamaloka case 31: return getTown(32);//Inside Rim Kamaloka case 32: return getTown(33);//near the Keucereus clan association location case 33: return getTown(34);//inside the Seed of
* Infinity case 34: return getTown(35);//outside the Seed of Infinity case 35: return getTown(36);//inside Aerial Cleft
*/
}
return 0;
}
public final static boolean townHasCastleInSiege(int townId)
{
// int[] castleidarray = {0,0,0,0,0,0,0,1,2,3,4,0,5,0,0,6,0};
int[] castleidarray =
{
0,
0,
0,
0,
0,
0,
0,
1,
2,
3,
4,
0,
5,
7,
8,
6,
0,
9,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
};
int castleIndex = castleidarray[townId];
if (castleIndex > 0)
{
Castle castle = CastleManager.getInstance().getCastles().get(CastleManager.getInstance().getCastleIndex(castleIndex));
if (castle != null)
{
return castle.getSiege().getIsInProgress();
}
}
return false;
}
public final static boolean townHasCastleInSiege(int x, int y)
{
int curtown = (MapRegionTable.getInstance().getMapRegion(x, y));
// int[] castleidarray = {0,0,0,0,0,1,0,2,3,4,5,0,0,6,0,0,0,0};
int[] castleidarray =
{
0,
0,
0,
0,
0,
1,
0,
2,
3,
4,
5,
0,
0,
6,
8,
7,
9,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
};
// find an instance of the castle for this town.
int castleIndex = castleidarray[curtown];
if (castleIndex > 0)
{
Castle castle = CastleManager.getInstance().getCastles().get(CastleManager.getInstance().getCastleIndex(castleIndex));
if (castle != null)
{
return castle.getSiege().getIsInProgress();
}
}
return false;
}
public final 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 final 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;
}
}
@@ -0,0 +1,75 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import gnu.trove.TIntObjectHashMap;
import java.util.logging.Logger;
import com.l2jserver.gameserver.model.L2Transformation;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
/**
* @author KenM
*/
public class TransformationManager
{
private static final Logger _log = Logger.getLogger(TransformationManager.class.getName());
public static TransformationManager getInstance()
{
return SingletonHolder._instance;
}
private final TIntObjectHashMap<L2Transformation> _transformations;
private TransformationManager()
{
_transformations = new TIntObjectHashMap<>();
}
public void report()
{
_log.info("Loaded: " + _transformations.size() + " transformations.");
}
public boolean transformPlayer(int id, L2PcInstance player)
{
L2Transformation template = getTransformationById(id);
if (template != null)
{
L2Transformation trans = template.createTransformationForPlayer(player);
trans.start();
return true;
}
return false;
}
public L2Transformation getTransformationById(int id)
{
return _transformations.get(id);
}
public L2Transformation registerTransformation(L2Transformation transformation)
{
return _transformations.put(transformation.getId(), transformation);
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final TransformationManager _instance = new TransformationManager();
}
}
@@ -0,0 +1,721 @@
/*
* 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.l2jserver.gameserver.instancemanager;
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import javolution.util.FastList;
import javolution.util.FastMap;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.Config;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2World;
import com.l2jserver.gameserver.model.L2WorldRegion;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.zone.L2SpawnZone;
import com.l2jserver.gameserver.model.zone.L2ZoneType;
import com.l2jserver.gameserver.model.zone.form.ZoneCuboid;
import com.l2jserver.gameserver.model.zone.form.ZoneCylinder;
import com.l2jserver.gameserver.model.zone.form.ZoneNPoly;
import com.l2jserver.gameserver.model.zone.type.L2ArenaZone;
import com.l2jserver.gameserver.model.zone.type.L2OlympiadStadiumZone;
/**
* This class manages the zones
* @author durgus
*/
public class ZoneManager
{
private static final Logger _log = Logger.getLogger(ZoneManager.class.getName());
// private final FastMap<Integer, L2ZoneType> _zones = new FastMap<Integer, L2ZoneType>();
private final Map<Class<? extends L2ZoneType>, Map<Integer, ? extends L2ZoneType>> _classZones = new FastMap<>();
private int _lastDynamicId = 300000;
private List<L2ItemInstance> _debugItems;
public static final ZoneManager getInstance()
{
return SingletonHolder._instance;
}
// =========================================================
// Data Field
// =========================================================
// Constructor
private ZoneManager()
{
load();
}
@SuppressWarnings("deprecation")
public void reload()
{
// int zoneCount = 0;
// Get the world regions
int count = 0;
L2WorldRegion[][] worldRegions = L2World.getInstance().getAllWorldRegions();
for (L2WorldRegion[] worldRegion : worldRegions)
{
for (L2WorldRegion element : worldRegion)
{
element.getZones().clear();
count++;
}
}
GrandBossManager.getInstance().getZones().clear();
_log.info("Removed zones in " + count + " regions.");
// Load the zones
load();
for (L2Object o : L2World.getInstance().getAllVisibleObjects().values())
{
if (o instanceof L2Character)
{
((L2Character) o).revalidateZone(true);
}
}
}
// =========================================================
// Method - Private
private final void load()
{
_log.info("Loading zones...");
_classZones.clear();
// Get the world regions
L2WorldRegion[][] worldRegions = L2World.getInstance().getAllWorldRegions();
// Load the zone xml
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
final File dir = new File(Config.DATAPACK_ROOT, "data/zones");
if (!dir.exists())
{
_log.config("Dir " + dir.getAbsolutePath() + " not exists");
return;
}
File[] files = dir.listFiles();
FastList<File> hash = new FastList<>(files.length);
for (File f : files)
{
// default file first
if ("zone.xml".equalsIgnoreCase(f.getName()))
{
hash.addFirst(f);
}
else if (f.getName().endsWith(".xml"))
{
hash.add(f);
}
}
Document doc;
NamedNodeMap attrs;
Node attribute;
String zoneName;
int[][] coords;
int zoneId, minZ, maxZ;
String zoneType, zoneShape;
for (File f : hash)
{
doc = factory.newDocumentBuilder().parse(f);
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
attrs = n.getAttributes();
attribute = attrs.getNamedItem("enabled");
if ((attribute != null) && !Boolean.parseBoolean(attribute.getNodeValue()))
{
continue;
}
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("zone".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
attribute = attrs.getNamedItem("id");
if (attribute != null)
{
zoneId = Integer.parseInt(attribute.getNodeValue());
}
else
{
zoneId = _lastDynamicId++;
}
attribute = attrs.getNamedItem("name");
if (attribute != null)
{
zoneName = attribute.getNodeValue();
}
else
{
zoneName = null;
}
attribute = attrs.getNamedItem("minZ");
if (attribute != null)
{
minZ = Integer.parseInt(attribute.getNodeValue());
}
else
{
_log.warning("ZoneData: Missing minZ for zone: " + zoneId + " in file: " + f.getName());
continue;
}
attribute = attrs.getNamedItem("maxZ");
if (attribute != null)
{
maxZ = Integer.parseInt(attribute.getNodeValue());
}
else
{
_log.warning("ZoneData: Missing maxZ for zone: " + zoneId + " in file: " + f.getName());
continue;
}
attribute = attrs.getNamedItem("type");
if (attribute != null)
{
zoneType = attribute.getNodeValue();
}
else
{
_log.warning("ZoneData: Missing type for zone: " + zoneId + " in file: " + f.getName());
continue;
}
attribute = attrs.getNamedItem("shape");
if (attribute != null)
{
zoneShape = attribute.getNodeValue();
}
else
{
_log.warning("ZoneData: Missing shape for zone: " + zoneId + " in file: " + f.getName());
continue;
}
// Create the zone
Class<?> newZone;
try
{
newZone = Class.forName("com.l2jserver.gameserver.model.zone.type.L2" + zoneType);
}
catch (ClassNotFoundException e)
{
_log.warning("ZoneData: No such zone type: " + zoneType + " in file: " + f.getName());
continue;
}
Constructor<?> zoneConstructor = newZone.getConstructor(int.class);
L2ZoneType temp = (L2ZoneType) zoneConstructor.newInstance(zoneId);
// Get the zone shape from sql
try
{
coords = null;
int[] point;
FastList<int[]> rs = FastList.newInstance();
try
{
// loading from XML first
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("node".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
point = new int[2];
point[0] = Integer.parseInt(attrs.getNamedItem("X").getNodeValue());
point[1] = Integer.parseInt(attrs.getNamedItem("Y").getNodeValue());
rs.add(point);
}
}
coords = rs.toArray(new int[rs.size()][]);
}
finally
{
FastList.recycle(rs);
}
if ((coords == null) || (coords.length == 0))
{
_log.warning("ZoneData: missing data for zone: " + zoneId + " in both XML and SQL, file: " + f.getName());
continue;
}
// Create this zone. Parsing for cuboids is a
// bit different than for other polygons
// cuboids need exactly 2 points to be defined.
// Other polygons need at least 3 (one per
// vertex)
if (zoneShape.equalsIgnoreCase("Cuboid"))
{
if (coords.length == 2)
{
temp.setZone(new ZoneCuboid(coords[0][0], coords[1][0], coords[0][1], coords[1][1], minZ, maxZ));
}
else
{
_log.warning("ZoneData: Missing cuboid vertex in sql data for zone: " + zoneId + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("NPoly"))
{
// nPoly needs to have at least 3 vertices
if (coords.length > 2)
{
final int[] aX = new int[coords.length];
final int[] aY = new int[coords.length];
for (int i = 0; i < coords.length; i++)
{
aX[i] = coords[i][0];
aY[i] = coords[i][1];
}
temp.setZone(new ZoneNPoly(aX, aY, minZ, maxZ));
}
else
{
_log.warning("ZoneData: Bad data for zone: " + zoneId + " in file: " + f.getName());
continue;
}
}
else if (zoneShape.equalsIgnoreCase("Cylinder"))
{
// A Cylinder zone requires a center point
// at x,y and a radius
attrs = d.getAttributes();
final int zoneRad = Integer.parseInt(attrs.getNamedItem("rad").getNodeValue());
if ((coords.length == 1) && (zoneRad > 0))
{
temp.setZone(new ZoneCylinder(coords[0][0], coords[0][1], minZ, maxZ, zoneRad));
}
else
{
_log.warning("ZoneData: Bad data for zone: " + zoneId + " in file: " + f.getName());
continue;
}
}
else
{
_log.warning("ZoneData: Unknown shape: " + zoneShape + " in file: " + f.getName());
continue;
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "ZoneData: Failed to load zone " + zoneId + " coordinates: " + e.getMessage(), e);
}
// Check for additional parameters
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("stat".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
String name = attrs.getNamedItem("name").getNodeValue();
String val = attrs.getNamedItem("val").getNodeValue();
temp.setParameter(name, val);
}
else if ("spawn".equalsIgnoreCase(cd.getNodeName()) && (temp instanceof L2SpawnZone))
{
attrs = cd.getAttributes();
int spawnX = Integer.parseInt(attrs.getNamedItem("X").getNodeValue());
int spawnY = Integer.parseInt(attrs.getNamedItem("Y").getNodeValue());
int spawnZ = Integer.parseInt(attrs.getNamedItem("Z").getNodeValue());
Node val = attrs.getNamedItem("isChaotic");
if ((val != null) && Boolean.parseBoolean(val.getNodeValue()))
{
((L2SpawnZone) temp).addChaoticSpawn(spawnX, spawnY, spawnZ);
}
else
{
((L2SpawnZone) temp).addSpawn(spawnX, spawnY, spawnZ);
}
}
}
if (checkId(zoneId))
{
_log.config("Caution: Zone (" + zoneId + ") from file: " + f.getName() + " overrides previos definition.");
}
if ((zoneName != null) && !zoneName.isEmpty())
{
temp.setName(zoneName);
}
addZone(zoneId, temp);
// Register the zone into any world region it
// intersects with...
// currently 11136 test for each zone :>
int ax, ay, bx, by;
for (int x = 0; x < worldRegions.length; x++)
{
for (int y = 0; y < worldRegions[x].length; y++)
{
ax = (x - L2World.OFFSET_X) << L2World.SHIFT_BY;
bx = ((x + 1) - L2World.OFFSET_X) << L2World.SHIFT_BY;
ay = (y - L2World.OFFSET_Y) << L2World.SHIFT_BY;
by = ((y + 1) - L2World.OFFSET_Y) << L2World.SHIFT_BY;
if (temp.getZone().intersectsRectangle(ax, bx, ay, by))
{
if (Config.DEBUG)
{
_log.info("Zone (" + zoneId + ") added to: " + x + " " + y);
}
worldRegions[x][y].addZone(temp);
}
}
}
}
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error while loading zones.", e);
return;
}
_log.info("Done: loaded " + _classZones.size() + " zone classes and " + getSize() + " zones.");
}
public int getSize()
{
int i = 0;
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
i += map.size();
}
return i;
}
public boolean checkId(int id)
{
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
if (map.containsKey(id))
{
return true;
}
}
return false;
}
/**
* Add new zone
* @param zone
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> void addZone(Integer id, T zone)
{
// _zones.put(id, zone);
Map<Integer, T> map = (Map<Integer, T>) _classZones.get(zone.getClass());
if (map == null)
{
map = new FastMap<>();
map.put(id, zone);
_classZones.put(zone.getClass(), map);
}
else
{
map.put(id, zone);
}
}
/**
* Returns all zones registered with the ZoneManager. To minimise iteration processing retrieve zones from L2WorldRegion for a specific location instead.
* @return zones
* @see #getAllZones(Class)
*/
@Deprecated
public Collection<L2ZoneType> getAllZones()
{
FastList<L2ZoneType> zones = new FastList<>();
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
zones.addAll(map.values());
}
return zones;
}
/**
* Return all zones by class type
* @param <T>
* @param zoneType Zone class
* @return Collection of zones
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> Collection<T> getAllZones(Class<T> zoneType)
{
return (Collection<T>) _classZones.get(zoneType).values();
}
/**
* Get zone by ID
* @param id
* @return
* @see #getZoneById(int, Class)
*/
public L2ZoneType getZoneById(int id)
{
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
if (map.containsKey(id))
{
return map.get(id);
}
}
return null;
}
/**
* Get zone by ID and zone class
* @param id
* @param zoneType
* @return zone
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> T getZoneById(int id, Class<T> zoneType)
{
return (T) _classZones.get(zoneType).get(id);
}
/**
* Returns all zones from where the object is located
* @param object
* @return zones
*/
public FastList<L2ZoneType> getZones(L2Object object)
{
return getZones(object.getX(), object.getY(), object.getZ());
}
/**
* Returns zone from where the object is located by type
* @param object
* @param type
* @return zone
*/
public <T extends L2ZoneType> T getZone(L2Object object, Class<T> type)
{
if (object == null)
{
return null;
}
return getZone(object.getX(), object.getY(), object.getZ(), type);
}
/**
* Returns all zones from given coordinates (plane)
* @param x
* @param y
* @return zones
*/
public FastList<L2ZoneType> getZones(int x, int y)
{
L2WorldRegion region = L2World.getInstance().getRegion(x, y);
FastList<L2ZoneType> temp = new FastList<>();
for (L2ZoneType zone : region.getZones())
{
if (zone.isInsideZone(x, y))
{
temp.add(zone);
}
}
return temp;
}
/**
* Returns all zones from given coordinates
* @param x
* @param y
* @param z
* @return zones
*/
public FastList<L2ZoneType> getZones(int x, int y, int z)
{
L2WorldRegion region = L2World.getInstance().getRegion(x, y);
FastList<L2ZoneType> temp = new FastList<>();
for (L2ZoneType zone : region.getZones())
{
if (zone.isInsideZone(x, y, z))
{
temp.add(zone);
}
}
return temp;
}
/**
* Returns zone from given coordinates
* @param x
* @param y
* @param z
* @param type
* @return zone
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> T getZone(int x, int y, int z, Class<T> type)
{
L2WorldRegion region = L2World.getInstance().getRegion(x, y);
for (L2ZoneType zone : region.getZones())
{
if (zone.isInsideZone(x, y, z) && type.isInstance(zone))
{
return (T) zone;
}
}
return null;
}
public final L2ArenaZone getArena(L2Character character)
{
if (character == null)
{
return null;
}
for (L2ZoneType temp : ZoneManager.getInstance().getZones(character.getX(), character.getY(), character.getZ()))
{
if ((temp instanceof L2ArenaZone) && temp.isCharacterInZone(character))
{
return ((L2ArenaZone) temp);
}
}
return null;
}
public final L2OlympiadStadiumZone getOlympiadStadium(L2Character character)
{
if (character == null)
{
return null;
}
for (L2ZoneType temp : ZoneManager.getInstance().getZones(character.getX(), character.getY(), character.getZ()))
{
if ((temp instanceof L2OlympiadStadiumZone) && temp.isCharacterInZone(character))
{
return ((L2OlympiadStadiumZone) temp);
}
}
return null;
}
/**
* For testing purposes only
* @param <T>
* @param obj
* @param type
* @return
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> T getClosestZone(L2Object obj, Class<T> type)
{
T zone = getZone(obj, type);
if (zone == null)
{
double closestdis = Double.MAX_VALUE;
for (T temp : (Collection<T>) _classZones.get(type).values())
{
double distance = temp.getDistanceToZone(obj);
if (distance < closestdis)
{
closestdis = distance;
zone = temp;
}
}
}
return zone;
}
/**
* General storage for debug items used for visualizing zones.
* @return list of items
*/
public List<L2ItemInstance> getDebugItems()
{
if (_debugItems == null)
{
_debugItems = new FastList<>();
}
return _debugItems;
}
/**
* Remove all debug items from l2world
*/
public void clearDebugItems()
{
if (_debugItems != null)
{
Iterator<L2ItemInstance> it = _debugItems.iterator();
while (it.hasNext())
{
L2ItemInstance item = it.next();
if (item != null)
{
item.decayMe();
}
it.remove();
}
}
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final ZoneManager _instance = new ZoneManager();
}
}
@@ -0,0 +1,619 @@
/*
* 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.l2jserver.gameserver.instancemanager.games;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jserver.Config;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.L2ItemInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.util.Rnd;
public class Lottery
{
public static final long SECOND = 1000;
public static final long MINUTE = 60000;
protected static final Logger _log = Logger.getLogger(Lottery.class.getName());
private static final String INSERT_LOTTERY = "INSERT INTO games(id, idnr, enddate, prize, newprize) VALUES (?, ?, ?, ?, ?)";
private static final String UPDATE_PRICE = "UPDATE games SET prize=?, newprize=? WHERE id = 1 AND idnr = ?";
private static final String UPDATE_LOTTERY = "UPDATE games SET finished=1, prize=?, newprize=?, number1=?, number2=?, prize1=?, prize2=?, prize3=? WHERE id=1 AND idnr=?";
private static final String SELECT_LAST_LOTTERY = "SELECT idnr, prize, newprize, enddate, finished FROM games WHERE id = 1 ORDER BY idnr DESC LIMIT 1";
private static final String SELECT_LOTTERY_ITEM = "SELECT enchant_level, custom_type2 FROM items WHERE item_id = 4442 AND custom_type1 = ?";
private static final String SELECT_LOTTERY_TICKET = "SELECT number1, number2, prize1, prize2, prize3 FROM games WHERE id = 1 and idnr = ?";
protected int _number;
protected long _prize;
protected boolean _isSellingTickets;
protected boolean _isStarted;
protected long _enddate;
private Lottery()
{
_number = 1;
_prize = Config.ALT_LOTTERY_PRIZE;
_isSellingTickets = false;
_isStarted = false;
_enddate = System.currentTimeMillis();
if (Config.ALLOW_LOTTERY)
{
(new startLottery()).run();
}
}
public static Lottery getInstance()
{
return SingletonHolder._instance;
}
public int getId()
{
return _number;
}
public long getPrize()
{
return _prize;
}
public long getEndDate()
{
return _enddate;
}
public void increasePrize(long count)
{
_prize += count;
Connection con = null;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement;
statement = con.prepareStatement(UPDATE_PRICE);
statement.setLong(1, getPrize());
statement.setLong(2, getPrize());
statement.setInt(3, getId());
statement.execute();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not increase current lottery prize: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
public boolean isSellableTickets()
{
return _isSellingTickets;
}
public boolean isStarted()
{
return _isStarted;
}
private class startLottery implements Runnable
{
protected startLottery()
{
// Do nothing
}
@Override
public void run()
{
Connection con = null;
PreparedStatement statement;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement(SELECT_LAST_LOTTERY);
ResultSet rset = statement.executeQuery();
if (rset.next())
{
_number = rset.getInt("idnr");
if (rset.getInt("finished") == 1)
{
_number++;
_prize = rset.getLong("newprize");
}
else
{
_prize = rset.getLong("prize");
_enddate = rset.getLong("enddate");
if (_enddate <= (System.currentTimeMillis() + (2 * MINUTE)))
{
(new finishLottery()).run();
rset.close();
statement.close();
return;
}
if (_enddate > System.currentTimeMillis())
{
_isStarted = true;
ThreadPoolManager.getInstance().scheduleGeneral(new finishLottery(), _enddate - System.currentTimeMillis());
if (_enddate > (System.currentTimeMillis() + (12 * MINUTE)))
{
_isSellingTickets = true;
ThreadPoolManager.getInstance().scheduleGeneral(new stopSellingTickets(), _enddate - System.currentTimeMillis() - (10 * MINUTE));
}
rset.close();
statement.close();
return;
}
}
}
rset.close();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not restore lottery data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
if (Config.DEBUG)
{
_log.info("Lottery: Starting ticket sell for lottery #" + getId() + ".");
}
_isSellingTickets = true;
_isStarted = true;
Announcements.getInstance().announceToAll("Lottery tickets are now available for Lucky Lottery #" + getId() + ".");
Calendar finishtime = Calendar.getInstance();
finishtime.setTimeInMillis(_enddate);
finishtime.set(Calendar.MINUTE, 0);
finishtime.set(Calendar.SECOND, 0);
if (finishtime.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
{
finishtime.set(Calendar.HOUR_OF_DAY, 19);
_enddate = finishtime.getTimeInMillis();
_enddate += 604800000;
}
else
{
finishtime.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
finishtime.set(Calendar.HOUR_OF_DAY, 19);
_enddate = finishtime.getTimeInMillis();
}
ThreadPoolManager.getInstance().scheduleGeneral(new stopSellingTickets(), _enddate - System.currentTimeMillis() - (10 * MINUTE));
ThreadPoolManager.getInstance().scheduleGeneral(new finishLottery(), _enddate - System.currentTimeMillis());
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement(INSERT_LOTTERY);
statement.setInt(1, 1);
statement.setInt(2, getId());
statement.setLong(3, getEndDate());
statement.setLong(4, getPrize());
statement.setLong(5, getPrize());
statement.execute();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not store new lottery data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
}
}
private class stopSellingTickets implements Runnable
{
protected stopSellingTickets()
{
// Do nothing
}
@Override
public void run()
{
if (Config.DEBUG)
{
_log.info("Lottery: Stopping ticket sell for lottery #" + getId() + ".");
}
_isSellingTickets = false;
Announcements.getInstance().announceToAll(SystemMessage.getSystemMessage(SystemMessageId.LOTTERY_TICKET_SALES_TEMP_SUSPENDED));
}
}
private class finishLottery implements Runnable
{
protected finishLottery()
{
// Do nothing
}
@Override
public void run()
{
if (Config.DEBUG)
{
_log.info("Lottery: Ending lottery #" + getId() + ".");
}
int[] luckynums = new int[5];
int luckynum = 0;
for (int i = 0; i < 5; i++)
{
boolean found = true;
while (found)
{
luckynum = Rnd.get(20) + 1;
found = false;
for (int j = 0; j < i; j++)
{
if (luckynums[j] == luckynum)
{
found = true;
}
}
}
luckynums[i] = luckynum;
}
if (Config.DEBUG)
{
_log.info("Lottery: The lucky numbers are " + luckynums[0] + ", " + luckynums[1] + ", " + luckynums[2] + ", " + luckynums[3] + ", " + luckynums[4] + ".");
}
int enchant = 0;
int type2 = 0;
for (int i = 0; i < 5; i++)
{
if (luckynums[i] < 17)
{
enchant += Math.pow(2, luckynums[i] - 1);
}
else
{
type2 += Math.pow(2, luckynums[i] - 17);
}
}
if (Config.DEBUG)
{
_log.info("Lottery: Encoded lucky numbers are " + enchant + ", " + type2);
}
int count1 = 0;
int count2 = 0;
int count3 = 0;
int count4 = 0;
Connection con = null;
PreparedStatement statement;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement(SELECT_LOTTERY_ITEM);
statement.setInt(1, getId());
ResultSet rset = statement.executeQuery();
while (rset.next())
{
int curenchant = rset.getInt("enchant_level") & enchant;
int curtype2 = rset.getInt("custom_type2") & type2;
if ((curenchant == 0) && (curtype2 == 0))
{
continue;
}
int count = 0;
for (int i = 1; i <= 16; i++)
{
int val = curenchant / 2;
if (val != ((double) curenchant / 2))
{
count++;
}
int val2 = curtype2 / 2;
if (val2 != ((double) curtype2 / 2))
{
count++;
}
curenchant = val;
curtype2 = val2;
}
if (count == 5)
{
count1++;
}
else if (count == 4)
{
count2++;
}
else if (count == 3)
{
count3++;
}
else if (count > 0)
{
count4++;
}
}
rset.close();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could restore lottery data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
long prize4 = count4 * Config.ALT_LOTTERY_2_AND_1_NUMBER_PRIZE;
long prize1 = 0;
long prize2 = 0;
long prize3 = 0;
if (count1 > 0)
{
prize1 = (long) (((getPrize() - prize4) * Config.ALT_LOTTERY_5_NUMBER_RATE) / count1);
}
if (count2 > 0)
{
prize2 = (long) (((getPrize() - prize4) * Config.ALT_LOTTERY_4_NUMBER_RATE) / count2);
}
if (count3 > 0)
{
prize3 = (long) (((getPrize() - prize4) * Config.ALT_LOTTERY_3_NUMBER_RATE) / count3);
}
if (Config.DEBUG)
{
_log.info("Lottery: " + count1 + " players with all FIVE numbers each win " + prize1 + ".");
_log.info("Lottery: " + count2 + " players with FOUR numbers each win " + prize2 + ".");
_log.info("Lottery: " + count3 + " players with THREE numbers each win " + prize3 + ".");
_log.info("Lottery: " + count4 + " players with ONE or TWO numbers each win " + prize4 + ".");
}
long newprize = getPrize() - (prize1 + prize2 + prize3 + prize4);
if (Config.DEBUG)
{
_log.info("Lottery: Jackpot for next lottery is " + newprize + ".");
}
SystemMessage sm;
if (count1 > 0)
{
// There are winners.
sm = SystemMessage.getSystemMessage(SystemMessageId.AMOUNT_FOR_WINNER_S1_IS_S2_ADENA_WE_HAVE_S3_PRIZE_WINNER);
sm.addNumber(getId());
sm.addItemNumber(getPrize());
sm.addItemNumber(count1);
Announcements.getInstance().announceToAll(sm);
}
else
{
// There are no winners.
sm = SystemMessage.getSystemMessage(SystemMessageId.AMOUNT_FOR_LOTTERY_S1_IS_S2_ADENA_NO_WINNER);
sm.addNumber(getId());
sm.addItemNumber(getPrize());
Announcements.getInstance().announceToAll(sm);
}
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement(UPDATE_LOTTERY);
statement.setLong(1, getPrize());
statement.setLong(2, newprize);
statement.setInt(3, enchant);
statement.setInt(4, type2);
statement.setLong(5, prize1);
statement.setLong(6, prize2);
statement.setLong(7, prize3);
statement.setInt(8, getId());
statement.execute();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not store finished lottery data: " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
ThreadPoolManager.getInstance().scheduleGeneral(new startLottery(), MINUTE);
_number++;
_isStarted = false;
}
}
public int[] decodeNumbers(int enchant, int type2)
{
int res[] = new int[5];
int id = 0;
int nr = 1;
while (enchant > 0)
{
int val = enchant / 2;
if (val != ((double) enchant / 2))
{
res[id++] = nr;
}
enchant /= 2;
nr++;
}
nr = 17;
while (type2 > 0)
{
int val = type2 / 2;
if (val != ((double) type2 / 2))
{
res[id++] = nr;
}
type2 /= 2;
nr++;
}
return res;
}
public long[] checkTicket(L2ItemInstance item)
{
return checkTicket(item.getCustomType1(), item.getEnchantLevel(), item.getCustomType2());
}
public long[] checkTicket(int id, int enchant, int type2)
{
long res[] =
{
0,
0
};
Connection con = null;
PreparedStatement statement;
try
{
con = L2DatabaseFactory.getInstance().getConnection();
statement = con.prepareStatement(SELECT_LOTTERY_TICKET);
statement.setInt(1, id);
ResultSet rset = statement.executeQuery();
if (rset.next())
{
int curenchant = rset.getInt("number1") & enchant;
int curtype2 = rset.getInt("number2") & type2;
if ((curenchant == 0) && (curtype2 == 0))
{
rset.close();
statement.close();
return res;
}
int count = 0;
for (int i = 1; i <= 16; i++)
{
int val = curenchant / 2;
if (val != ((double) curenchant / 2))
{
count++;
}
int val2 = curtype2 / 2;
if (val2 != ((double) curtype2 / 2))
{
count++;
}
curenchant = val;
curtype2 = val2;
}
switch (count)
{
case 0:
break;
case 5:
res[0] = 1;
res[1] = rset.getLong("prize1");
break;
case 4:
res[0] = 2;
res[1] = rset.getLong("prize2");
break;
case 3:
res[0] = 3;
res[1] = rset.getLong("prize3");
break;
default:
res[0] = 4;
res[1] = 200;
}
if (Config.DEBUG)
{
_log.warning("count: " + count + ", id: " + id + ", enchant: " + enchant + ", type2: " + type2);
}
}
rset.close();
statement.close();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not check lottery ticket #" + id + ": " + e.getMessage(), e);
}
finally
{
L2DatabaseFactory.close(con);
}
return res;
}
@SuppressWarnings("synthetic-access")
private static class SingletonHolder
{
protected static final Lottery _instance = new Lottery();
}
}