123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /*
- * Copyright (C) 2004-2015 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.commons.database.pool.impl.ConnectionFactory;
- 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.L2FestivalMonsterInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2FortCommanderInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2GrandBossInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2GuardInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
- import com.l2jserver.gameserver.model.actor.instance.L2RiftInvaderInstance;
- import com.l2jserver.gameserver.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 = ConnectionFactory.getInstance().getConnection();
- Statement s = con.createStatement();
- ResultSet rs = s.executeQuery("SELECT itemId, charId, playerKarma, playerPkKills, nbKills, endTime FROM cursed_weapons"))
- {
- // Retrieve the L2PcInstance from the characters table of the database
- CursedWeapon cw;
- while (rs.next())
- {
- cw = _cursedWeapons.get(rs.getInt("itemId"));
- cw.setPlayerId(rs.getInt("charId"));
- cw.setPlayerKarma(rs.getInt("playerKarma"));
- cw.setPlayerPkKills(rs.getInt("playerPkKills"));
- cw.setNbKills(rs.getInt("nbKills"));
- cw.setEndTime(rs.getLong("endTime"));
- cw.reActivate();
- }
- }
- catch (Exception e)
- {
- _log.log(Level.WARNING, "Could not restore CursedWeapons data: " + e.getMessage(), e);
- }
- }
-
- private final void controlPlayers()
- {
- // TODO: See comments below...
- // This entire for loop should NOT be necessary, since it is already handled by
- // CursedWeapon.endOfLife(). However, if we indeed *need* to duplicate it for safety,
- // then we'd better make sure that it FULLY cleans up inactive cursed weapons!
- // Undesired effects result otherwise, such as player with no zariche but with karma
- // or a lost-child entry in the cursed weapons table, without a corresponding one in items...
-
- // Retrieve the L2PcInstance from the characters table of the database
- try (Connection con = ConnectionFactory.getInstance().getConnection();
- PreparedStatement ps = con.prepareStatement("SELECT owner_id FROM items WHERE item_id=?"))
- {
- for (CursedWeapon cw : _cursedWeapons.values())
- {
- if (cw.isActivated())
- {
- continue;
- }
-
- // Do an item check to be sure that the cursed weapon isn't hold by someone
- 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 L2RiftInvaderInstance) || (attackable instanceof L2FestivalMonsterInstance) || (attackable instanceof L2GuardInstance) || (attackable instanceof L2GrandBossInstance) || (attackable instanceof L2FeedableBeastInstance) || (attackable instanceof L2FortCommanderInstance))
- {
- return;
- }
-
- for (CursedWeapon cw : _cursedWeapons.values())
- {
- if (cw.isActive())
- {
- continue;
- }
-
- if (cw.checkDrop(attackable, player))
- {
- break;
- }
- }
- }
-
- public void activate(L2PcInstance player, L2ItemInstance item)
- {
- CursedWeapon cw = _cursedWeapons.get(item.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.S2_MINUTE_OF_USAGE_TIME_ARE_LEFT_FOR_S1);
- 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 = ConnectionFactory.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();
- }
- }
|