This commit is contained in:
mobius
2015-01-01 20:02:50 +00:00
parent eeae660458
commit a6a3718849
17894 changed files with 2818932 additions and 0 deletions

View File

@ -0,0 +1,328 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.sql.Statement;
import java.util.HashMap;
import java.util.Map;
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.AirShipTeleportList;
import com.l2jserver.gameserver.model.StatsSet;
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.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.network.serverpackets.ExAirShipTeleportList;
public class AirShipManager
{
private static final Logger _log = Logger.getLogger(AirShipManager.class.getName());
private static final String LOAD_DB = "SELECT * FROM airships";
private static final String ADD_DB = "INSERT INTO airships (owner_id,fuel) VALUES (?,?)";
private static final String UPDATE_DB = "UPDATE airships SET fuel=? WHERE owner_id=?";
private L2CharTemplate _airShipTemplate = null;
private final Map<Integer, StatsSet> _airShipsInfo = new HashMap<>();
private final Map<Integer, L2AirShipInstance> _airShips = new HashMap<>();
private final Map<Integer, AirShipTeleportList> _teleports = new HashMap<>();
protected AirShipManager()
{
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.getInt("fuel"));
airShip.getStat().setMoveSpeed(280);
airShip.getStat().setRotationSpeed(2000);
}
airShip.setHeading(heading);
airShip.setXYZInvisible(x, y, z);
airShip.spawnMe();
return airShip;
}
public void removeAirShip(L2AirShipInstance ship)
{
if (ship.getOwnerId() != 0)
{
storeInDb(ship.getOwnerId());
final StatsSet info = _airShipsInfo.get(ship.getOwnerId());
if (info != null)
{
info.set("fuel", ship.getFuel());
}
}
}
public boolean hasAirShipLicense(int ownerId)
{
return _airShipsInfo.containsKey(ownerId);
}
public void registerLicense(int ownerId)
{
if (!_airShipsInfo.containsKey(ownerId))
{
final StatsSet info = new StatsSet();
info.set("fuel", 600);
_airShipsInfo.put(ownerId, info);
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(ADD_DB))
{
ps.setInt(1, ownerId);
ps.setInt(2, info.getInt("fuel"));
ps.executeUpdate();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not add new airship license: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing: " + e.getMessage(), e);
}
}
}
public boolean hasAirShip(int ownerId)
{
final L2AirShipInstance ship = _airShips.get(ownerId);
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.containsKey(dockId))
{
return;
}
final AirShipTeleportList all = _teleports.get(dockId);
player.sendPacket(new ExAirShipTeleportList(all.getLocation(), all.getRoute(), all.getFuel()));
}
public VehiclePathPoint[] getTeleportDestination(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
if (all == null)
{
return null;
}
if ((index < -1) || (index >= all.getRoute().length))
{
return null;
}
return all.getRoute()[index + 1];
}
public int getFuelConsumption(int dockId, int index)
{
final AirShipTeleportList all = _teleports.get(dockId);
if (all == null)
{
return 0;
}
if ((index < -1) || (index >= all.getFuel().length))
{
return 0;
}
return all.getFuel()[index + 1];
}
private void load()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(LOAD_DB))
{
StatsSet info;
while (rs.next())
{
info = new StatsSet();
info.set("fuel", rs.getInt("fuel"));
_airShipsInfo.put(rs.getInt("owner_id"), info);
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not load airships table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while initializing: " + e.getMessage(), e);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _airShipsInfo.size() + " private airships");
}
private void storeInDb(int ownerId)
{
StatsSet info = _airShipsInfo.get(ownerId);
if (info == null)
{
return;
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(UPDATE_DB))
{
ps.setInt(1, info.getInt("fuel"));
ps.setInt(2, ownerId);
ps.executeUpdate();
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not update airships table: " + e.getMessage(), e);
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error while save: " + e.getMessage(), e);
}
}
public static final AirShipManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AirShipManager _instance = new AirShipManager();
}
}

View File

@ -0,0 +1,280 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
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 final class AntiFeedManager
{
public static final int GAME_ID = 0;
public static final int OLYMPIAD_ID = 1;
public static final int TVT_ID = 2;
public static final int L2EVENT_ID = 3;
private final Map<Integer, Long> _lastDeathTimes = new ConcurrentHashMap<>();
private final Map<Integer, Map<Integer, AtomicInteger>> _eventIPs = new ConcurrentHashMap<>();
protected AntiFeedManager()
{
}
/**
* Set time of the last player's death to current
* @param objectId Player's objectId
*/
public final void setLastDeathTime(int objectId)
{
_lastDeathTimes.put(objectId, System.currentTimeMillis());
}
/**
* Check if current kill should be counted as non-feeded.
* @param attacker Attacker character
* @param target Target character
* @return True if kill is non-feeded.
*/
public final boolean check(L2Character attacker, L2Character target)
{
if (!Config.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()))
{
if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.L2JMOD_ANTIFEED_INTERVAL)
{
return false;
}
}
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)
{
_eventIPs.putIfAbsent(eventId, new ConcurrentHashMap<Integer, AtomicInteger>());
}
/**
* @param eventId
* @param player
* @param max
* @return If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true.<br>
* False if number of all simultaneous connections from player's IP address higher than max.
*/
public final boolean tryAddPlayer(int eventId, L2PcInstance player, int max)
{
return tryAddClient(eventId, player.getClient(), max);
}
/**
* @param eventId
* @param client
* @param max
* @return If number of all simultaneous connections from player's IP address lower than max then increment connection count and return true.<br>
* False if number of all simultaneous connections from player's IP address higher than max.
*/
public final boolean tryAddClient(int eventId, L2GameClient client, int max)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
int limit = max;
if (Config.L2JMOD_DUALBOX_CHECK_WHITELIST.containsKey(addrHash))
{
limit += Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash);
}
final AtomicInteger connectionCount = event.computeIfAbsent(addrHash, k -> new AtomicInteger());
return connectionCount.getAndIncrement() < limit;
}
/**
* Decreasing number of active connection from player's IP address
* @param eventId
* @param player
* @return true if success and false if any problem detected.
*/
public final boolean removePlayer(int eventId, L2PcInstance player)
{
return removeClient(eventId, player.getClient());
}
/**
* Decreasing number of active connection from player's IP address
* @param eventId
* @param client
* @return true if success and false if any problem detected.
*/
public final boolean removeClient(int eventId, L2GameClient client)
{
if (client == null)
{
return false; // unable to determine IP address
}
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event == null)
{
return false; // no such event registered
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
return event.computeIfPresent(addrHash, (k, v) ->
{
if ((v == null) || (v.decrementAndGet() == 0))
{
return null;
}
return v;
}) != null;
}
/**
* Remove player connection IP address from all registered events lists.
* @param client
*/
public final void onDisconnect(L2GameClient client)
{
if (client == null)
{
return;
}
_eventIPs.forEach((k, v) ->
{
removeClient(k, client);
});
}
/**
* Clear all entries for this eventId.
* @param eventId
*/
public final void clear(int eventId)
{
final Map<Integer, AtomicInteger> event = _eventIPs.get(eventId);
if (event != null)
{
event.clear();
}
}
/**
* @param player
* @param max
* @return maximum number of allowed connections (whitelist + max)
*/
public final int getLimit(L2PcInstance player, int max)
{
return getLimit(player.getClient(), max);
}
/**
* @param client
* @param max
* @return maximum number of allowed connections (whitelist + max)
*/
public final int getLimit(L2GameClient client, int max)
{
if (client == null)
{
return max;
}
final Integer addrHash = Integer.valueOf(client.getConnectionAddress().hashCode());
int limit = max;
if (Config.L2JMOD_DUALBOX_CHECK_WHITELIST.containsKey(addrHash))
{
limit += Config.L2JMOD_DUALBOX_CHECK_WHITELIST.get(addrHash);
}
return limit;
}
public static final AntiFeedManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AntiFeedManager _instance = new AntiFeedManager();
}
}

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.model.entity.Auction;
/**
* Zoey76: TODO: Rewrite it and unharcode it.
*/
public final class AuctionManager
{
protected static final Logger _log = Logger.getLogger(AuctionManager.class.getName());
private final List<Auction> _auctions = new ArrayList<>();
private static final String[] ITEM_INIT_DATA =
{
"(22, 0, 'NPC', 'NPC Clan', 'ClanHall', 22, 0, 'Moonstone Hall', 1, 20000000, 0, 1073037600000)",
"(23, 0, 'NPC', 'NPC Clan', 'ClanHall', 23, 0, 'Onyx Hall', 1, 20000000, 0, 1073037600000)",
"(24, 0, 'NPC', 'NPC Clan', 'ClanHall', 24, 0, 'Topaz Hall', 1, 20000000, 0, 1073037600000)",
"(25, 0, 'NPC', 'NPC Clan', 'ClanHall', 25, 0, 'Ruby Hall', 1, 20000000, 0, 1073037600000)",
"(26, 0, 'NPC', 'NPC Clan', 'ClanHall', 26, 0, 'Crystal Hall', 1, 20000000, 0, 1073037600000)",
"(27, 0, 'NPC', 'NPC Clan', 'ClanHall', 27, 0, 'Onyx Hall', 1, 20000000, 0, 1073037600000)",
"(28, 0, 'NPC', 'NPC Clan', 'ClanHall', 28, 0, 'Sapphire Hall', 1, 20000000, 0, 1073037600000)",
"(29, 0, 'NPC', 'NPC Clan', 'ClanHall', 29, 0, 'Moonstone Hall', 1, 20000000, 0, 1073037600000)",
"(30, 0, 'NPC', 'NPC Clan', 'ClanHall', 30, 0, 'Emerald Hall', 1, 20000000, 0, 1073037600000)",
"(31, 0, 'NPC', 'NPC Clan', 'ClanHall', 31, 0, 'The Atramental Barracks', 1, 8000000, 0, 1073037600000)",
"(32, 0, 'NPC', 'NPC Clan', 'ClanHall', 32, 0, 'The Scarlet Barracks', 1, 8000000, 0, 1073037600000)",
"(33, 0, 'NPC', 'NPC Clan', 'ClanHall', 33, 0, 'The Viridian Barracks', 1, 8000000, 0, 1073037600000)",
"(36, 0, 'NPC', 'NPC Clan', 'ClanHall', 36, 0, 'The Golden Chamber', 1, 50000000, 0, 1106827200000)",
"(37, 0, 'NPC', 'NPC Clan', 'ClanHall', 37, 0, 'The Silver Chamber', 1, 50000000, 0, 1106827200000)",
"(38, 0, 'NPC', 'NPC Clan', 'ClanHall', 38, 0, 'The Mithril Chamber', 1, 50000000, 0, 1106827200000)",
"(39, 0, 'NPC', 'NPC Clan', 'ClanHall', 39, 0, 'Silver Manor', 1, 50000000, 0, 1106827200000)",
"(40, 0, 'NPC', 'NPC Clan', 'ClanHall', 40, 0, 'Gold Manor', 1, 50000000, 0, 1106827200000)",
"(41, 0, 'NPC', 'NPC Clan', 'ClanHall', 41, 0, 'The Bronze Chamber', 1, 50000000, 0, 1106827200000)",
"(42, 0, 'NPC', 'NPC Clan', 'ClanHall', 42, 0, 'The Golden Chamber', 1, 50000000, 0, 1106827200000)",
"(43, 0, 'NPC', 'NPC Clan', 'ClanHall', 43, 0, 'The Silver Chamber', 1, 50000000, 0, 1106827200000)",
"(44, 0, 'NPC', 'NPC Clan', 'ClanHall', 44, 0, 'The Mithril Chamber', 1, 50000000, 0, 1106827200000)",
"(45, 0, 'NPC', 'NPC Clan', 'ClanHall', 45, 0, 'The Bronze Chamber', 1, 50000000, 0, 1106827200000)",
"(46, 0, 'NPC', 'NPC Clan', 'ClanHall', 46, 0, 'Silver Manor', 1, 50000000, 0, 1106827200000)",
"(47, 0, 'NPC', 'NPC Clan', 'ClanHall', 47, 0, 'Moonstone Hall', 1, 50000000, 0, 1106827200000)",
"(48, 0, 'NPC', 'NPC Clan', 'ClanHall', 48, 0, 'Onyx Hall', 1, 50000000, 0, 1106827200000)",
"(49, 0, 'NPC', 'NPC Clan', 'ClanHall', 49, 0, 'Emerald Hall', 1, 50000000, 0, 1106827200000)",
"(50, 0, 'NPC', 'NPC Clan', 'ClanHall', 50, 0, 'Sapphire Hall', 1, 50000000, 0, 1106827200000)",
"(51, 0, 'NPC', 'NPC Clan', 'ClanHall', 51, 0, 'Mont Chamber', 1, 50000000, 0, 1106827200000)",
"(52, 0, 'NPC', 'NPC Clan', 'ClanHall', 52, 0, 'Astaire Chamber', 1, 50000000, 0, 1106827200000)",
"(53, 0, 'NPC', 'NPC Clan', 'ClanHall', 53, 0, 'Aria Chamber', 1, 50000000, 0, 1106827200000)",
"(54, 0, 'NPC', 'NPC Clan', 'ClanHall', 54, 0, 'Yiana Chamber', 1, 50000000, 0, 1106827200000)",
"(55, 0, 'NPC', 'NPC Clan', 'ClanHall', 55, 0, 'Roien Chamber', 1, 50000000, 0, 1106827200000)",
"(56, 0, 'NPC', 'NPC Clan', 'ClanHall', 56, 0, 'Luna Chamber', 1, 50000000, 0, 1106827200000)",
"(57, 0, 'NPC', 'NPC Clan', 'ClanHall', 57, 0, 'Traban Chamber', 1, 50000000, 0, 1106827200000)",
"(58, 0, 'NPC', 'NPC Clan', 'ClanHall', 58, 0, 'Eisen Hall', 1, 20000000, 0, 1106827200000)",
"(59, 0, 'NPC', 'NPC Clan', 'ClanHall', 59, 0, 'Heavy Metal Hall', 1, 20000000, 0, 1106827200000)",
"(60, 0, 'NPC', 'NPC Clan', 'ClanHall', 60, 0, 'Molten Ore Hall', 1, 20000000, 0, 1106827200000)",
"(61, 0, 'NPC', 'NPC Clan', 'ClanHall', 61, 0, 'Titan Hall', 1, 20000000, 0, 1106827200000)"
};
// @formatter:off
private static final int[] ItemInitDataId =
{
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
};
// @formatter:on
protected AuctionManager()
{
load();
}
public void reload()
{
_auctions.clear();
load();
}
private final void load()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM auction ORDER BY id"))
{
while (rs.next())
{
_auctions.add(new Auction(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + _auctions.size() + " auction(s)");
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Exception: AuctionManager.load(): " + e.getMessage(), e);
}
}
public final Auction getAuction(int auctionId)
{
int index = getAuctionIndex(auctionId);
if (index >= 0)
{
return _auctions.get(index);
}
return null;
}
public final int getAuctionIndex(int auctionId)
{
Auction auction;
for (int i = 0; i < _auctions.size(); i++)
{
auction = _auctions.get(i);
if ((auction != null) && (auction.getId() == auctionId))
{
return i;
}
}
return -1;
}
public final List<Auction> getAuctions()
{
return _auctions;
}
/**
* Init Clan NPC aution
* @param id
*/
public void initNPC(int id)
{
int i;
for (i = 0; i < ItemInitDataId.length; i++)
{
if (ItemInitDataId[i] == id)
{
break;
}
}
if ((i >= ItemInitDataId.length) || (ItemInitDataId[i] != id))
{
_log.warning(getClass().getSimpleName() + ": Clan Hall auction not found for Id :" + id);
return;
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement())
{
s.executeUpdate("INSERT INTO `auction` VALUES " + ITEM_INIT_DATA[i]);
_auctions.add(new Auction(id));
_log.info(getClass().getSimpleName() + ": Created auction for ClanHall: " + id);
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Exception: Auction.initNPC(): " + e.getMessage(), e);
}
}
public static final AuctionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AuctionManager _instance = new AuctionManager();
}
}

View File

@ -0,0 +1,212 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.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.StatsSet;
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.model.actor.templates.L2CharTemplate;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
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;
}
protected BoatManager()
{
for (int i = 0; i < _docksBusy.length; i++)
{
_docksBusy[i] = false;
}
}
public L2BoatInstance getNewBoat(int boatId, int x, int y, int z, int heading)
{
if (!Config.ALLOW_BOAT)
{
return null;
}
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
* @param point1
* @param point2
* @param packet
*/
public void broadcastPacket(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket packet)
{
broadcastPacketsToPlayers(point1, point2, packet);
}
/**
* Broadcast several packets in both path points
* @param point1
* @param point2
* @param packets
*/
public void broadcastPackets(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket... packets)
{
broadcastPacketsToPlayers(point1, point2, packets);
}
private void broadcastPacketsToPlayers(VehiclePathPoint point1, VehiclePathPoint point2, L2GameServerPacket... packets)
{
for (L2PcInstance player : L2World.getInstance().getPlayers())
{
double dx = (double) player.getX() - point1.getX();
double dy = (double) player.getY() - point1.getY();
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (L2GameServerPacket p : packets)
{
player.sendPacket(p);
}
}
else
{
dx = (double) player.getX() - point2.getX();
dy = (double) player.getY() - point2.getY();
if (Math.sqrt((dx * dx) + (dy * dy)) < Config.BOAT_BROADCAST_RADIUS)
{
for (L2GameServerPacket p : packets)
{
player.sendPacket(p);
}
}
}
}
}
private static class SingletonHolder
{
protected static final BoatManager _instance = new BoatManager();
}
}

View File

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

View File

@ -0,0 +1,346 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.Statement;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
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.L2ClanMember;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
public final class CastleManager implements InstanceListManager
{
private static final Logger _log = Logger.getLogger(CastleManager.class.getName());
private List<Castle> _castles;
private final Map<Integer, Long> _castleSiegeDate = new ConcurrentHashMap<>();
private static final int _castleCirclets[] =
{
0,
6838,
6835,
6839,
6837,
6840,
6834,
6836,
8182,
8183
};
public final int findNearestCastleIndex(L2Object obj)
{
return findNearestCastleIndex(obj, Long.MAX_VALUE);
}
public final int findNearestCastleIndex(L2Object obj, long maxDistance)
{
int index = getCastleIndex(obj);
if (index < 0)
{
double distance;
Castle castle;
for (int i = 0; i < 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;
}
public final Castle getCastleById(int castleId)
{
for (Castle temp : getCastles())
{
if (temp.getResidenceId() == castleId)
{
return temp;
}
}
return null;
}
public final Castle getCastleByOwner(L2Clan clan)
{
for (Castle temp : getCastles())
{
if (temp.getOwnerId() == clan.getId())
{
return temp;
}
}
return null;
}
public final Castle getCastle(String name)
{
for (Castle temp : getCastles())
{
if (temp.getName().equalsIgnoreCase(name.trim()))
{
return temp;
}
}
return null;
}
public final Castle getCastle(int x, int y, int z)
{
for (Castle temp : getCastles())
{
if (temp.checkIfInZone(x, y, z))
{
return temp;
}
}
return null;
}
public final Castle getCastle(L2Object activeObject)
{
return getCastle(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getCastleIndex(int castleId)
{
Castle castle;
for (int i = 0; i < getCastles().size(); i++)
{
castle = getCastles().get(i);
if ((castle != null) && (castle.getResidenceId() == castleId))
{
return i;
}
}
return -1;
}
public final int getCastleIndex(L2Object activeObject)
{
return getCastleIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getCastleIndex(int x, int y, int z)
{
Castle castle;
for (int i = 0; i < 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 boolean hasOwnedCastle()
{
boolean hasOwnedCastle = false;
for (Castle castle : getCastles())
{
if (castle.getOwnerId() > 0)
{
hasOwnedCastle = true;
break;
}
}
return hasOwnedCastle;
}
public final void validateTaxes(int sealStrifeOwner)
{
final int maxTax = 15;
for (Castle castle : _castles)
{
if (castle.getTaxPercent() > maxTax)
{
castle.setTaxPercent(maxTax);
}
}
}
public int getCirclet()
{
return getCircletByCastleId(1);
}
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
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM items WHERE owner_id = ? and item_id = ?"))
{
ps.setInt(1, member.getObjectId());
ps.setInt(2, circletId);
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, "Failed to remove castle circlets offline for player " + member.getName() + ": " + e.getMessage(), e);
}
}
}
@Override
public void loadInstances()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM castle ORDER BY id"))
{
while (rs.next())
{
getCastles().add(new Castle(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + getCastles().size() + " castles");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadCastleData(): " + e.getMessage(), e);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (final Castle castle : _castles)
{
castle.activateInstance();
}
}
public void registerSiegeDate(int castleId, long siegeDate)
{
_castleSiegeDate.put(castleId, siegeDate);
}
public int getSiegeDates(long siegeDate)
{
int count = 0;
for (long date : _castleSiegeDate.values())
{
if (Math.abs(date - siegeDate) < 1000)
{
count++;
}
}
return count;
}
public static final CastleManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CastleManager _instance = new CastleManager();
}
}

View File

@ -0,0 +1,821 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
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.ThreadPoolManager;
import com.l2jserver.gameserver.engines.DocumentParser;
import com.l2jserver.gameserver.enums.ManorMode;
import com.l2jserver.gameserver.model.CropProcure;
import com.l2jserver.gameserver.model.L2Clan;
import com.l2jserver.gameserver.model.L2ClanMember;
import com.l2jserver.gameserver.model.L2Seed;
import com.l2jserver.gameserver.model.SeedProduction;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.entity.Castle;
import com.l2jserver.gameserver.model.interfaces.IStorable;
import com.l2jserver.gameserver.model.itemcontainer.ItemContainer;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.util.Rnd;
/**
* Castle manor system.
* @author malyelfik
*/
public final class CastleManorManager implements DocumentParser, IStorable
{
// SQL queries
private static final String INSERT_PRODUCT = "INSERT INTO castle_manor_production VALUES (?, ?, ?, ?, ?, ?)";
private static final String INSERT_CROP = "INSERT INTO castle_manor_procure VALUES (?, ?, ?, ?, ?, ?, ?)";
// Current manor status
private ManorMode _mode = ManorMode.APPROVED;
// Temporary date
private Calendar _nextModeChange = null;
// Seeds holder
private static final Map<Integer, L2Seed> _seeds = new HashMap<>();
// Manor period settings
private final Map<Integer, List<CropProcure>> _procure = new HashMap<>();
private final Map<Integer, List<CropProcure>> _procureNext = new HashMap<>();
private final Map<Integer, List<SeedProduction>> _production = new HashMap<>();
private final Map<Integer, List<SeedProduction>> _productionNext = new HashMap<>();
public CastleManorManager()
{
if (Config.ALLOW_MANOR)
{
load(); // Load seed data (XML)
loadDb(); // Load castle manor data (DB)
// Set mode and start timer
final Calendar currentTime = Calendar.getInstance();
final int hour = currentTime.get(Calendar.HOUR_OF_DAY);
final int min = currentTime.get(Calendar.MINUTE);
final int maintenanceMin = Config.ALT_MANOR_REFRESH_MIN + Config.ALT_MANOR_MAINTENANCE_MIN;
if (((hour >= Config.ALT_MANOR_REFRESH_TIME) && (min >= maintenanceMin)) || (hour < Config.ALT_MANOR_APPROVE_TIME) || ((hour == Config.ALT_MANOR_APPROVE_TIME) && (min <= Config.ALT_MANOR_APPROVE_MIN)))
{
_mode = ManorMode.MODIFIABLE;
}
else if ((hour == Config.ALT_MANOR_REFRESH_TIME) && ((min >= Config.ALT_MANOR_REFRESH_MIN) && (min < maintenanceMin)))
{
_mode = ManorMode.MAINTENANCE;
}
// Schedule mode change
scheduleModeChange();
// Schedule autosave
if (!Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(this::storeMe, Config.ALT_MANOR_SAVE_PERIOD_RATE, Config.ALT_MANOR_SAVE_PERIOD_RATE, TimeUnit.HOURS);
}
// Send debug message
if (Config.DEBUG)
{
LOGGER.info(getClass().getSimpleName() + ": Current mode " + _mode.toString());
}
}
else
{
_mode = ManorMode.DISABLED;
LOGGER.info(getClass().getSimpleName() + ": Manor system is deactivated.");
}
}
@Override
public final void load()
{
parseDatapackFile("data/seeds.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _seeds.size() + " seeds.");
}
@Override
public final void parseDocument(Document doc)
{
StatsSet set;
NamedNodeMap attrs;
Node att;
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 ("castle".equalsIgnoreCase(d.getNodeName()))
{
final int castleId = parseInteger(d.getAttributes(), "id");
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("crop".equalsIgnoreCase(c.getNodeName()))
{
set = new StatsSet();
set.set("castleId", castleId);
attrs = c.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
_seeds.put(set.getInt("seedId"), new L2Seed(set));
}
}
}
}
}
}
}
private final void loadDb()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement stProduction = con.prepareStatement("SELECT * FROM castle_manor_production WHERE castle_id=?");
PreparedStatement stProcure = con.prepareStatement("SELECT * FROM castle_manor_procure WHERE castle_id=?"))
{
for (Castle castle : CastleManager.getInstance().getCastles())
{
final int castleId = castle.getResidenceId();
// Clear params
stProduction.clearParameters();
stProcure.clearParameters();
// Seed production
final List<SeedProduction> pCurrent = new ArrayList<>();
final List<SeedProduction> pNext = new ArrayList<>();
stProduction.setInt(1, castleId);
try (ResultSet rs = stProduction.executeQuery())
{
while (rs.next())
{
final int seedId = rs.getInt("seed_id");
if (_seeds.containsKey(seedId)) // Don't load unknown seeds
{
final SeedProduction sp = new SeedProduction(seedId, rs.getLong("amount"), rs.getLong("price"), rs.getInt("start_amount"));
if (rs.getBoolean("next_period"))
{
pNext.add(sp);
}
else
{
pCurrent.add(sp);
}
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Unknown seed id: " + seedId + "!");
}
}
}
_production.put(castleId, pCurrent);
_productionNext.put(castleId, pNext);
// Seed procure
final List<CropProcure> current = new ArrayList<>();
final List<CropProcure> next = new ArrayList<>();
stProcure.setInt(1, castleId);
try (ResultSet rs = stProcure.executeQuery())
{
final Set<Integer> cropIds = getCropIds();
while (rs.next())
{
final int cropId = rs.getInt("crop_id");
if (cropIds.contains(cropId)) // Don't load unknown crops
{
final CropProcure cp = new CropProcure(cropId, rs.getLong("amount"), rs.getInt("reward_type"), rs.getLong("start_amount"), rs.getLong("price"));
if (rs.getBoolean("next_period"))
{
next.add(cp);
}
else
{
current.add(cp);
}
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Unknown crop id: " + cropId + "!");
}
}
}
_procure.put(castleId, current);
_procureNext.put(castleId, next);
}
LOGGER.info(getClass().getSimpleName() + ": Manor data loaded.");
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Unable to load manor data! " + e.getMessage());
}
}
// -------------------------------------------------------
// Manor methods
// -------------------------------------------------------
private final void scheduleModeChange()
{
// Calculate next mode change
_nextModeChange = Calendar.getInstance();
_nextModeChange.set(Calendar.SECOND, 0);
switch (_mode)
{
case MODIFIABLE:
_nextModeChange.set(Calendar.HOUR_OF_DAY, Config.ALT_MANOR_APPROVE_TIME);
_nextModeChange.set(Calendar.MINUTE, Config.ALT_MANOR_APPROVE_MIN);
if (_nextModeChange.before(Calendar.getInstance()))
{
_nextModeChange.add(Calendar.DATE, 1);
}
break;
case MAINTENANCE:
_nextModeChange.set(Calendar.HOUR_OF_DAY, Config.ALT_MANOR_REFRESH_TIME);
_nextModeChange.set(Calendar.MINUTE, Config.ALT_MANOR_REFRESH_MIN + Config.ALT_MANOR_MAINTENANCE_MIN);
break;
case APPROVED:
_nextModeChange.set(Calendar.HOUR_OF_DAY, Config.ALT_MANOR_REFRESH_TIME);
_nextModeChange.set(Calendar.MINUTE, Config.ALT_MANOR_REFRESH_MIN);
break;
}
// Schedule mode change
ThreadPoolManager.getInstance().scheduleGeneral(this::changeMode, (_nextModeChange.getTimeInMillis() - System.currentTimeMillis()));
}
public final void changeMode()
{
switch (_mode)
{
case APPROVED:
{
// Change mode
_mode = ManorMode.MAINTENANCE;
// Update manor period
for (Castle castle : CastleManager.getInstance().getCastles())
{
final L2Clan owner = castle.getOwner();
if (owner == null)
{
continue;
}
final int castleId = castle.getResidenceId();
final ItemContainer cwh = owner.getWarehouse();
for (CropProcure crop : _procure.get(castleId))
{
if (crop.getStartAmount() > 0)
{
// Adding bought crops to clan warehouse
if (crop.getStartAmount() != crop.getAmount())
{
long count = (long) ((crop.getStartAmount() - crop.getAmount()) * 0.9);
if ((count < 1) && (Rnd.nextInt(99) < 90))
{
count = 1;
}
if (count > 0)
{
cwh.addItem("Manor", getSeedByCrop(crop.getId()).getMatureId(), count, null, null);
}
}
// Reserved and not used money giving back to treasury
if (crop.getAmount() > 0)
{
castle.addToTreasuryNoTax(crop.getAmount() * crop.getPrice());
}
}
}
// Change next period to current and prepare next period data
final List<SeedProduction> _nextProduction = _productionNext.get(castleId);
final List<CropProcure> _nextProcure = _procureNext.get(castleId);
_production.put(castleId, _nextProduction);
_procure.put(castleId, _nextProcure);
if (castle.getTreasury() < getManorCost(castleId, false))
{
_productionNext.put(castleId, Collections.emptyList());
_procureNext.put(castleId, Collections.emptyList());
}
else
{
final List<SeedProduction> production = new ArrayList<>(_nextProduction);
for (SeedProduction s : production)
{
s.setAmount(s.getStartAmount());
}
_productionNext.put(castleId, production);
final List<CropProcure> procure = new ArrayList<>(_nextProcure);
for (CropProcure cr : procure)
{
cr.setAmount(cr.getStartAmount());
}
_procureNext.put(castleId, procure);
}
}
// Save changes
storeMe();
break;
}
case MAINTENANCE:
{
// Notify clan leader about manor mode change
for (Castle castle : CastleManager.getInstance().getCastles())
{
final L2Clan owner = castle.getOwner();
if (owner != null)
{
final L2ClanMember clanLeader = owner.getLeader();
if ((clanLeader != null) && clanLeader.isOnline())
{
clanLeader.getPlayerInstance().sendPacket(SystemMessageId.THE_MANOR_INFORMATION_HAS_BEEN_UPDATED);
}
}
}
_mode = ManorMode.MODIFIABLE;
break;
}
case MODIFIABLE:
{
_mode = ManorMode.APPROVED;
for (Castle castle : CastleManager.getInstance().getCastles())
{
final L2Clan owner = castle.getOwner();
if (owner == null)
{
continue;
}
int slots = 0;
final int castleId = castle.getResidenceId();
final ItemContainer cwh = owner.getWarehouse();
for (CropProcure crop : _procureNext.get(castleId))
{
if ((crop.getStartAmount() > 0) && (cwh.getItemsByItemId(getSeedByCrop(crop.getId()).getMatureId()) == null))
{
slots++;
}
}
final long manorCost = getManorCost(castleId, true);
if (!cwh.validateCapacity(slots) && (castle.getTreasury() < manorCost))
{
_productionNext.get(castleId).clear();
_procureNext.get(castleId).clear();
// Notify clan leader
final L2ClanMember clanLeader = owner.getLeader();
if ((clanLeader != null) && clanLeader.isOnline())
{
clanLeader.getPlayerInstance().sendPacket(SystemMessageId.YOU_DO_NOT_HAVE_ENOUGH_FUNDS_IN_THE_CLAN_WAREHOUSE_FOR_THE_MANOR_TO_OPERATE);
}
}
else
{
castle.addToTreasuryNoTax(-manorCost);
}
}
// Store changes
if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
storeMe();
}
break;
}
}
scheduleModeChange();
if (Config.DEBUG)
{
LOGGER.info(getClass().getName() + ": Manor mode changed to " + _mode.toString() + "!");
}
}
public final void setNextSeedProduction(List<SeedProduction> list, int castleId)
{
_productionNext.put(castleId, list);
if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement dps = con.prepareStatement("DELETE FROM castle_manor_production WHERE castle_id = ? AND next_period = 1");
PreparedStatement ips = con.prepareStatement(INSERT_PRODUCT))
{
// Delete old data
dps.setInt(1, castleId);
dps.executeUpdate();
// Insert new data
if (!list.isEmpty())
{
for (SeedProduction sp : list)
{
ips.setInt(1, castleId);
ips.setInt(2, sp.getId());
ips.setLong(3, sp.getAmount());
ips.setLong(4, sp.getStartAmount());
ips.setLong(5, sp.getPrice());
ips.setBoolean(6, true);
ips.addBatch();
}
ips.executeBatch();
}
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
}
}
}
public final void setNextCropProcure(List<CropProcure> list, int castleId)
{
_procureNext.put(castleId, list);
if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement dps = con.prepareStatement("DELETE FROM castle_manor_procure WHERE castle_id = ? AND next_period = 1");
PreparedStatement ips = con.prepareStatement(INSERT_CROP))
{
// Delete old data
dps.setInt(1, castleId);
dps.executeUpdate();
// Insert new data
if (!list.isEmpty())
{
for (CropProcure cp : list)
{
ips.setInt(1, castleId);
ips.setInt(2, cp.getId());
ips.setLong(3, cp.getAmount());
ips.setLong(4, cp.getStartAmount());
ips.setLong(5, cp.getPrice());
ips.setInt(6, cp.getReward());
ips.setBoolean(7, true);
ips.addBatch();
}
ips.executeBatch();
}
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
}
}
}
public final void updateCurrentProduction(int castleId, Collection<SeedProduction> items)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE castle_manor_production SET amount = ? WHERE castle_id = ? AND seed_id = ? AND next_period = 0"))
{
for (SeedProduction sp : items)
{
ps.setLong(1, sp.getAmount());
ps.setInt(2, castleId);
ps.setInt(3, sp.getId());
ps.addBatch();
}
ps.executeBatch();
}
catch (Exception e)
{
LOGGER.info(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
}
}
public final void updateCurrentProcure(int castleId, Collection<CropProcure> items)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE castle_manor_procure SET amount = ? WHERE castle_id = ? AND crop_id = ? AND next_period = 0"))
{
for (CropProcure sp : items)
{
ps.setLong(1, sp.getAmount());
ps.setInt(2, castleId);
ps.setInt(3, sp.getId());
ps.addBatch();
}
ps.executeBatch();
}
catch (Exception e)
{
LOGGER.info(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
}
}
public final List<SeedProduction> getSeedProduction(int castleId, boolean nextPeriod)
{
return (nextPeriod) ? _productionNext.get(castleId) : _production.get(castleId);
}
public final SeedProduction getSeedProduct(int castleId, int seedId, boolean nextPeriod)
{
for (SeedProduction sp : getSeedProduction(castleId, nextPeriod))
{
if (sp.getId() == seedId)
{
return sp;
}
}
return null;
}
public final List<CropProcure> getCropProcure(int castleId, boolean nextPeriod)
{
return (nextPeriod) ? _procureNext.get(castleId) : _procure.get(castleId);
}
public final CropProcure getCropProcure(int castleId, int cropId, boolean nextPeriod)
{
for (CropProcure cp : getCropProcure(castleId, nextPeriod))
{
if (cp.getId() == cropId)
{
return cp;
}
}
return null;
}
public final long getManorCost(int castleId, boolean nextPeriod)
{
final List<CropProcure> procure = getCropProcure(castleId, nextPeriod);
final List<SeedProduction> production = getSeedProduction(castleId, nextPeriod);
long total = 0;
for (SeedProduction seed : production)
{
final L2Seed s = getSeed(seed.getId());
total += (s == null) ? 1 : (s.getSeedReferencePrice() * seed.getStartAmount());
}
for (CropProcure crop : procure)
{
total += (crop.getPrice() * crop.getStartAmount());
}
return total;
}
@Override
public final boolean storeMe()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ds = con.prepareStatement("DELETE FROM castle_manor_production");
PreparedStatement is = con.prepareStatement(INSERT_PRODUCT);
PreparedStatement dp = con.prepareStatement("DELETE FROM castle_manor_procure");
PreparedStatement ip = con.prepareStatement(INSERT_CROP))
{
// Delete old seeds
ds.executeUpdate();
// Current production
for (Map.Entry<Integer, List<SeedProduction>> entry : _production.entrySet())
{
for (SeedProduction sp : entry.getValue())
{
is.setInt(1, entry.getKey());
is.setInt(2, sp.getId());
is.setLong(3, sp.getAmount());
is.setLong(4, sp.getStartAmount());
is.setLong(5, sp.getPrice());
is.setBoolean(6, false);
is.addBatch();
}
}
// Next production
for (Map.Entry<Integer, List<SeedProduction>> entry : _productionNext.entrySet())
{
for (SeedProduction sp : entry.getValue())
{
is.setInt(1, entry.getKey());
is.setInt(2, sp.getId());
is.setLong(3, sp.getAmount());
is.setLong(4, sp.getStartAmount());
is.setLong(5, sp.getPrice());
is.setBoolean(6, true);
is.addBatch();
}
}
// Execute production batch
is.executeBatch();
// Delete old procure
dp.executeUpdate();
// Current procure
for (Map.Entry<Integer, List<CropProcure>> entry : _procure.entrySet())
{
for (CropProcure cp : entry.getValue())
{
ip.setInt(1, entry.getKey());
ip.setInt(2, cp.getId());
ip.setLong(3, cp.getAmount());
ip.setLong(4, cp.getStartAmount());
ip.setLong(5, cp.getPrice());
ip.setInt(6, cp.getReward());
ip.setBoolean(7, false);
ip.addBatch();
}
}
// Next procure
for (Map.Entry<Integer, List<CropProcure>> entry : _procureNext.entrySet())
{
for (CropProcure cp : entry.getValue())
{
ip.setInt(1, entry.getKey());
ip.setInt(2, cp.getId());
ip.setLong(3, cp.getAmount());
ip.setLong(4, cp.getStartAmount());
ip.setLong(5, cp.getPrice());
ip.setInt(6, cp.getReward());
ip.setBoolean(7, true);
ip.addBatch();
}
}
// Execute procure batch
ip.executeBatch();
return true;
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
return false;
}
}
public final void resetManorData(int castleId)
{
_procure.get(castleId).clear();
_procureNext.get(castleId).clear();
_production.get(castleId).clear();
_productionNext.get(castleId).clear();
if (Config.ALT_MANOR_SAVE_ALL_ACTIONS)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ds = con.prepareStatement("DELETE FROM castle_manor_production WHERE castle_id = ?");
PreparedStatement dc = con.prepareStatement("DELETE FROM castle_manor_procure WHERE castle_id = ?"))
{
// Delete seeds
ds.setInt(1, castleId);
ds.executeUpdate();
// Delete procure
dc.setInt(1, castleId);
dc.executeUpdate();
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Unable to store manor data! " + e.getMessage());
}
}
}
public final boolean isUnderMaintenance()
{
return _mode.equals(ManorMode.MAINTENANCE);
}
public final boolean isManorApproved()
{
return _mode.equals(ManorMode.APPROVED);
}
public final boolean isModifiablePeriod()
{
return _mode.equals(ManorMode.MODIFIABLE);
}
public final String getCurrentModeName()
{
return _mode.toString();
}
public final String getNextModeChange()
{
return new SimpleDateFormat("dd/MM HH:mm:ss").format(_nextModeChange.getTime());
}
// -------------------------------------------------------
// Seed methods
// -------------------------------------------------------
public final List<L2Seed> getCrops()
{
final List<L2Seed> seeds = new ArrayList<>();
final List<Integer> cropIds = new ArrayList<>();
for (L2Seed seed : _seeds.values())
{
if (!cropIds.contains(seed.getCropId()))
{
seeds.add(seed);
cropIds.add(seed.getCropId());
}
}
cropIds.clear();
return seeds;
}
public final Set<L2Seed> getSeedsForCastle(int castleId)
{
return _seeds.values().stream().filter(s -> s.getCastleId() == castleId).collect(Collectors.toSet());
}
public final Set<Integer> getSeedIds()
{
return _seeds.keySet();
}
public final Set<Integer> getCropIds()
{
return _seeds.values().stream().map(L2Seed::getCropId).collect(Collectors.toSet());
}
public final L2Seed getSeed(int seedId)
{
return _seeds.get(seedId);
}
public final L2Seed getSeedByCrop(int cropId, int castleId)
{
for (L2Seed s : getSeedsForCastle(castleId))
{
if (s.getCropId() == cropId)
{
return s;
}
}
return null;
}
public final L2Seed getSeedByCrop(int cropId)
{
for (L2Seed s : _seeds.values())
{
if (s.getCropId() == cropId)
{
return s;
}
}
return null;
}
// -------------------------------------------------------
// Static methods
// -------------------------------------------------------
public static final CastleManorManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CastleManorManager _instance = new CastleManorManager();
}
}

View File

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

View File

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

View File

@ -0,0 +1,160 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.ResultSet;
import java.sql.Statement;
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 final class CoupleManager
{
private static final Logger _log = Logger.getLogger(CoupleManager.class.getName());
private FastList<Couple> _couples;
protected CoupleManager()
{
load();
}
public void reload()
{
getCouples().clear();
load();
}
private final void load()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement ps = con.createStatement();
ResultSet rs = ps.executeQuery("SELECT id FROM mods_wedding ORDER BY id"))
{
while (rs.next())
{
getCouples().add(new Couple(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + getCouples().size() + " couples(s)");
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Exception: CoupleManager.load(): " + e.getMessage(), e);
}
}
public final Couple getCouple(int coupleId)
{
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;
}
public static final CoupleManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CoupleManager _instance = new CoupleManager();
}
}

View File

@ -0,0 +1,437 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.sql.Statement;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.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.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.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.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.util.Broadcast;
/**
* UnAfraid: TODO: Rewrite with DocumentParser
* @author Micht
*/
public final class CursedWeaponsManager
{
private static final Logger _log = Logger.getLogger(CursedWeaponsManager.class.getName());
private Map<Integer, CursedWeapon> _cursedWeapons;
protected CursedWeaponsManager()
{
init();
}
private void init()
{
_cursedWeapons = new HashMap<>();
if (!Config.ALLOW_CURSED_WEAPONS)
{
return;
}
load();
restore();
controlPlayers();
_log.info(getClass().getSimpleName() + ": Loaded : " + _cursedWeapons.size() + " cursed weapon(s).");
}
public final void reload()
{
init();
}
private final void load()
{
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
File file = new File(Config.DATAPACK_ROOT + "/data/cursedWeapons.xml");
if (!file.exists())
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't find data/" + file.getName());
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);
}
}
}
}
}
catch (Exception e)
{
_log.log(Level.SEVERE, "Error parsing cursed weapons file.", e);
return;
}
}
private final void restore()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT itemId, charId, playerKarma, playerPkKills, nbKills, endTime FROM cursed_weapons"))
{
// Retrieve the L2PcInstance from the characters table of the database
CursedWeapon cw;
while (rs.next())
{
cw = _cursedWeapons.get(rs.getInt("itemId"));
cw.setPlayerId(rs.getInt("charId"));
cw.setPlayerKarma(rs.getInt("playerKarma"));
cw.setPlayerPkKills(rs.getInt("playerPkKills"));
cw.setNbKills(rs.getInt("nbKills"));
cw.setEndTime(rs.getLong("endTime"));
cw.reActivate();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not restore CursedWeapons data: " + e.getMessage(), e);
}
}
private final void controlPlayers()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
// TODO: See comments below...
// This entire for loop should NOT be necessary, since it is already handled by
// CursedWeapon.endOfLife(). However, if we indeed *need* to duplicate it for safety,
// then we'd better make sure that it FULLY cleans up inactive cursed weapons!
// Undesired effects result otherwise, such as player with no zariche but with karma
// or a lost-child entry in the cursed weapons table, without a corresponding one in items...
// Retrieve the L2PcInstance from the characters table of the database
try (PreparedStatement ps = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?"))
{
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated())
{
continue;
}
// Do an item check to be sure that the cursed weapon isn't hold by someone
int itemId = cw.getItemId();
ps.setInt(1, itemId);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
// A player has the cursed weapon in his inventory ...
int playerId = rset.getInt("owner_id");
_log.info("PROBLEM : Player " + playerId + " owns the cursed weapon " + itemId + " but he shouldn't.");
// Delete the item
try (PreparedStatement delete = con.prepareStatement("DELETE FROM items WHERE owner_id=? AND item_id=?"))
{
delete.setInt(1, playerId);
delete.setInt(2, itemId);
if (delete.executeUpdate() != 1)
{
_log.warning("Error while deleting cursed weapon " + itemId + " from userId " + playerId);
}
}
// Restore the player's old karma and pk count
try (PreparedStatement update = con.prepareStatement("UPDATE characters SET karma=?, pkkills=? WHERE charId=?"))
{
update.setInt(1, cw.getPlayerKarma());
update.setInt(2, cw.getPlayerPkKills());
update.setInt(3, playerId);
if (update.executeUpdate() != 1)
{
_log.warning("Error while updating karma & pkkills for userId " + cw.getPlayerId());
}
}
// clean up the cursed weapons table.
removeFromDb(itemId);
}
}
ps.clearParameters();
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Could not check CursedWeapons data: " + e.getMessage(), e);
}
}
public synchronized void checkDrop(L2Attackable attackable, L2PcInstance player)
{
if ((attackable instanceof L2DefenderInstance) || (attackable instanceof L2GuardInstance) || (attackable instanceof L2GrandBossInstance) || (attackable instanceof L2FeedableBeastInstance) || (attackable instanceof L2FortCommanderInstance))
{
return;
}
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActive())
{
continue;
}
if (cw.checkDrop(attackable, player))
{
break;
}
}
}
public void activate(L2PcInstance player, L2ItemInstance item)
{
CursedWeapon cw = _cursedWeapons.get(item.getId());
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.S1_HAS_S2_MINUTE_S_OF_USAGE_TIME_REMAINING);
sm.addString(cw.getName());
// sm.addItemName(cw.getItemId());
sm.addInt((int) ((cw.getEndTime() - System.currentTimeMillis()) / 60000));
player.sendPacket(sm);
}
}
}
public int checkOwnsWeaponId(int ownerId)
{
for (CursedWeapon cw : _cursedWeapons.values())
{
if (cw.isActivated() && (ownerId == cw.getPlayerId()))
{
return cw.getItemId();
}
}
return -1;
}
public static void removeFromDb(int itemId)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM cursed_weapons WHERE itemId = ?"))
{
ps.setInt(1, itemId);
ps.executeUpdate();
}
catch (SQLException e)
{
_log.log(Level.SEVERE, "CursedWeaponsManager: Failed to remove data: " + e.getMessage(), e);
}
}
public void saveData()
{
for (CursedWeapon cw : _cursedWeapons.values())
{
cw.saveData();
}
}
public boolean isCursed(int itemId)
{
return _cursedWeapons.containsKey(itemId);
}
public Collection<CursedWeapon> getCursedWeapons()
{
return _cursedWeapons.values();
}
public Set<Integer> getCursedWeaponsIds()
{
return _cursedWeapons.keySet();
}
public CursedWeapon getCursedWeapon(int itemId)
{
return _cursedWeapons.get(itemId);
}
public void givePassive(int itemId)
{
try
{
_cursedWeapons.get(itemId).giveSkill();
}
catch (Exception e)
{
/***/
}
}
public static final CursedWeaponsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CursedWeaponsManager _instance = new CursedWeaponsManager();
}
}

View File

@ -0,0 +1,270 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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;
/**
* @author godson
*/
public final 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;
}
protected DayNightSpawnManager()
{
_dayCreatures = new ArrayList<>();
_nightCreatures = new ArrayList<>();
_bosses = new FastMap<>();
}
public void addDayCreature(L2Spawn spawnDat)
{
_dayCreatures.add(spawnDat);
}
public void addNightCreature(L2Spawn spawnDat)
{
_nightCreatures.add(spawnDat);
}
/**
* Spawn Day Creatures, and Unspawn Night Creatures
*/
public void spawnDayCreatures()
{
spawnCreatures(_nightCreatures, _dayCreatures, "night", "day");
}
/**
* Spawn Night Creatures, and Unspawn Day Creatures
*/
public void spawnNightCreatures()
{
spawnCreatures(_dayCreatures, _nightCreatures, "day", "night");
}
/**
* Manage Spawn/Respawn
* @param unSpawnCreatures List with spawns must be unspawned
* @param spawnCreatures List with spawns must be spawned
* @param UnspawnLogInfo String for log info for unspawned L2NpcInstance
* @param SpawnLogInfo String for log info for spawned L2NpcInstance
*/
private void spawnCreatures(List<L2Spawn> unSpawnCreatures, List<L2Spawn> spawnCreatures, String UnspawnLogInfo, String SpawnLogInfo)
{
try
{
if (!unSpawnCreatures.isEmpty())
{
int i = 0;
for (L2Spawn spawn : unSpawnCreatures)
{
if (spawn == null)
{
continue;
}
spawn.stopRespawn();
L2Npc last = spawn.getLastSpawn();
if (last != null)
{
last.deleteMe();
i++;
}
}
_log.info("DayNightSpawnManager: Removed " + i + " " + UnspawnLogInfo + " creatures");
}
int i = 0;
for (L2Spawn spawnDat : spawnCreatures)
{
if (spawnDat == null)
{
continue;
}
spawnDat.startRespawn();
spawnDat.doSpawn();
i++;
}
_log.info("DayNightSpawnManager: Spawned " + i + " " + SpawnLogInfo + " creatures");
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while spawning creatures: " + e.getMessage(), e);
}
}
private void changeMode(int mode)
{
if (_nightCreatures.isEmpty() && _dayCreatures.isEmpty() && _bosses.isEmpty())
{
return;
}
switch (mode)
{
case 0:
spawnDayCreatures();
specialNightBoss(0);
break;
case 1:
spawnNightCreatures();
specialNightBoss(1);
break;
default:
_log.warning("DayNightSpawnManager: Wrong mode sent");
break;
}
}
public DayNightSpawnManager trim()
{
((ArrayList<?>) _nightCreatures).trimToSize();
((ArrayList<?>) _dayCreatures).trimToSize();
return this;
}
public void notifyChangeMode()
{
try
{
if (GameTimeController.getInstance().isNight())
{
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
{
L2RaidBossInstance boss;
for (L2Spawn spawn : _bosses.keySet())
{
boss = _bosses.get(spawn);
if ((boss == null) && (mode == 1))
{
boss = (L2RaidBossInstance) spawn.doSpawn();
RaidBossSpawnManager.getInstance().notifySpawnNightBoss(boss);
_bosses.remove(spawn);
_bosses.put(spawn, boss);
continue;
}
if ((boss == null) && (mode == 0))
{
continue;
}
if ((boss != null) && (boss.getId() == 25328) && boss.getRaidStatus().equals(RaidBossSpawnManager.StatusEnum.ALIVE))
{
handleHellmans(boss, mode);
}
return;
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error while specialNoghtBoss(): " + e.getMessage(), e);
}
}
private void handleHellmans(L2RaidBossInstance boss, int mode)
{
switch (mode)
{
case 0:
boss.deleteMe();
_log.info(getClass().getSimpleName() + ": Deleting Hellman raidboss");
break;
case 1:
if (!boss.isVisible())
{
boss.spawnMe();
}
_log.info(getClass().getSimpleName() + ": Spawning Hellman raidboss");
break;
}
}
public L2RaidBossInstance handleBoss(L2Spawn spawnDat)
{
if (_bosses.containsKey(spawnDat))
{
return _bosses.get(spawnDat);
}
if (GameTimeController.getInstance().isNight())
{
L2RaidBossInstance raidboss = (L2RaidBossInstance) spawnDat.doSpawn();
_bosses.put(spawnDat, raidboss);
return raidboss;
}
_bosses.put(spawnDat, null);
return null;
}
private static class SingletonHolder
{
protected static final DayNightSpawnManager _instance = new DayNightSpawnManager();
}
}

View File

@ -0,0 +1,239 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.List;
import javolution.util.FastList;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Duel;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
public final class DuelManager
{
private final List<Duel> _duels;
private int _currentDuelId = 0x90;
protected DuelManager()
{
_duels = new FastList<>();
}
private int getNextDuelId()
{
// In case someone wants to run the server forever :)
if (++_currentDuelId >= 2147483640)
{
_currentDuelId = 1;
}
return _currentDuelId;
}
public Duel getDuel(int duelId)
{
for (Duel duel : _duels)
{
if (duel.getId() == duelId)
{
return duel;
}
}
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().getMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
if (!playerInPvP)
{
for (L2PcInstance temp : playerB.getParty().getMembers())
{
if (temp.getPvpFlag() != 0)
{
playerInPvP = true;
break;
}
}
}
// A player has PvP flag
if (playerInPvP)
{
for (L2PcInstance temp : playerA.getParty().getMembers())
{
temp.sendMessage(engagedInPvP);
}
for (L2PcInstance temp : playerB.getParty().getMembers())
{
temp.sendMessage(engagedInPvP);
}
return;
}
}
else
{
if ((playerA.getPvpFlag() != 0) || (playerB.getPvpFlag() != 0))
{
playerA.sendMessage(engagedInPvP);
playerB.sendMessage(engagedInPvP);
return;
}
}
final 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;
}
final Duel duel = getDuel(player.getDuelId());
duel.doSurrender(player);
}
/**
* Updates player states.
* @param player - the dying player
*/
public void onPlayerDefeat(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onPlayerDefeat(player);
}
}
/**
* Registers a buff which will be removed if the duel ends
* @param player
* @param buff
*/
public void onBuff(L2PcInstance player, Skill buff)
{
if ((player == null) || !player.isInDuel() || (buff == null))
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onBuff(player, buff);
}
}
/**
* Removes player from duel.
* @param player - the removed player
*/
public void onRemoveFromParty(L2PcInstance player)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel != null)
{
duel.onRemoveFromParty(player);
}
}
/**
* Broadcasts a packet to the team opposing the given player.
* @param player
* @param packet
*/
public void broadcastToOppositTeam(L2PcInstance player, L2GameServerPacket packet)
{
if ((player == null) || !player.isInDuel())
{
return;
}
final Duel duel = getDuel(player.getDuelId());
if (duel == null)
{
return;
}
if ((duel.getPlayerA() == null) || (duel.getPlayerB() == null))
{
return;
}
if (duel.getPlayerA() == player)
{
duel.broadcastToTeam2(packet);
}
else if (duel.getPlayerB() == player)
{
duel.broadcastToTeam1(packet);
}
else if (duel.isPartyDuel())
{
if ((duel.getPlayerA().getParty() != null) && duel.getPlayerA().getParty().getMembers().contains(player))
{
duel.broadcastToTeam2(packet);
}
else if ((duel.getPlayerB().getParty() != null) && duel.getPlayerB().getParty().getMembers().contains(player))
{
duel.broadcastToTeam1(packet);
}
}
}
public static final DuelManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final DuelManager _instance = new DuelManager();
}
}

View File

@ -0,0 +1,214 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.ResultSet;
import java.sql.Statement;
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 final class FortManager implements InstanceListManager
{
protected static final Logger _log = Logger.getLogger(FortManager.class.getName());
private List<Fort> _forts;
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;
}
public final Fort getFortById(int fortId)
{
for (Fort f : getForts())
{
if (f.getResidenceId() == fortId)
{
return f;
}
}
return null;
}
public final Fort getFortByOwner(L2Clan clan)
{
for (Fort f : getForts())
{
if (f.getOwnerClan() == clan)
{
return f;
}
}
return null;
}
public final Fort getFort(String name)
{
for (Fort f : getForts())
{
if (f.getName().equalsIgnoreCase(name.trim()))
{
return f;
}
}
return null;
}
public final Fort getFort(int x, int y, int z)
{
for (Fort f : getForts())
{
if (f.checkIfInZone(x, y, z))
{
return f;
}
}
return null;
}
public final Fort getFort(L2Object activeObject)
{
return getFort(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getFortIndex(int fortId)
{
Fort fort;
for (int i = 0; i < getForts().size(); i++)
{
fort = getForts().get(i);
if ((fort != null) && (fort.getResidenceId() == fortId))
{
return i;
}
}
return -1;
}
public final int getFortIndex(L2Object activeObject)
{
return getFortIndex(activeObject.getX(), activeObject.getY(), activeObject.getZ());
}
public final int getFortIndex(int x, int y, int z)
{
Fort fort;
for (int i = 0; i < 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()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id FROM fort ORDER BY id"))
{
while (rs.next())
{
getForts().add(new Fort(rs.getInt("id")));
}
_log.info(getClass().getSimpleName() + ": Loaded: " + getForts().size() + " fortress");
for (Fort fort : getForts())
{
fort.getSiege().getSiegeGuardManager().loadSiegeGuard();
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Exception: loadFortData(): " + e.getMessage(), e);
}
}
@Override
public void updateReferences()
{
}
@Override
public void activateInstances()
{
for (final Fort fort : _forts)
{
fort.activateInstance();
}
}
public static final FortManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final FortManager _instance = new FortManager();
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.NpcData;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Fort;
public final class FortSiegeGuardManager
{
private static final Logger _log = Logger.getLogger(FortSiegeGuardManager.class.getName());
private final Fort _fort;
private final FastMap<Integer, FastList<L2Spawn>> _siegeGuards = new FastMap<>();
public FortSiegeGuardManager(Fort fort)
{
_fort = fort;
}
/**
* Spawn guards.
*/
public void spawnSiegeGuard()
{
try
{
final FastList<L2Spawn> monsterList = getSiegeGuardSpawn().get(getFort().getResidenceId());
if (monsterList != null)
{
for (L2Spawn spawnDat : monsterList)
{
spawnDat.doSpawn();
if (spawnDat.getRespawnDelay() == 0)
{
spawnDat.stopRespawn();
}
else
{
spawnDat.startRespawn();
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error spawning siege guards for fort " + getFort().getName() + ":" + e.getMessage(), e);
}
}
/**
* Unspawn guards.
*/
public void unspawnSiegeGuard()
{
try
{
final FastList<L2Spawn> monsterList = getSiegeGuardSpawn().get(getFort().getResidenceId());
if (monsterList != null)
{
for (L2Spawn spawnDat : monsterList)
{
spawnDat.stopRespawn();
if (spawnDat.getLastSpawn() != null)
{
spawnDat.getLastSpawn().doDie(spawnDat.getLastSpawn());
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error unspawning siege guards for fort " + getFort().getName() + ":" + e.getMessage(), e);
}
}
/**
* Load guards.
*/
void loadSiegeGuard()
{
_siegeGuards.clear();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT npcId, x, y, z, heading, respawnDelay FROM fort_siege_guards WHERE fortId = ?"))
{
final int fortId = getFort().getResidenceId();
ps.setInt(1, fortId);
try (ResultSet rs = ps.executeQuery())
{
FastList<L2Spawn> siegeGuardSpawns = new FastList<>();
while (rs.next())
{
L2NpcTemplate template = NpcData.getInstance().getTemplate(rs.getInt("npcId"));
if (template != null)
{
L2Spawn spawn = new L2Spawn(template);
spawn.setAmount(1);
spawn.setX(rs.getInt("x"));
spawn.setY(rs.getInt("y"));
spawn.setZ(rs.getInt("z"));
spawn.setHeading(rs.getInt("heading"));
spawn.setRespawnDelay(rs.getInt("respawnDelay"));
spawn.setLocationId(0);
siegeGuardSpawns.add(spawn);
}
else
{
_log.warning("Missing npc data in npc table for ID: " + rs.getInt("npcId"));
}
}
_siegeGuards.put(fortId, siegeGuardSpawns);
}
}
catch (Exception e)
{
_log.log(Level.WARNING, "Error loading siege guard for fort " + getFort().getName() + ": " + e.getMessage(), e);
}
}
public final Fort getFort()
{
return _fort;
}
public final FastMap<Integer, FastList<L2Spawn>> getSiegeGuardSpawn()
{
return _siegeGuards;
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,401 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javolution.util.FastMap;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.engines.DocumentParser;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.entity.Instance;
import com.l2jserver.gameserver.model.instancezone.InstanceWorld;
/**
* @author evill33t, GodKratos
*/
public final class InstanceManager implements DocumentParser
{
private static final Map<Integer, Instance> _instanceList = new FastMap<>();
private final Map<Integer, InstanceWorld> _instanceWorlds = new FastMap<>();
private int _dynamic = 300000;
// InstanceId Names
private static final Map<Integer, String> _instanceIdNames = new HashMap<>();
private final Map<Integer, Map<Integer, Long>> _playerInstanceTimes = new FastMap<>();
// SQL Queries
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=?";
protected InstanceManager()
{
// Creates the multiverse.
_instanceList.put(-1, new Instance(-1, "multiverse"));
LOGGER.info(getClass().getSimpleName() + ": Multiverse Instance created.");
// Creates the universe.
_instanceList.put(0, new Instance(0, "universe"));
LOGGER.info(getClass().getSimpleName() + ": Universe Instance created.");
load();
}
@Override
public void load()
{
_instanceIdNames.clear();
parseDatapackFile("data/instancenames.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _instanceIdNames.size() + " instance names.");
}
/**
* @param playerObjId
* @param id
* @return
*/
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;
}
/**
* @param playerObjId
* @return
*/
public Map<Integer, Long> getAllInstanceTimes(int playerObjId)
{
if (!_playerInstanceTimes.containsKey(playerObjId))
{
restoreInstanceTimes(playerObjId);
}
final Map<Integer, Long> instanceTimes = _playerInstanceTimes.get(playerObjId);
for (Entry<Integer, Long> entry : instanceTimes.entrySet())
{
if (entry.getValue() <= System.currentTimeMillis())
{
deleteInstanceTime(playerObjId, entry.getKey());
}
}
return instanceTimes;
}
/**
* @param playerObjId
* @param id
* @param time
*/
public void setInstanceTime(int playerObjId, int id, long time)
{
if (!_playerInstanceTimes.containsKey(playerObjId))
{
restoreInstanceTimes(playerObjId);
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(ADD_INSTANCE_TIME))
{
ps.setInt(1, playerObjId);
ps.setInt(2, id);
ps.setLong(3, time);
ps.setLong(4, time);
ps.execute();
_playerInstanceTimes.get(playerObjId).put(id, time);
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Could not insert character instance time data: " + e.getMessage());
}
}
/**
* @param playerObjId
* @param id
*/
public void deleteInstanceTime(int playerObjId, int id)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(DELETE_INSTANCE_TIME))
{
ps.setInt(1, playerObjId);
ps.setInt(2, id);
ps.execute();
_playerInstanceTimes.get(playerObjId).remove(id);
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Could not delete character instance time data: " + e.getMessage());
}
}
/**
* @param playerObjId
*/
public void restoreInstanceTimes(int playerObjId)
{
if (_playerInstanceTimes.containsKey(playerObjId))
{
return; // already restored
}
_playerInstanceTimes.put(playerObjId, new FastMap<Integer, Long>());
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(RESTORE_INSTANCE_TIMES))
{
ps.setInt(1, playerObjId);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
int id = rs.getInt("instanceId");
long time = rs.getLong("time");
if (time < System.currentTimeMillis())
{
deleteInstanceTime(playerObjId, id);
}
else
{
_playerInstanceTimes.get(playerObjId).put(id, time);
}
}
}
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Could not delete character instance time data: " + e.getMessage());
}
}
/**
* @param id
* @return
*/
public String getInstanceIdName(int id)
{
if (_instanceIdNames.containsKey(id))
{
return _instanceIdNames.get(id);
}
return ("UnknownInstance");
}
@Override
public void parseDocument(Document doc)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equals(n.getNodeName()))
{
NamedNodeMap attrs;
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("instance".equals(d.getNodeName()))
{
attrs = d.getAttributes();
_instanceIdNames.put(parseInteger(attrs, "id"), attrs.getNamedItem("name").getNodeValue());
}
}
}
}
}
/**
* @param world
*/
public void addWorld(InstanceWorld world)
{
_instanceWorlds.put(world.getInstanceId(), world);
}
/**
* @param instanceId
* @return
*/
public InstanceWorld getWorld(int instanceId)
{
return _instanceWorlds.get(instanceId);
}
/**
* Check if the player have a World Instance where it's allowed to enter.
* @param player the player to check
* @return the instance world
*/
public InstanceWorld getPlayerWorld(L2PcInstance player)
{
for (InstanceWorld temp : _instanceWorlds.values())
{
if ((temp != null) && (temp.isAllowed(player.getObjectId())))
{
return temp;
}
}
return null;
}
/**
* @param instanceid
*/
public void destroyInstance(int instanceid)
{
if (instanceid <= 0)
{
return;
}
final 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);
}
}
}
/**
* @param instanceid
* @return
*/
public Instance getInstance(int instanceid)
{
return _instanceList.get(instanceid);
}
/**
* @return
*/
public Map<Integer, Instance> getInstances()
{
return _instanceList;
}
/**
* @param objectId
* @return
*/
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;
}
/**
* @param id
* @return
*/
public boolean createInstance(int id)
{
if (getInstance(id) != null)
{
return false;
}
final Instance instance = new Instance(id);
_instanceList.put(id, instance);
return true;
}
/**
* @param id
* @param template
* @return
*/
public boolean createInstanceFromTemplate(int id, String template)
{
if (getInstance(id) != null)
{
return false;
}
final 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)
{
LOGGER.warning(getClass().getSimpleName() + ": More then " + (Integer.MAX_VALUE - 300000) + " instances created");
_dynamic = 300000;
}
}
final Instance instance = new Instance(_dynamic);
_instanceList.put(_dynamic, instance);
if (template != null)
{
instance.loadInstanceTemplate(template);
}
return _dynamic;
}
/**
* Gets the single instance of {@code InstanceManager}.
* @return single instance of {@code InstanceManager}
*/
public static final InstanceManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final InstanceManager _instance = new InstanceManager();
}
}

View File

@ -0,0 +1,174 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.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());
private final Map<Integer, ItemAuctionInstance> _managerInstances = new HashMap<>();
private final AtomicInteger _auctionIds;
protected ItemAuctionManager()
{
_auctionIds = new AtomicInteger(1);
if (!Config.ALT_ITEM_AUCTION_ENABLED)
{
_log.log(Level.INFO, getClass().getSimpleName() + ": Disabled by config.");
return;
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rset = statement.executeQuery("SELECT auctionId FROM item_auction ORDER BY auctionId DESC LIMIT 0, 1"))
{
if (rset.next())
{
_auctionIds.set(rset.getInt(1) + 1);
}
}
catch (final SQLException e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading auctions.", e);
}
final File file = new File(Config.DATAPACK_ROOT + "/data/ItemAuctions.xml");
if (!file.exists())
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Missing ItemAuctions.xml!");
return;
}
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setIgnoringComments(true);
try
{
final Document doc = factory.newDocumentBuilder().parse(file);
for (Node na = doc.getFirstChild(); na != null; na = na.getNextSibling())
{
if ("list".equalsIgnoreCase(na.getNodeName()))
{
for (Node nb = na.getFirstChild(); nb != null; nb = nb.getNextSibling())
{
if ("instance".equalsIgnoreCase(nb.getNodeName()))
{
final NamedNodeMap nab = nb.getAttributes();
final int instanceId = Integer.parseInt(nab.getNamedItem("id").getNodeValue());
if (_managerInstances.containsKey(instanceId))
{
throw new Exception("Dublicated instanceId " + instanceId);
}
final ItemAuctionInstance instance = new ItemAuctionInstance(instanceId, _auctionIds, nb);
_managerInstances.put(instanceId, instance);
}
}
}
}
_log.log(Level.INFO, getClass().getSimpleName() + ": Loaded " + _managerInstances.size() + " instance(s).");
}
catch (Exception e)
{
_log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading auctions from xml.", e);
}
}
public final void shutdown()
{
for (ItemAuctionInstance instance : _managerInstances.values())
{
instance.shutdown();
}
}
public final ItemAuctionInstance getManagerInstance(final int instanceId)
{
return _managerInstances.get(instanceId);
}
public final int getNextAuctionId()
{
return _auctionIds.getAndIncrement();
}
public static final void deleteAuction(final int auctionId)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement statement = con.prepareStatement("DELETE FROM item_auction WHERE auctionId=?"))
{
statement.setInt(1, auctionId);
statement.execute();
}
try (PreparedStatement statement = con.prepareStatement("DELETE FROM item_auction_bid WHERE auctionId=?"))
{
statement.setInt(1, auctionId);
statement.execute();
}
}
catch (SQLException e)
{
_log.log(Level.SEVERE, "L2ItemAuctionManagerInstance: Failed deleting auction: " + auctionId, e);
}
}
/**
* Gets the single instance of {@code ItemAuctionManager}.
* @return single instance of {@code ItemAuctionManager}
*/
public static final ItemAuctionManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ItemAuctionManager _instance = new ItemAuctionManager();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,199 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.sql.Statement;
import java.util.ArrayList;
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
* @version 8/24/10
*/
public class RaidBossPointsManager
{
private static final Logger _log = Logger.getLogger(RaidBossPointsManager.class.getName());
private FastMap<Integer, Map<Integer, Integer>> _list;
public RaidBossPointsManager()
{
init();
}
private final void init()
{
_list = new FastMap<>();
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT `charId`,`boss_id`,`points` FROM `character_raid_points`"))
{
while (rs.next())
{
int charId = rs.getInt("charId");
int bossId = rs.getInt("boss_id");
int points = rs.getInt("points");
Map<Integer, Integer> values = _list.get(charId);
if (values == null)
{
values = new FastMap<>();
}
values.put(bossId, points);
_list.put(charId, values);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _list.size() + " Characters Raid Points.");
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldnt load raid points ", e);
}
}
public final void updatePointsInDB(L2PcInstance player, int raidId, int points)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("REPLACE INTO character_raid_points (`charId`,`boss_id`,`points`) VALUES (?,?,?)"))
{
ps.setInt(1, player.getObjectId());
ps.setInt(2, raidId);
ps.setInt(3, points);
ps.executeUpdate();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't update char raid points for player: " + player, e);
}
}
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()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE from character_raid_points WHERE charId > 0"))
{
statement.executeUpdate();
_list.clear();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't clean raid points", e);
}
}
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());
list.sort(Comparator.comparing(Entry<Integer, Integer>::getValue).reversed());
int ranking = 1;
for (Map.Entry<Integer, Integer> entry : list)
{
tmpRanking.put(entry.getKey(), ranking++);
}
return tmpRanking;
}
public static final RaidBossPointsManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final RaidBossPointsManager _instance = new RaidBossPointsManager();
}
}

View File

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

View File

@ -0,0 +1,282 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.NpcData;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.entity.Castle;
public final class SiegeGuardManager
{
private static Logger _log = Logger.getLogger(SiegeGuardManager.class.getName());
private final Castle _castle;
private final List<L2Spawn> _siegeGuardSpawn = new FastList<>();
public SiegeGuardManager(Castle castle)
{
_castle = castle;
}
/**
* Add guard.
* @param activeChar
* @param npcId
*/
public void addSiegeGuard(L2PcInstance activeChar, int npcId)
{
if (activeChar == null)
{
return;
}
addSiegeGuard(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
}
/**
* Add guard.
* @param x
* @param y
* @param z
* @param heading
* @param npcId
*/
public void addSiegeGuard(int x, int y, int z, int heading, int npcId)
{
saveSiegeGuard(x, y, z, heading, npcId, 0);
}
/**
* Hire merc.
* @param activeChar
* @param npcId
*/
public void hireMerc(L2PcInstance activeChar, int npcId)
{
if (activeChar == null)
{
return;
}
hireMerc(activeChar.getX(), activeChar.getY(), activeChar.getZ(), activeChar.getHeading(), npcId);
}
/**
* Hire merc.
* @param x
* @param y
* @param z
* @param heading
* @param npcId
*/
public void hireMerc(int x, int y, int z, int heading, int npcId)
{
saveSiegeGuard(x, y, z, heading, npcId, 1);
}
/**
* Remove a single mercenary, identified by the npcId and location. Presumably, this is used when a castle lord picks up a previously dropped ticket
* @param npcId
* @param x
* @param y
* @param z
*/
public void removeMerc(int npcId, int x, int y, int z)
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Delete From castle_siege_guards Where npcId = ? And x = ? AND y = ? AND z = ? AND isHired = 1"))
{
ps.setInt(1, npcId);
ps.setInt(2, x);
ps.setInt(3, y);
ps.setInt(4, z);
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting hired siege guard at " + x + ',' + y + ',' + z + ": " + e.getMessage(), e);
}
}
/**
* Remove mercs.
*/
public void removeMercs()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("Delete From castle_siege_guards Where castleId = ? And isHired = 1"))
{
ps.setInt(1, getCastle().getResidenceId());
ps.execute();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error deleting hired siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
}
/**
* Spawn guards.
*/
public void spawnSiegeGuard()
{
try
{
int hiredCount = 0, hiredMax = MercTicketManager.getInstance().getMaxAllowedMerc(_castle.getResidenceId());
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, getClass().getSimpleName() + ": Error spawning siege guards for castle " + getCastle().getName(), e);
}
}
/**
* Unspawn guards.
*/
public void unspawnSiegeGuard()
{
for (L2Spawn spawn : getSiegeGuardSpawn())
{
if ((spawn != null) && (spawn.getLastSpawn() != null))
{
spawn.stopRespawn();
spawn.getLastSpawn().doDie(spawn.getLastSpawn());
}
}
getSiegeGuardSpawn().clear();
}
/**
* Load guards.
*/
private void loadSiegeGuard()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM castle_siege_guards Where castleId = ? And isHired = ?"))
{
ps.setInt(1, getCastle().getResidenceId());
if (getCastle().getOwnerId() > 0)
{
ps.setInt(2, 1);
}
else
{
ps.setInt(2, 0);
}
try (ResultSet rs = ps.executeQuery())
{
L2Spawn spawn1;
L2NpcTemplate template1;
while (rs.next())
{
template1 = NpcData.getInstance().getTemplate(rs.getInt("npcId"));
if (template1 != null)
{
spawn1 = new L2Spawn(template1);
spawn1.setAmount(1);
spawn1.setX(rs.getInt("x"));
spawn1.setY(rs.getInt("y"));
spawn1.setZ(rs.getInt("z"));
spawn1.setHeading(rs.getInt("heading"));
spawn1.setRespawnDelay(rs.getInt("respawnDelay"));
spawn1.setLocationId(0);
_siegeGuardSpawn.add(spawn1);
}
else
{
_log.warning(getClass().getSimpleName() + ": Missing npc data in npc table for id: " + rs.getInt("npcId"));
}
}
}
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error loading siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
}
/**
* Save guards.
* @param x
* @param y
* @param z
* @param heading
* @param npcId
* @param isHire
*/
private void saveSiegeGuard(int x, int y, int z, int heading, int npcId, int isHire)
{
try (Connection con = 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().getResidenceId());
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();
}
catch (Exception e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Error adding siege guard for castle " + getCastle().getName() + ": " + e.getMessage(), e);
}
}
public final Castle getCastle()
{
return _castle;
}
public final List<L2Spawn> getSiegeGuardSpawn()
{
return _siegeGuardSpawn;
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,752 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.gameserver.engines.DocumentParser;
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.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.zone.AbstractZoneSettings;
import com.l2jserver.gameserver.model.zone.L2ZoneForm;
import com.l2jserver.gameserver.model.zone.L2ZoneRespawn;
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;
import com.l2jserver.gameserver.model.zone.type.L2RespawnZone;
import com.l2jserver.gameserver.model.zone.type.NpcSpawnTerritory;
/**
* This class manages the zones
* @author durgus
*/
public final class ZoneManager implements DocumentParser
{
private static final Map<String, AbstractZoneSettings> _settings = new HashMap<>();
private final Map<Class<? extends L2ZoneType>, Map<Integer, ? extends L2ZoneType>> _classZones = new HashMap<>();
private final Map<String, NpcSpawnTerritory> _spawnTerritories = new HashMap<>();
private int _lastDynamicId = 300000;
private List<L2ItemInstance> _debugItems;
/**
* Instantiates a new zone manager.
*/
protected ZoneManager()
{
load();
}
/**
* Reload.
*/
public void reload()
{
// Get the world regions
int count = 0;
final L2WorldRegion[][] worldRegions = L2World.getInstance().getWorldRegions();
// Backup old zone settings
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
for (L2ZoneType zone : map.values())
{
if (zone.getSettings() != null)
{
_settings.put(zone.getName(), zone.getSettings());
}
}
}
// Clear zones
for (L2WorldRegion[] worldRegion : worldRegions)
{
for (L2WorldRegion element : worldRegion)
{
element.getZones().clear();
count++;
}
}
GrandBossManager.getInstance().getZones().clear();
LOGGER.info(getClass().getSimpleName() + ": Removed zones in " + count + " regions.");
// Load the zones
load();
// Re-validate all characters in zones
for (L2Object obj : L2World.getInstance().getVisibleObjects())
{
if (obj instanceof L2Character)
{
((L2Character) obj).revalidateZone(true);
}
}
_settings.clear();
}
@Override
public void parseDocument(Document doc, File f)
{
// Get the world regions
final L2WorldRegion[][] worldRegions = L2World.getInstance().getWorldRegions();
NamedNodeMap attrs;
Node attribute;
String zoneName;
int[][] coords;
int zoneId, minZ, maxZ;
String zoneType, zoneShape;
final List<int[]> rs = new ArrayList<>();
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("type");
if (attribute != null)
{
zoneType = attribute.getNodeValue();
}
else
{
LOGGER.warning("ZoneData: Missing type for zone in file: " + f.getName());
continue;
}
attribute = attrs.getNamedItem("id");
if (attribute != null)
{
zoneId = Integer.parseInt(attribute.getNodeValue());
}
else
{
zoneId = zoneType.equalsIgnoreCase("NpcSpawnTerritory") ? 0 : _lastDynamicId++;
}
attribute = attrs.getNamedItem("name");
if (attribute != null)
{
zoneName = attribute.getNodeValue();
}
else
{
zoneName = null;
}
// Check zone name for NpcSpawnTerritory. Must exist and to be unique
if (zoneType.equalsIgnoreCase("NpcSpawnTerritory"))
{
if (zoneName == null)
{
LOGGER.warning("ZoneData: Missing name for NpcSpawnTerritory in file: " + f.getName() + ", skipping zone");
continue;
}
else if (_spawnTerritories.containsKey(zoneName))
{
LOGGER.warning("ZoneData: Name " + zoneName + " already used for another zone, check file: " + f.getName() + ". Skipping zone");
continue;
}
}
minZ = parseInteger(attrs, "minZ");
maxZ = parseInteger(attrs, "maxZ");
zoneType = parseString(attrs, "type");
zoneShape = parseString(attrs, "shape");
// Get the zone shape from xml
L2ZoneForm zoneForm = null;
try
{
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("node".equalsIgnoreCase(cd.getNodeName()))
{
attrs = cd.getAttributes();
int[] point = new int[2];
point[0] = parseInteger(attrs, "X");
point[1] = parseInteger(attrs, "Y");
rs.add(point);
}
}
coords = rs.toArray(new int[rs.size()][2]);
rs.clear();
if ((coords == null) || (coords.length == 0))
{
LOGGER.warning(getClass().getSimpleName() + ": ZoneData: missing data for zone: " + zoneId + " XML 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)
{
zoneForm = new ZoneCuboid(coords[0][0], coords[1][0], coords[0][1], coords[1][1], minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": 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];
}
zoneForm = new ZoneNPoly(aX, aY, minZ, maxZ);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": 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))
{
zoneForm = new ZoneCylinder(coords[0][0], coords[0][1], minZ, maxZ, zoneRad);
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": ZoneData: Bad data for zone: " + zoneId + " in file: " + f.getName());
continue;
}
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": ZoneData: Unknown shape: \"" + zoneShape + "\" for zone: " + zoneId + " in file: " + f.getName());
continue;
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": ZoneData: Failed to load zone " + zoneId + " coordinates: " + e.getMessage(), e);
}
// No further parameters needed, if NpcSpawnTerritory is loading
if (zoneType.equalsIgnoreCase("NpcSpawnTerritory"))
{
_spawnTerritories.put(zoneName, new NpcSpawnTerritory(zoneName, zoneForm));
continue;
}
// Create the zone
Class<?> newZone = null;
Constructor<?> zoneConstructor = null;
L2ZoneType temp;
try
{
newZone = Class.forName("com.l2jserver.gameserver.model.zone.type.L2" + zoneType);
zoneConstructor = newZone.getConstructor(int.class);
temp = (L2ZoneType) zoneConstructor.newInstance(zoneId);
temp.setZone(zoneForm);
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": ZoneData: No such zone type: " + zoneType + " in file: " + f.getName());
continue;
}
// 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 L2ZoneRespawn))
{
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("type");
((L2ZoneRespawn) temp).parseLoc(spawnX, spawnY, spawnZ, val == null ? null : val.getNodeValue());
}
else if ("race".equalsIgnoreCase(cd.getNodeName()) && (temp instanceof L2RespawnZone))
{
attrs = cd.getAttributes();
String race = attrs.getNamedItem("name").getNodeValue();
String point = attrs.getNamedItem("point").getNodeValue();
((L2RespawnZone) temp).addRaceRespawnPoint(race, point);
}
}
if (checkId(zoneId))
{
LOGGER.config(getClass().getSimpleName() + ": 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))
{
worldRegions[x][y].addZone(temp);
}
}
}
}
}
}
}
}
@Override
public final void load()
{
_classZones.clear();
_spawnTerritories.clear();
parseDatapackDirectory("data/zones", false);
parseDatapackDirectory("data/zones/npcSpawnTerritories", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _classZones.size() + " zone classes and " + getSize() + " zones.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _spawnTerritories.size() + " NPC spawn territoriers.");
}
/**
* Gets the size.
* @return the size
*/
public int getSize()
{
int i = 0;
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
i += map.size();
}
return i;
}
/**
* Check id.
* @param id the id
* @return true, if successful
*/
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 <T> the generic type
* @param id the id
* @param zone the zone
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> void addZone(Integer id, T zone)
{
Map<Integer, T> map = (Map<Integer, T>) _classZones.get(zone.getClass());
if (map == null)
{
map = new HashMap<>();
map.put(id, zone);
_classZones.put(zone.getClass(), map);
}
else
{
map.put(id, zone);
}
}
/**
* Returns all zones registered with the ZoneManager. To minimize iteration processing retrieve zones from L2WorldRegion for a specific location instead.
* @return zones
* @see #getAllZones(Class)
*/
@Deprecated
public Collection<L2ZoneType> getAllZones()
{
final List<L2ZoneType> zones = new ArrayList<>();
for (Map<Integer, ? extends L2ZoneType> map : _classZones.values())
{
zones.addAll(map.values());
}
return zones;
}
/**
* Return all zones by class type.
* @param <T> the generic type
* @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 the id
* @return the zone by id
* @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 <T> the generic type
* @param id the id
* @param zoneType the zone type
* @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 the object
* @return zones
*/
public List<L2ZoneType> getZones(L2Object object)
{
return getZones(object.getX(), object.getY(), object.getZ());
}
/**
* Gets the zone.
* @param <T> the generic type
* @param object the object
* @param type the type
* @return zone from where the object is located by type
*/
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 the x
* @param y the y
* @return zones
*/
public List<L2ZoneType> getZones(int x, int y)
{
final L2WorldRegion region = L2World.getInstance().getRegion(x, y);
final List<L2ZoneType> temp = new ArrayList<>();
for (L2ZoneType zone : region.getZones())
{
if (zone.isInsideZone(x, y))
{
temp.add(zone);
}
}
return temp;
}
/**
* Returns all zones from given coordinates.
* @param x the x
* @param y the y
* @param z the z
* @return zones
*/
public List<L2ZoneType> getZones(int x, int y, int z)
{
final L2WorldRegion region = L2World.getInstance().getRegion(x, y);
final List<L2ZoneType> temp = new ArrayList<>();
for (L2ZoneType zone : region.getZones())
{
if (zone.isInsideZone(x, y, z))
{
temp.add(zone);
}
}
return temp;
}
/**
* Gets the zone.
* @param <T> the generic type
* @param x the x
* @param y the y
* @param z the z
* @param type the type
* @return zone from given coordinates
*/
@SuppressWarnings("unchecked")
public <T extends L2ZoneType> T getZone(int x, int y, int z, Class<T> type)
{
final 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;
}
/**
* Get spawm territory by name
* @param name name of territory to search
* @return link to zone form
*/
public NpcSpawnTerritory getSpawnTerritory(String name)
{
return _spawnTerritories.containsKey(name) ? _spawnTerritories.get(name) : null;
}
/**
* Returns all spawm territories from where the object is located
* @param object
* @return zones
*/
public List<NpcSpawnTerritory> getSpawnTerritories(L2Object object)
{
List<NpcSpawnTerritory> temp = new ArrayList<>();
for (NpcSpawnTerritory territory : _spawnTerritories.values())
{
if (territory.isInsideZone(object.getX(), object.getY(), object.getZ()))
{
temp.add(territory);
}
}
return temp;
}
/**
* Gets the arena.
* @param character the character
* @return the arena
*/
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;
}
/**
* Gets the olympiad stadium.
* @param character the character
* @return the olympiad stadium
*/
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> the generic type
* @param obj the obj
* @param type the type
* @return the closest zone
*/
@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 ArrayList<>();
}
return _debugItems;
}
/**
* Remove all debug items from l2world.
*/
public void clearDebugItems()
{
if (_debugItems != null)
{
final Iterator<L2ItemInstance> it = _debugItems.iterator();
while (it.hasNext())
{
final L2ItemInstance item = it.next();
if (item != null)
{
item.decayMe();
}
it.remove();
}
}
}
/**
* Gets the settings.
* @param name the name
* @return the settings
*/
public static AbstractZoneSettings getSettings(String name)
{
return _settings.get(name);
}
/**
* Gets the single instance of ZoneManager.
* @return single instance of ZoneManager
*/
public static final ZoneManager getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ZoneManager _instance = new ZoneManager();
}
}

View File

@ -0,0 +1,568 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.sql.Statement;
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.ThreadPoolManager;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.util.Broadcast;
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;
protected 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;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(UPDATE_PRICE))
{
statement.setLong(1, getPrize());
statement.setLong(2, getPrize());
statement.setInt(3, getId());
statement.execute();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not increase current lottery prize: " + e.getMessage(), e);
}
}
public boolean isSellableTickets()
{
return _isSellingTickets;
}
public boolean isStarted()
{
return _isStarted;
}
private class startLottery implements Runnable
{
protected startLottery()
{
// Do nothing
}
@Override
public void run()
{
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rset = statement.executeQuery(SELECT_LAST_LOTTERY))
{
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();
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));
}
return;
}
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not restore lottery data: " + e.getMessage(), e);
}
if (Config.DEBUG)
{
_log.info("Lottery: Starting ticket sell for lottery #" + getId() + ".");
}
_isSellingTickets = true;
_isStarted = true;
Broadcast.toAllOnlinePlayers("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 (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement 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();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not store new lottery data: " + e.getMessage(), e);
}
}
}
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;
Broadcast.toAllOnlinePlayers(SystemMessage.getSystemMessage(SystemMessageId.LOTTERY_TICKET_SALES_HAVE_BEEN_TEMPORARILY_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;
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(SELECT_LOTTERY_ITEM))
{
statement.setInt(1, getId());
try (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 != Math.round((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++;
}
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could restore lottery data: " + e.getMessage(), e);
}
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.THE_PRIZE_AMOUNT_FOR_THE_WINNER_OF_LOTTERY_S1_IS_S2_ADENA_WE_HAVE_S3_FIRST_PRIZE_WINNERS);
sm.addInt(getId());
sm.addLong(getPrize());
sm.addLong(count1);
Broadcast.toAllOnlinePlayers(sm);
}
else
{
// There are no winners.
sm = SystemMessage.getSystemMessage(SystemMessageId.THE_PRIZE_AMOUNT_FOR_LUCKY_LOTTERY_S1_IS_S2_ADENA_THERE_WAS_NO_FIRST_PRIZE_WINNER_IN_THIS_DRAWING_THEREFORE_THE_JACKPOT_WILL_BE_ADDED_TO_THE_NEXT_DRAWING);
sm.addInt(getId());
sm.addLong(getPrize());
Broadcast.toAllOnlinePlayers(sm);
}
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement 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();
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not store finished lottery data: " + e.getMessage(), e);
}
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 != Math.round((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
};
try (Connection con = L2DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement(SELECT_LOTTERY_TICKET))
{
statement.setInt(1, id);
try (ResultSet rset = statement.executeQuery())
{
if (rset.next())
{
int curenchant = rset.getInt("number1") & enchant;
int curtype2 = rset.getInt("number2") & type2;
if ((curenchant == 0) && (curtype2 == 0))
{
return res;
}
int count = 0;
for (int i = 1; i <= 16; i++)
{
int val = curenchant / 2;
if (val != Math.round((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);
}
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Lottery: Could not check lottery ticket #" + id + ": " + e.getMessage(), e);
}
return res;
}
private static class SingletonHolder
{
protected static final Lottery _instance = new Lottery();
}
}

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change attack time task.
* @author xban1x
*/
public final class FourSepulchersChangeAttackTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(false);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(true);
manager.setIsCoolDownTime(false);
manager.locationShadowSpawns();
manager.spawnMysteriousBox(31921);
manager.spawnMysteriousBox(31922);
manager.spawnMysteriousBox(31923);
manager.spawnMysteriousBox(31924);
if (!manager.isFirstTimeRun())
{
manager.setWarmUpTimeEnd(Calendar.getInstance().getTimeInMillis());
}
long interval = 0;
// say task
if (manager.isFirstTimeRun())
{
for (double min = Calendar.getInstance().get(Calendar.MINUTE); min < manager.getCycleMin(); min++)
{
// looking for next shout time....
if ((min % 5) == 0)// check if min can be divided by 5
{
final Calendar inter = Calendar.getInstance();
inter.set(Calendar.MINUTE, (int) min);
ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersManagerSayTask(), inter.getTimeInMillis() - Calendar.getInstance().getTimeInMillis());
break;
}
}
}
else
{
ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersManagerSayTask(), 5 * 60400);
}
// searching time when attack time will be ended:
// counting difference between time when attack time ends and
// current time
// and then launching change time task
if (manager.isFirstTimeRun())
{
interval = manager.getAttackTimeEnd() - Calendar.getInstance().getTimeInMillis();
}
else
{
interval = Config.FS_TIME_ATTACK * 60000L;
}
manager.setChangeCoolDownTimeTask(ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersChangeCoolDownTimeTask(), interval));
final ScheduledFuture<?> changeAttackTimeTask = manager.getChangeAttackTimeTask();
if (changeAttackTimeTask != null)
{
changeAttackTimeTask.cancel(true);
manager.setChangeAttackTimeTask(null);
}
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change cool down time task.
* @author xban1x
*/
public final class FourSepulchersChangeCoolDownTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(false);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(false);
manager.setIsCoolDownTime(true);
manager.clean();
final Calendar time = Calendar.getInstance();
// one hour = 55th min to 55 min of next hour, so we check for this,
// also check for first launch
if (!manager.isFirstTimeRun() && (Calendar.getInstance().get(Calendar.MINUTE) > manager.getCycleMin()))
{
time.set(Calendar.HOUR, Calendar.getInstance().get(Calendar.HOUR) + 1);
}
time.set(Calendar.MINUTE, manager.getCycleMin());
if (manager.isFirstTimeRun())
{
manager.setIsFirstTimeRun(false);
}
long interval = time.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
manager.setChangeEntryTimeTask(ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersChangeEntryTimeTask(), interval));
final ScheduledFuture<?> changeCoolDownTimeTask = manager.getChangeCoolDownTimeTask();
if (changeCoolDownTimeTask != null)
{
changeCoolDownTimeTask.cancel(true);
manager.setChangeCoolDownTimeTask(null);
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import java.util.Calendar;
import java.util.concurrent.ScheduledFuture;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers change entry time task.
* @author xban1x
*/
public final class FourSepulchersChangeEntryTimeTask implements Runnable
{
@Override
public void run()
{
final FourSepulchersManager manager = FourSepulchersManager.getInstance();
manager.setIsEntryTime(true);
manager.setIsWarmUpTime(false);
manager.setIsAttackTime(false);
manager.setIsCoolDownTime(false);
long interval = 0;
// if this is first launch - search time whFourSepulchersManager_inEntryTime = true;naFourSepulchersManager_inEntryTime = true;maen entry time will be
// ended:
// counting difference between time when entry time ends and current
// time
// and then launching change time task
if (manager.isFirstTimeRun())
{
interval = manager.getEntrytTimeEnd() - Calendar.getInstance().getTimeInMillis();
}
else
{
interval = Config.FS_TIME_ENTRY * 60000L; // else use stupid
// method
}
// launching saying process...
ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersManagerSayTask(), 0);
manager.setChangeWarmUpTimeTask(ThreadPoolManager.getInstance().scheduleEffect(new FourSepulchersChangeWarmUpTimeTask(), interval));
final ScheduledFuture<?> changeEntryTimeTask = manager.getChangeEntryTimeTask();
if (changeEntryTimeTask != null)
{
changeEntryTimeTask.cancel(true);
manager.setChangeEntryTimeTask(null);
}
}
}

View File

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

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import java.util.Calendar;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.instancemanager.FourSepulchersManager;
/**
* Four Sepulchers manager say task.
* @author xban1x
*/
public final class FourSepulchersManagerSayTask implements Runnable
{
@Override
public void run()
{
if (FourSepulchersManager.getInstance().isAttackTime())
{
final Calendar tmp = Calendar.getInstance();
tmp.setTimeInMillis(Calendar.getInstance().getTimeInMillis() - FourSepulchersManager.getInstance().getWarmUpTimeEnd());
if ((tmp.get(Calendar.MINUTE) + 5) < Config.FS_TIME_ATTACK)
{
FourSepulchersManager.getInstance().managerSay((byte) tmp.get(Calendar.MINUTE)); // byte
// because
// minute
// cannot be
// more than
// 59
ThreadPoolManager.getInstance().scheduleGeneral(new FourSepulchersManagerSayTask(), 5 * 60000);
}
// attack time ending chat
else if ((tmp.get(Calendar.MINUTE) + 5) >= Config.FS_TIME_ATTACK)
{
FourSepulchersManager.getInstance().managerSay((byte) 90); // sending a unique id :D
}
}
else if (FourSepulchersManager.getInstance().isEntryTime())
{
FourSepulchersManager.getInstance().managerSay((byte) 0);
}
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import com.l2jserver.gameserver.instancemanager.GrandBossManager;
/**
* @author xban1x
*/
public class GrandBossManagerStoreTask implements Runnable
{
@Override
public void run()
{
GrandBossManager.getInstance().storeMe();
}
}

View File

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

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import com.l2jserver.gameserver.instancemanager.HandysBlockCheckerManager;
/**
* Handys Block Checker penalty remove.
* @author xban1x
*/
public final class PenaltyRemoveTask implements Runnable
{
private final int _objectId;
public PenaltyRemoveTask(int id)
{
_objectId = id;
}
@Override
public void run()
{
HandysBlockCheckerManager.getInstance().removePenalty(_objectId);
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import com.l2jserver.gameserver.instancemanager.WalkingManager;
import com.l2jserver.gameserver.model.actor.L2Npc;
/**
* Task which starts npc movement.
* @author xban1x
*/
public final class StartMovingTask implements Runnable
{
final L2Npc _npc;
final String _routeName;
public StartMovingTask(L2Npc npc, String routeName)
{
_npc = npc;
_routeName = routeName;
}
@Override
public void run()
{
if (_npc != null)
{
WalkingManager.getInstance().startMoving(_npc, _routeName);
}
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2004-2014 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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.tasks;
import com.l2jserver.gameserver.instancemanager.GraciaSeedsManager;
/**
* Task which updates Seed of Destruction state.
* @author xban1x
*/
public final class UpdateSoDStateTask implements Runnable
{
@Override
public void run()
{
final GraciaSeedsManager manager = GraciaSeedsManager.getInstance();
manager.setSoDState(1, true);
manager.updateSodState();
}
}