Renamed trunk folder.

This commit is contained in:
MobiusDev
2016-08-14 11:56:36 +00:00
parent 0bb4e57aad
commit 69cbd04d91
19923 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.enums.ChatType;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.announce.Announcement;
import com.l2jmobius.gameserver.model.announce.AnnouncementType;
import com.l2jmobius.gameserver.model.announce.AutoAnnouncement;
import com.l2jmobius.gameserver.model.announce.IAnnouncement;
import com.l2jmobius.gameserver.network.serverpackets.CreatureSay;
/**
* Loads announcements from database.
* @author UnAfraid
*/
public final class AnnouncementsTable
{
private static Logger LOGGER = Logger.getLogger(AnnouncementsTable.class.getName());
private final Map<Integer, IAnnouncement> _announcements = new ConcurrentSkipListMap<>();
protected AnnouncementsTable()
{
load();
}
private void load()
{
_announcements.clear();
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement st = con.createStatement();
ResultSet rset = st.executeQuery("SELECT * FROM announcements"))
{
while (rset.next())
{
final AnnouncementType type = AnnouncementType.findById(rset.getInt("type"));
final Announcement announce;
switch (type)
{
case NORMAL:
case CRITICAL:
{
announce = new Announcement(rset);
break;
}
case AUTO_NORMAL:
case AUTO_CRITICAL:
{
announce = new AutoAnnouncement(rset);
break;
}
default:
{
continue;
}
}
_announcements.put(announce.getId(), announce);
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed loading announcements:", e);
}
}
/**
* Sending all announcements to the player
* @param player
*/
public void showAnnouncements(L2PcInstance player)
{
sendAnnouncements(player, AnnouncementType.NORMAL);
sendAnnouncements(player, AnnouncementType.CRITICAL);
sendAnnouncements(player, AnnouncementType.EVENT);
}
/**
* Sends all announcements to the player by the specified type
* @param player
* @param type
*/
public void sendAnnouncements(L2PcInstance player, AnnouncementType type)
{
for (IAnnouncement announce : _announcements.values())
{
if (announce.isValid() && (announce.getType() == type))
{
player.sendPacket(new CreatureSay(0, //
type == AnnouncementType.CRITICAL ? ChatType.CRITICAL_ANNOUNCE : ChatType.ANNOUNCEMENT, //
player.getName(), announce.getContent()));
}
}
}
/**
* Adds announcement
* @param announce
*/
public void addAnnouncement(IAnnouncement announce)
{
if (announce.storeMe())
{
_announcements.put(announce.getId(), announce);
}
}
/**
* Removes announcement by id
* @param id
* @return {@code true} if announcement exists and was deleted successfully, {@code false} otherwise.
*/
public boolean deleteAnnouncement(int id)
{
final IAnnouncement announce = _announcements.remove(id);
return (announce != null) && announce.deleteMe();
}
/**
* @param id
* @return {@link IAnnouncement} by id
*/
public IAnnouncement getAnnounce(int id)
{
return _announcements.get(id);
}
/**
* @return {@link Collection} containing all announcements
*/
public Collection<IAnnouncement> getAllAnnouncements()
{
return _announcements.values();
}
/**
* @return Single instance of {@link AnnouncementsTable}
*/
public static AnnouncementsTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AnnouncementsTable _instance = new AnnouncementsTable();
}
}

View File

@@ -0,0 +1,316 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* Loads name and access level for all players.
* @version 2005/03/27
*/
public class CharNameTable
{
private static Logger _log = Logger.getLogger(CharNameTable.class.getName());
private final Map<Integer, String> _chars = new ConcurrentHashMap<>();
private final Map<Integer, Integer> _accessLevels = new ConcurrentHashMap<>();
protected CharNameTable()
{
if (Config.CACHE_CHAR_NAMES)
{
loadAll();
}
}
public final void addName(L2PcInstance player)
{
if (player != null)
{
addName(player.getObjectId(), player.getName());
_accessLevels.put(player.getObjectId(), player.getAccessLevel().getLevel());
}
}
private final void addName(int objectId, String name)
{
if (name != null)
{
if (!name.equals(_chars.get(objectId)))
{
_chars.put(objectId, name);
}
}
}
public final void removeName(int objId)
{
_chars.remove(objId);
_accessLevels.remove(objId);
}
public final int getIdByName(String name)
{
if ((name == null) || name.isEmpty())
{
return -1;
}
for (Entry<Integer, String> entry : _chars.entrySet())
{
if (entry.getValue().equalsIgnoreCase(name))
{
return entry.getKey();
}
}
if (Config.CACHE_CHAR_NAMES)
{
return -1;
}
int id = -1;
int accessLevel = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT charId,accesslevel FROM characters WHERE char_name=?"))
{
ps.setString(1, name);
try (ResultSet rs = ps.executeQuery())
{
while (rs.next())
{
id = rs.getInt("charId");
accessLevel = rs.getInt("accesslevel");
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not check existing char name: " + e.getMessage(), e);
}
if (id > 0)
{
_chars.put(id, name);
_accessLevels.put(id, accessLevel);
return id;
}
return -1; // not found
}
public final String getNameById(int id)
{
if (id <= 0)
{
return null;
}
String name = _chars.get(id);
if (name != null)
{
return name;
}
if (Config.CACHE_CHAR_NAMES)
{
return null;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT char_name,accesslevel FROM characters WHERE charId=?"))
{
ps.setInt(1, id);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
name = rset.getString("char_name");
_chars.put(id, name);
_accessLevels.put(id, rset.getInt("accesslevel"));
return name;
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not check existing char id: " + e.getMessage(), e);
}
return null; // not found
}
public final int getAccessLevelById(int objectId)
{
if (getNameById(objectId) != null)
{
return _accessLevels.get(objectId);
}
return 0;
}
public synchronized boolean doesCharNameExist(String name)
{
boolean result = false;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) as count FROM characters WHERE char_name=?"))
{
ps.setString(1, name);
try (ResultSet rs = ps.executeQuery())
{
if (rs.next())
{
result = rs.getInt("count") > 0;
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not check existing charname: " + e.getMessage(), e);
}
return result;
}
public int getAccountCharacterCount(String account)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT COUNT(char_name) as count FROM characters WHERE account_name=?"))
{
ps.setString(1, account);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
return rset.getInt("count");
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "Couldn't retrieve account for id: " + e.getMessage(), e);
}
return 0;
}
public int getLevelById(int objectId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT level FROM characters WHERE charId = ?"))
{
ps.setInt(1, objectId);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
return rset.getInt("level");
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not check existing char count: " + e.getMessage(), e);
}
return 0;
}
public int getClassIdById(int objectId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT classid FROM characters WHERE charId = ?"))
{
ps.setInt(1, objectId);
try (ResultSet rset = ps.executeQuery())
{
if (rset.next())
{
return rset.getInt("classid");
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't retrieve class for id: " + e.getMessage(), e);
}
return 0;
}
public int getClanIdById(int objectId)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT clanId FROM characters WHERE charId = ?"))
{
ps.setInt(1, objectId);
try (ResultSet rset = ps.executeQuery())
{
while (rset.next())
{
return rset.getInt("clanId");
}
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Could not check existing char count: " + e.getMessage(), e);
}
return 0;
}
private void loadAll()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT charId, char_name, accesslevel FROM characters"))
{
while (rs.next())
{
final int id = rs.getInt("charId");
_chars.put(id, rs.getString("char_name"));
_accessLevels.put(id, rs.getInt("accesslevel"));
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't retrieve all char id/name/access: " + e.getMessage(), e);
}
_log.info(getClass().getSimpleName() + ": Loaded " + _chars.size() + " char names.");
}
public static CharNameTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CharNameTable _instance = new CharNameTable();
}
}

View File

@@ -0,0 +1,256 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.xml.impl.NpcData;
import com.l2jmobius.gameserver.data.xml.impl.PetDataTable;
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
import com.l2jmobius.gameserver.model.L2PetData;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance;
import com.l2jmobius.gameserver.model.actor.instance.L2ServitorInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.network.serverpackets.PetItemList;
/**
* @author Nyaran
*/
public class CharSummonTable
{
private static final Logger LOGGER = Logger.getLogger(CharSummonTable.class.getName());
private static final Map<Integer, Integer> _pets = new ConcurrentHashMap<>();
private static final Map<Integer, Set<Integer>> _servitors = new ConcurrentHashMap<>();
// SQL
private static final String INIT_PET = "SELECT ownerId, item_obj_id FROM pets WHERE restore = 'true'";
private static final String INIT_SUMMONS = "SELECT ownerId, summonId FROM character_summons";
private static final String LOAD_SUMMON = "SELECT summonSkillId, summonId, curHp, curMp, time FROM character_summons WHERE ownerId = ?";
private static final String REMOVE_SUMMON = "DELETE FROM character_summons WHERE ownerId = ? and summonId = ?";
private static final String SAVE_SUMMON = "REPLACE INTO character_summons (ownerId,summonId,summonSkillId,curHp,curMp,time) VALUES (?,?,?,?,?,?)";
public Map<Integer, Integer> getPets()
{
return _pets;
}
public Map<Integer, Set<Integer>> getServitors()
{
return _servitors;
}
public void init()
{
if (Config.RESTORE_SERVITOR_ON_RECONNECT)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(INIT_SUMMONS))
{
while (rs.next())
{
_servitors.computeIfAbsent(rs.getInt("ownerId"), k -> ConcurrentHashMap.newKeySet()).add(rs.getInt("summonId"));
}
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Error while loading saved servitor: " + e);
}
}
if (Config.RESTORE_PET_ON_RECONNECT)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery(INIT_PET))
{
while (rs.next())
{
_pets.put(rs.getInt("ownerId"), rs.getInt("item_obj_id"));
}
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Error while loading saved pet: " + e);
}
}
}
public void removeServitor(L2PcInstance activeChar, int summonObjectId)
{
_servitors.computeIfPresent(activeChar.getObjectId(), (k, v) ->
{
v.remove(summonObjectId);
return !v.isEmpty() ? v : null;
});
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(REMOVE_SUMMON))
{
ps.setInt(1, activeChar.getObjectId());
ps.setInt(2, summonObjectId);
ps.execute();
}
catch (SQLException e)
{
LOGGER.warning(getClass().getSimpleName() + ": Summon cannot be removed: " + e);
}
}
public void restorePet(L2PcInstance activeChar)
{
final L2ItemInstance item = activeChar.getInventory().getItemByObjectId(_pets.get(activeChar.getObjectId()));
if (item == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Null pet summoning item for: " + activeChar);
return;
}
final L2PetData petData = PetDataTable.getInstance().getPetDataByItemId(item.getId());
if (petData == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Null pet data for: " + activeChar + " and summoning item: " + item);
return;
}
final L2NpcTemplate npcTemplate = NpcData.getInstance().getTemplate(petData.getNpcId());
if (npcTemplate == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Null pet NPC template for: " + activeChar + " and pet Id:" + petData.getNpcId());
return;
}
final L2PetInstance pet = L2PetInstance.spawnPet(npcTemplate, activeChar, item);
if (pet == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Null pet instance for: " + activeChar + " and pet NPC template:" + npcTemplate);
return;
}
pet.setShowSummonAnimation(true);
pet.setTitle(activeChar.getName());
if (!pet.isRespawned())
{
pet.setCurrentHp(pet.getMaxHp());
pet.setCurrentMp(pet.getMaxMp());
pet.getStat().setExp(pet.getExpForThisLevel());
pet.setCurrentFed(pet.getMaxFed());
}
pet.setRunning();
if (!pet.isRespawned())
{
pet.storeMe();
}
item.setEnchantLevel(pet.getLevel());
activeChar.setPet(pet);
pet.spawnMe(activeChar.getX() + 50, activeChar.getY() + 100, activeChar.getZ());
pet.startFeed();
pet.setFollowStatus(true);
pet.getOwner().sendPacket(new PetItemList(pet.getInventory().getItems()));
pet.broadcastStatusUpdate();
}
public void restoreServitor(L2PcInstance activeChar)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(LOAD_SUMMON))
{
ps.setInt(1, activeChar.getObjectId());
try (ResultSet rs = ps.executeQuery())
{
Skill skill;
while (rs.next())
{
final int summonObjId = rs.getInt("summonId");
final int skillId = rs.getInt("summonSkillId");
final int curHp = rs.getInt("curHp");
final int curMp = rs.getInt("curMp");
final int time = rs.getInt("time");
skill = SkillData.getInstance().getSkill(skillId, activeChar.getSkillLevel(skillId));
if ((skill == null) || !activeChar.hasServitor(summonObjId))
{
removeServitor(activeChar, summonObjId);
return;
}
skill.applyEffects(activeChar, activeChar);
final L2ServitorInstance summon = (L2ServitorInstance) activeChar.getServitor(summonObjId);
summon.setCurrentHp(curHp);
summon.setCurrentMp(curMp);
summon.setLifeTimeRemaining(time);
}
}
}
catch (SQLException e)
{
LOGGER.warning(getClass().getSimpleName() + ": Servitor cannot be restored: " + e);
}
}
public void saveSummon(L2ServitorInstance summon)
{
if ((summon == null) || (summon.getLifeTimeRemaining() <= 0))
{
return;
}
_servitors.computeIfAbsent(summon.getOwner().getObjectId(), k -> ConcurrentHashMap.newKeySet()).add(summon.getObjectId());
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement(SAVE_SUMMON))
{
ps.setInt(1, summon.getOwner().getObjectId());
ps.setInt(2, summon.getObjectId());
ps.setInt(3, summon.getReferenceSkill());
ps.setInt(4, (int) Math.round(summon.getCurrentHp()));
ps.setInt(5, (int) Math.round(summon.getCurrentMp()));
ps.setInt(6, summon.getLifeTimeRemaining());
ps.execute();
}
catch (Exception e)
{
LOGGER.warning(getClass().getSimpleName() + ": Failed to store summon: " + summon + " from " + summon.getOwner() + ", error: " + e);
}
}
public static CharSummonTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CharSummonTable _instance = new CharSummonTable();
}
}

View File

@@ -0,0 +1,490 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.communitybbs.Manager.ForumsBBSManager;
import com.l2jmobius.gameserver.data.xml.impl.ClanHallData;
import com.l2jmobius.gameserver.enums.UserInfoType;
import com.l2jmobius.gameserver.idfactory.IdFactory;
import com.l2jmobius.gameserver.instancemanager.FortManager;
import com.l2jmobius.gameserver.instancemanager.FortSiegeManager;
import com.l2jmobius.gameserver.instancemanager.SiegeManager;
import com.l2jmobius.gameserver.model.ClanPrivilege;
import com.l2jmobius.gameserver.model.ClanWar;
import com.l2jmobius.gameserver.model.ClanWar.ClanWarState;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2ClanMember;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.model.entity.Fort;
import com.l2jmobius.gameserver.model.entity.FortSiege;
import com.l2jmobius.gameserver.model.entity.Siege;
import com.l2jmobius.gameserver.model.events.EventDispatcher;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerClanCreate;
import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerClanDestroy;
import com.l2jmobius.gameserver.model.events.impl.clan.OnClanWarFinish;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.PledgeShowInfoUpdate;
import com.l2jmobius.gameserver.network.serverpackets.PledgeShowMemberListAll;
import com.l2jmobius.gameserver.network.serverpackets.PledgeShowMemberListUpdate;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.util.EnumIntBitmask;
import com.l2jmobius.gameserver.util.Util;
/**
* This class loads the clan related data.
*/
public class ClanTable
{
private static final Logger LOGGER = Logger.getLogger(ClanTable.class.getName());
private final Map<Integer, L2Clan> _clans = new ConcurrentHashMap<>();
protected ClanTable()
{
// forums has to be loaded before clan data, because of last forum id used should have also memo included
if (Config.ENABLE_COMMUNITY_BOARD)
{
ForumsBBSManager.getInstance().initRoot();
}
L2Clan clan;
// Count the clans
int clanCount = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT clan_id FROM clan_data"))
{
while (rs.next())
{
final int clanId = rs.getInt("clan_id");
_clans.put(clanId, new L2Clan(clanId));
clan = getClan(clanId);
if (clan.getDissolvingExpiryTime() != 0)
{
scheduleRemoveClan(clan.getId());
}
clanCount++;
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, "Error restoring ClanTable.", e);
}
LOGGER.info(getClass().getSimpleName() + ": Restored " + clanCount + " clans from the database.");
allianceCheck();
restorewars();
}
/**
* Gets the clans.
* @return the clans
*/
public Collection<L2Clan> getClans()
{
return _clans.values();
}
/**
* Gets the clan count.
* @return the clan count
*/
public int getClanCount()
{
return _clans.size();
}
/**
* @param clanId
* @return
*/
public L2Clan getClan(int clanId)
{
return _clans.get(clanId);
}
public L2Clan getClanByName(String clanName)
{
return getClans().stream().filter(c -> c.getName().equalsIgnoreCase(clanName)).findFirst().orElse(null);
}
/**
* Creates a new clan and store clan info to database
* @param player
* @param clanName
* @return NULL if clan with same name already exists
*/
public L2Clan createClan(L2PcInstance player, String clanName)
{
if (null == player)
{
return null;
}
if (10 > player.getLevel())
{
player.sendPacket(SystemMessageId.YOU_DO_NOT_MEET_THE_CRITERIA_IN_ORDER_TO_CREATE_A_CLAN);
return null;
}
if (0 != player.getClanId())
{
player.sendPacket(SystemMessageId.YOU_HAVE_FAILED_TO_CREATE_A_CLAN);
return null;
}
if (System.currentTimeMillis() < player.getClanCreateExpiryTime())
{
player.sendPacket(SystemMessageId.YOU_MUST_WAIT_10_DAYS_BEFORE_CREATING_A_NEW_CLAN);
return null;
}
if (!Util.isAlphaNumeric(clanName) || (2 > clanName.length()))
{
player.sendPacket(SystemMessageId.CLAN_NAME_IS_INVALID);
return null;
}
if (16 < clanName.length())
{
player.sendPacket(SystemMessageId.CLAN_NAME_S_LENGTH_IS_INCORRECT);
return null;
}
if (null != getClanByName(clanName))
{
// clan name is already taken
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.S1_ALREADY_EXISTS);
sm.addString(clanName);
player.sendPacket(sm);
return null;
}
final L2Clan clan = new L2Clan(IdFactory.getInstance().getNextId(), clanName);
final L2ClanMember leader = new L2ClanMember(clan, player);
clan.setLeader(leader);
leader.setPlayerInstance(player);
clan.store();
player.setClan(clan);
player.setPledgeClass(L2ClanMember.calculatePledgeClass(player));
player.setClanPrivileges(new EnumIntBitmask<>(ClanPrivilege.class, true));
_clans.put(Integer.valueOf(clan.getId()), clan);
// should be update packet only
player.sendPacket(new PledgeShowInfoUpdate(clan));
PledgeShowMemberListAll.sendAllTo(player);
player.sendPacket(new PledgeShowMemberListUpdate(player));
player.sendPacket(SystemMessageId.YOUR_CLAN_HAS_BEEN_CREATED);
player.broadcastUserInfo(UserInfoType.RELATION, UserInfoType.CLAN);
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerClanCreate(player, clan));
return clan;
}
public synchronized void destroyClan(int clanId)
{
final L2Clan clan = getClan(clanId);
if (clan == null)
{
return;
}
clan.broadcastToOnlineMembers(SystemMessage.getSystemMessage(SystemMessageId.CLAN_HAS_DISPERSED));
final int castleId = clan.getCastleId();
if (castleId == 0)
{
for (Siege siege : SiegeManager.getInstance().getSieges())
{
siege.removeSiegeClan(clan);
}
}
final int fortId = clan.getFortId();
if (fortId == 0)
{
for (FortSiege siege : FortSiegeManager.getInstance().getSieges())
{
siege.removeAttacker(clan);
}
}
final ClanHall hall = ClanHallData.getInstance().getClanHallByClan(clan);
if (hall != null)
{
hall.setOwner(null);
}
final L2ClanMember leaderMember = clan.getLeader();
if (leaderMember == null)
{
clan.getWarehouse().destroyAllItems("ClanRemove", null, null);
}
else
{
clan.getWarehouse().destroyAllItems("ClanRemove", clan.getLeader().getPlayerInstance(), null);
}
for (L2ClanMember member : clan.getMembers())
{
clan.removeClanMember(member.getObjectId(), 0);
}
_clans.remove(clanId);
IdFactory.getInstance().releaseId(clanId);
try (Connection con = DatabaseFactory.getInstance().getConnection())
{
try (PreparedStatement ps = con.prepareStatement("DELETE FROM clan_data WHERE clan_id=?"))
{
ps.setInt(1, clanId);
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM clan_privs WHERE clan_id=?"))
{
ps.setInt(1, clanId);
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM clan_skills WHERE clan_id=?"))
{
ps.setInt(1, clanId);
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM clan_subpledges WHERE clan_id=?"))
{
ps.setInt(1, clanId);
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM clan_wars WHERE clan1=? OR clan2=?"))
{
ps.setInt(1, clanId);
ps.setInt(2, clanId);
ps.execute();
}
try (PreparedStatement ps = con.prepareStatement("DELETE FROM clan_notices WHERE clan_id=?"))
{
ps.setInt(1, clanId);
ps.execute();
}
if (castleId != 0)
{
try (PreparedStatement ps = con.prepareStatement("UPDATE castle SET taxPercent = 0 WHERE id = ?"))
{
ps.setInt(1, castleId);
ps.execute();
}
}
if (fortId != 0)
{
final Fort fort = FortManager.getInstance().getFortById(fortId);
if (fort != null)
{
final L2Clan owner = fort.getOwnerClan();
if (clan == owner)
{
fort.removeOwner(true);
}
}
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Error removing clan from DB.", e);
}
// Notify to scripts
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerClanDestroy(leaderMember, clan));
}
public void scheduleRemoveClan(int clanId)
{
ThreadPoolManager.getInstance().scheduleGeneral(() ->
{
if (getClan(clanId) == null)
{
return;
}
if (getClan(clanId).getDissolvingExpiryTime() != 0)
{
destroyClan(clanId);
}
}, Math.max(getClan(clanId).getDissolvingExpiryTime() - System.currentTimeMillis(), 300000));
}
public boolean isAllyExists(String allyName)
{
for (L2Clan clan : getClans())
{
if ((clan.getAllyName() != null) && clan.getAllyName().equalsIgnoreCase(allyName))
{
return true;
}
}
return false;
}
public void storeclanswars(ClanWar war)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("REPLACE INTO clan_wars (clan1, clan2, clan1Kill, clan2Kill, winnerClan, startTime, endTime, state) VALUES(?,?,?,?,?,?,?)"))
{
ps.setInt(1, war.getAttackerClanId());
ps.setInt(2, war.getAttackedClanId());
ps.setInt(3, war.getAttackerKillCount());
ps.setInt(4, war.getAttackedKillCount());
ps.setInt(5, war.getWinnerClanId());
ps.setLong(6, war.getStartTime());
ps.setLong(7, war.getEndTime());
ps.setInt(8, war.getState().ordinal());
ps.execute();
}
catch (Exception e)
{
LOGGER.severe("Error storing clan wars data: " + e);
}
}
public void deleteclanswars(int clanId1, int clanId2)
{
final L2Clan clan1 = ClanTable.getInstance().getClan(clanId1);
final L2Clan clan2 = ClanTable.getInstance().getClan(clanId2);
EventDispatcher.getInstance().notifyEventAsync(new OnClanWarFinish(clan1, clan2));
clan1.deleteWar(clan2.getId());
clan2.deleteWar(clan1.getId());
clan1.broadcastClanStatus();
clan2.broadcastClanStatus();
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM clan_wars WHERE clan1=? AND clan2=?"))
{
ps.setInt(1, clanId1);
ps.setInt(2, clanId2);
ps.execute();
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Error removing clan wars data.", e);
}
}
private void restorewars()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rset = statement.executeQuery("SELECT clan1, clan2, clan1Kill, clan2Kill, winnerClan, startTime, endTime, state FROM clan_wars"))
{
while (rset.next())
{
final L2Clan attacker = getClan(rset.getInt("clan1"));
final L2Clan attacked = getClan(rset.getInt("clan2"));
if ((attacker != null) && (attacked != null))
{
final ClanWarState state = ClanWarState.values()[rset.getInt("state")];
final ClanWar clanWar = new ClanWar(attacker, attacked, rset.getInt("clan1Kill"), rset.getInt("clan2Kill"), rset.getInt("winnerClan"), rset.getLong("startTime"), rset.getLong("endTime"), state);
attacker.addWar(attacked.getId(), clanWar);
attacked.addWar(attacker.getId(), clanWar);
}
else
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Restorewars one of clans is null attacker:" + attacker + " attacked:" + attacked);
}
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Error restoring clan wars data.", e);
}
}
/**
* Check for nonexistent alliances
*/
private void allianceCheck()
{
for (L2Clan clan : _clans.values())
{
final int allyId = clan.getAllyId();
if ((allyId != 0) && (clan.getId() != allyId))
{
if (!_clans.containsKey(allyId))
{
clan.setAllyId(0);
clan.setAllyName(null);
clan.changeAllyCrest(0, true);
clan.updateClanInDB();
LOGGER.info(getClass().getSimpleName() + ": Removed alliance from clan: " + clan);
}
}
}
}
public List<L2Clan> getClanAllies(int allianceId)
{
final List<L2Clan> clanAllies = new ArrayList<>();
if (allianceId != 0)
{
for (L2Clan clan : _clans.values())
{
if ((clan != null) && (clan.getAllyId() == allianceId))
{
clanAllies.add(clan);
}
}
}
return clanAllies;
}
public void shutdown()
{
for (L2Clan clan : _clans.values())
{
clan.updateInDB();
}
}
public static ClanTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClanTable _instance = new ClanTable();
}
}

View File

@@ -0,0 +1,219 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.L2Crest;
import com.l2jmobius.gameserver.model.L2Crest.CrestType;
/**
* Loads and saves crests from database.
* @author NosBit
*/
public final class CrestTable
{
private static final Logger LOGGER = Logger.getLogger(CrestTable.class.getName());
private final Map<Integer, L2Crest> _crests = new ConcurrentHashMap<>();
private final AtomicInteger _nextId = new AtomicInteger(1);
protected CrestTable()
{
load();
}
public synchronized void load()
{
_crests.clear();
final Set<Integer> crestsInUse = new HashSet<>();
for (L2Clan clan : ClanTable.getInstance().getClans())
{
if (clan.getCrestId() != 0)
{
crestsInUse.add(clan.getCrestId());
}
if (clan.getCrestLargeId() != 0)
{
crestsInUse.add(clan.getCrestLargeId());
}
if (clan.getAllyCrestId() != 0)
{
crestsInUse.add(clan.getAllyCrestId());
}
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = statement.executeQuery("SELECT `crest_id`, `data`, `type` FROM `crests` ORDER BY `crest_id` DESC"))
{
while (rs.next())
{
final int id = rs.getInt("crest_id");
if (_nextId.get() <= id)
{
_nextId.set(id + 1);
}
// delete all unused crests except the last one we dont want to reuse
// a crest id because client will display wrong crest if its reused
if (!crestsInUse.contains(id) && (id != (_nextId.get() - 1)))
{
rs.deleteRow();
continue;
}
final byte[] data = rs.getBytes("data");
final CrestType crestType = CrestType.getById(rs.getInt("type"));
if (crestType != null)
{
_crests.put(id, new L2Crest(id, data, crestType));
}
else
{
LOGGER.warning("Unknown crest type found in database. Type:" + rs.getInt("type"));
}
}
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, "There was an error while loading crests from database:", e);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _crests.size() + " Crests.");
for (L2Clan clan : ClanTable.getInstance().getClans())
{
if ((clan.getCrestId() != 0) && (getCrest(clan.getCrestId()) == null))
{
LOGGER.info("Removing non-existent crest for clan " + clan.getName() + " [" + clan.getId() + "], crestId:" + clan.getCrestId());
clan.setCrestId(0);
clan.changeClanCrest(0);
}
if ((clan.getCrestLargeId() != 0) && (getCrest(clan.getCrestLargeId()) == null))
{
LOGGER.info("Removing non-existent large crest for clan " + clan.getName() + " [" + clan.getId() + "], crestLargeId:" + clan.getCrestLargeId());
clan.setCrestLargeId(0);
clan.changeLargeCrest(0);
}
if ((clan.getAllyCrestId() != 0) && (getCrest(clan.getAllyCrestId()) == null))
{
LOGGER.info("Removing non-existent ally crest for clan " + clan.getName() + " [" + clan.getId() + "], allyCrestId:" + clan.getAllyCrestId());
clan.setAllyCrestId(0);
clan.changeAllyCrest(0, true);
}
}
}
/**
* @param crestId The crest id
* @return {@code L2Crest} if crest is found, {@code null} if crest was not found.
*/
public L2Crest getCrest(int crestId)
{
return _crests.get(crestId);
}
/**
* Creates a {@code L2Crest} object and inserts it in database and cache.
* @param data
* @param crestType
* @return {@code L2Crest} on success, {@code null} on failure.
*/
public L2Crest createCrest(byte[] data, CrestType crestType)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("INSERT INTO `crests`(`crest_id`, `data`, `type`) VALUES(?, ?, ?)"))
{
final L2Crest crest = new L2Crest(getNextId(), data, crestType);
statement.setInt(1, crest.getId());
statement.setBytes(2, crest.getData());
statement.setInt(3, crest.getType().getId());
statement.executeUpdate();
_crests.put(crest.getId(), crest);
return crest;
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, "There was an error while saving crest in database:", e);
}
return null;
}
/**
* Removes crest from database and cache.
* @param crestId the id of crest to be removed.
*/
public void removeCrest(int crestId)
{
_crests.remove(crestId);
// avoid removing last crest id we dont want to lose index...
// because client will display wrong crest if its reused
if (crestId == (_nextId.get() - 1))
{
return;
}
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement statement = con.prepareStatement("DELETE FROM `crests` WHERE `crest_id` = ?"))
{
statement.setInt(1, crestId);
statement.executeUpdate();
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, "There was an error while deleting crest from database:", e);
}
}
/**
* @return The next crest id.
*/
public int getNextId()
{
return _nextId.getAndIncrement();
}
public static CrestTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CrestTable _instance = new CrestTable();
}
}

View File

@@ -0,0 +1,447 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.LoginServerThread;
import com.l2jmobius.gameserver.enums.PrivateStoreType;
import com.l2jmobius.gameserver.model.L2ManufactureItem;
import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.TradeItem;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.holders.SellBuffHolder;
import com.l2jmobius.gameserver.network.client.ConnectionState;
import com.l2jmobius.gameserver.network.client.L2GameClient;
public class OfflineTradersTable
{
private static Logger LOGGER = Logger.getLogger(OfflineTradersTable.class.getName());
// SQL DEFINITIONS
private static final String SAVE_OFFLINE_STATUS = "INSERT INTO character_offline_trade (`charId`,`time`,`type`,`title`) VALUES (?,?,?,?)";
private static final String SAVE_ITEMS = "INSERT INTO character_offline_trade_items (`charId`,`item`,`count`,`price`) VALUES (?,?,?,?)";
private static final String CLEAR_OFFLINE_TABLE = "DELETE FROM character_offline_trade";
private static final String CLEAR_OFFLINE_TABLE_PLAYER = "DELETE FROM character_offline_trade WHERE `charId`=?";
private static final String CLEAR_OFFLINE_TABLE_ITEMS = "DELETE FROM character_offline_trade_items";
private static final String CLEAR_OFFLINE_TABLE_ITEMS_PLAYER = "DELETE FROM character_offline_trade_items WHERE `charId`=?";
private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade";
private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?";
public void storeOffliners()
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement stm1 = con.prepareStatement(CLEAR_OFFLINE_TABLE);
PreparedStatement stm2 = con.prepareStatement(CLEAR_OFFLINE_TABLE_ITEMS);
PreparedStatement stm3 = con.prepareStatement(SAVE_OFFLINE_STATUS);
PreparedStatement stm_items = con.prepareStatement(SAVE_ITEMS))
{
stm1.execute();
stm2.execute();
con.setAutoCommit(false); // avoid halfway done
for (L2PcInstance pc : L2World.getInstance().getPlayers())
{
try
{
if ((pc.getPrivateStoreType() != PrivateStoreType.NONE) && ((pc.getClient() == null) || pc.getClient().isDetached()))
{
stm3.setInt(1, pc.getObjectId()); // Char Id
stm3.setLong(2, pc.getOfflineStartTime());
stm3.setInt(3, pc.isSellingBuffs() ? 9 : pc.getPrivateStoreType().getId()); // store type
String title = null;
switch (pc.getPrivateStoreType())
{
case BUY:
{
if (!Config.OFFLINE_TRADE_ENABLE)
{
continue;
}
title = pc.getBuyList().getTitle();
for (TradeItem i : pc.getBuyList().getItems())
{
stm_items.setInt(1, pc.getObjectId());
stm_items.setInt(2, i.getItem().getId());
stm_items.setLong(3, i.getCount());
stm_items.setLong(4, i.getPrice());
stm_items.executeUpdate();
stm_items.clearParameters();
}
break;
}
case SELL:
case PACKAGE_SELL:
{
if (!Config.OFFLINE_TRADE_ENABLE)
{
continue;
}
title = pc.getSellList().getTitle();
if (pc.isSellingBuffs())
{
for (SellBuffHolder holder : pc.getSellingBuffs())
{
stm_items.setInt(1, pc.getObjectId());
stm_items.setInt(2, holder.getSkillId());
stm_items.setLong(3, 0);
stm_items.setLong(4, holder.getPrice());
stm_items.executeUpdate();
stm_items.clearParameters();
}
}
else
{
for (TradeItem i : pc.getSellList().getItems())
{
stm_items.setInt(1, pc.getObjectId());
stm_items.setInt(2, i.getObjectId());
stm_items.setLong(3, i.getCount());
stm_items.setLong(4, i.getPrice());
stm_items.executeUpdate();
stm_items.clearParameters();
}
}
break;
}
case MANUFACTURE:
{
if (!Config.OFFLINE_CRAFT_ENABLE)
{
continue;
}
title = pc.getStoreName();
for (L2ManufactureItem i : pc.getManufactureItems().values())
{
stm_items.setInt(1, pc.getObjectId());
stm_items.setInt(2, i.getRecipeId());
stm_items.setLong(3, 0);
stm_items.setLong(4, i.getCost());
stm_items.executeUpdate();
stm_items.clearParameters();
}
break;
}
}
stm3.setString(4, title);
stm3.executeUpdate();
stm3.clearParameters();
con.commit(); // flush
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while saving offline trader: " + pc.getObjectId() + " " + e, e);
}
}
LOGGER.info(getClass().getSimpleName() + ": Offline traders stored.");
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while saving offline traders: " + e, e);
}
}
public void restoreOfflineTraders()
{
LOGGER.info(getClass().getSimpleName() + ": Loading offline traders...");
int nTraders = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement stm = con.createStatement();
ResultSet rs = stm.executeQuery(LOAD_OFFLINE_STATUS))
{
while (rs.next())
{
final long time = rs.getLong("time");
if (Config.OFFLINE_MAX_DAYS > 0)
{
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(time);
cal.add(Calendar.DAY_OF_YEAR, Config.OFFLINE_MAX_DAYS);
if (cal.getTimeInMillis() <= System.currentTimeMillis())
{
continue;
}
}
final int typeId = rs.getInt("type");
boolean isSellBuff = false;
if (typeId == 9)
{
isSellBuff = true;
}
final PrivateStoreType type = isSellBuff ? PrivateStoreType.PACKAGE_SELL : PrivateStoreType.findById(typeId);
if (type == null)
{
LOGGER.warning(getClass().getSimpleName() + ": PrivateStoreType with id " + rs.getInt("type") + " could not be found.");
continue;
}
if (type == PrivateStoreType.NONE)
{
continue;
}
L2PcInstance player = null;
try
{
final L2GameClient client = new L2GameClient();
client.setDetached(true);
player = L2PcInstance.load(rs.getInt("charId"));
client.setActiveChar(player);
player.setOnlineStatus(true, false);
client.setAccountName(player.getAccountNamePlayer());
client.setConnectionState(ConnectionState.IN_GAME);
player.setClient(client);
player.setOfflineStartTime(time);
if (isSellBuff)
{
player.setIsSellingBuffs(true);
}
player.spawnMe(player.getX(), player.getY(), player.getZ());
LoginServerThread.getInstance().addGameServerLogin(player.getAccountName(), client);
try (PreparedStatement stm_items = con.prepareStatement(LOAD_OFFLINE_ITEMS))
{
stm_items.setInt(1, player.getObjectId());
try (ResultSet items = stm_items.executeQuery())
{
switch (type)
{
case BUY:
{
while (items.next())
{
if (player.getBuyList().addItemByItemId(items.getInt(2), items.getLong(3), items.getLong(4)) == null)
{
continue;
// throw new NullPointerException();
}
}
player.getBuyList().setTitle(rs.getString("title"));
break;
}
case SELL:
case PACKAGE_SELL:
{
if (player.isSellingBuffs())
{
while (items.next())
{
player.getSellingBuffs().add(new SellBuffHolder(items.getInt("item"), items.getLong("price")));
}
}
else
{
while (items.next())
{
if (player.getSellList().addItem(items.getInt(2), items.getLong(3), items.getLong(4)) == null)
{
continue;
// throw new NullPointerException();
}
}
}
player.getSellList().setTitle(rs.getString("title"));
player.getSellList().setPackaged(type == PrivateStoreType.PACKAGE_SELL);
break;
}
case MANUFACTURE:
{
while (items.next())
{
player.getManufactureItems().put(items.getInt(2), new L2ManufactureItem(items.getInt(2), items.getLong(4)));
}
player.setStoreName(rs.getString("title"));
break;
}
}
}
}
player.sitDown();
if (Config.OFFLINE_SET_NAME_COLOR)
{
player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR);
}
player.setPrivateStoreType(type);
player.setOnlineStatus(true, true);
player.restoreEffects();
player.broadcastUserInfo();
nTraders++;
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e);
if (player != null)
{
player.deleteMe();
}
}
}
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + nTraders + " offline trader(s)");
if (!Config.STORE_OFFLINE_TRADE_IN_REALTIME)
{
try (Statement stm1 = con.createStatement())
{
stm1.execute(CLEAR_OFFLINE_TABLE);
stm1.execute(CLEAR_OFFLINE_TABLE_ITEMS);
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while loading offline traders: ", e);
}
}
public static synchronized void onTransaction(L2PcInstance trader, boolean finished, boolean firstCall)
{
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement stm1 = con.prepareStatement(CLEAR_OFFLINE_TABLE_ITEMS_PLAYER);
PreparedStatement stm2 = con.prepareStatement(CLEAR_OFFLINE_TABLE_PLAYER);
PreparedStatement stm3 = con.prepareStatement(SAVE_ITEMS);
PreparedStatement stm4 = con.prepareStatement(SAVE_OFFLINE_STATUS))
{
String title = null;
stm1.setInt(1, trader.getObjectId()); // Char Id
stm1.execute();
stm1.close();
// Trade is done - clear info
if (finished)
{
stm2.setInt(1, trader.getObjectId()); // Char Id
stm2.execute();
stm2.close();
}
else
{
try
{
if ((trader.getClient() == null) || trader.getClient().isDetached())
{
switch (trader.getPrivateStoreType())
{
case BUY:
{
if (firstCall)
{
title = trader.getBuyList().getTitle();
}
for (TradeItem i : trader.getBuyList().getItems())
{
stm3.setInt(1, trader.getObjectId());
stm3.setInt(2, i.getItem().getId());
stm3.setLong(3, i.getCount());
stm3.setLong(4, i.getPrice());
stm3.executeUpdate();
stm3.clearParameters();
}
break;
}
case SELL:
case PACKAGE_SELL:
{
if (firstCall)
{
title = trader.getSellList().getTitle();
}
for (TradeItem i : trader.getSellList().getItems())
{
stm3.setInt(1, trader.getObjectId());
stm3.setInt(2, i.getObjectId());
stm3.setLong(3, i.getCount());
stm3.setLong(4, i.getPrice());
stm3.executeUpdate();
stm3.clearParameters();
}
break;
}
case MANUFACTURE:
{
if (firstCall)
{
title = trader.getStoreName();
}
for (L2ManufactureItem i : trader.getManufactureItems().values())
{
stm3.setInt(1, trader.getObjectId());
stm3.setInt(2, i.getRecipeId());
stm3.setLong(3, 0);
stm3.setLong(4, i.getCost());
stm3.executeUpdate();
stm3.clearParameters();
}
break;
}
}
stm3.close();
if (firstCall)
{
stm4.setInt(1, trader.getObjectId()); // Char Id
stm4.setLong(2, trader.getOfflineStartTime());
stm4.setInt(3, trader.getPrivateStoreType().getId()); // store type
stm4.setString(4, title);
stm4.executeUpdate();
stm4.clearParameters();
stm4.close();
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline trader: " + trader.getObjectId() + " " + e, e);
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "OfflineTradersTable[storeTradeItems()]: Error while saving offline traders: " + e, e);
}
}
/**
* Gets the single instance of OfflineTradersTable.
* @return single instance of OfflineTradersTable
*/
public static OfflineTradersTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final OfflineTradersTable _instance = new OfflineTradersTable();
}
}

View File

@@ -0,0 +1,115 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.xml.impl.PetDataTable;
public class PetNameTable
{
private static Logger LOGGER = Logger.getLogger(PetNameTable.class.getName());
public static PetNameTable getInstance()
{
return SingletonHolder._instance;
}
public boolean doesPetNameExist(String name, int petNpcId)
{
boolean result = true;
try (Connection con = DatabaseFactory.getInstance().getConnection();
PreparedStatement ps = con.prepareStatement("SELECT name FROM pets p, items i WHERE p.item_obj_id = i.object_id AND name=? AND i.item_id IN (?)"))
{
ps.setString(1, name);
final StringBuilder cond = new StringBuilder();
if (!cond.toString().isEmpty())
{
cond.append(", ");
}
cond.append(PetDataTable.getInstance().getPetItemsByNpc(petNpcId));
ps.setString(2, cond.toString());
try (ResultSet rs = ps.executeQuery())
{
result = rs.next();
}
}
catch (SQLException e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Could not check existing petname:" + e.getMessage(), e);
}
return result;
}
public boolean isValidPetName(String name)
{
boolean result = true;
if (!isAlphaNumeric(name))
{
return result;
}
Pattern pattern;
try
{
pattern = Pattern.compile(Config.PET_NAME_TEMPLATE);
}
catch (PatternSyntaxException e) // case of illegal pattern
{
LOGGER.warning(getClass().getSimpleName() + ": Pet name pattern of config is wrong!");
pattern = Pattern.compile(".*");
}
final Matcher regexp = pattern.matcher(name);
if (!regexp.matches())
{
result = false;
}
return result;
}
private boolean isAlphaNumeric(String text)
{
boolean result = true;
final char[] chars = text.toCharArray();
for (int i = 0; i < chars.length; i++)
{
if (!Character.isLetterOrDigit(chars[i]))
{
result = false;
break;
}
}
return result;
}
private static class SingletonHolder
{
protected static final PetNameTable _instance = new PetNameTable();
}
}

View File

@@ -0,0 +1,92 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* @author Nyaran
*/
public class SummonEffectsTable
{
/** Servitors **/
// Map tree
// -> key: charObjectId, value: classIndex Map
// --> key: classIndex, value: servitors Map
// ---> key: servitorSkillId, value: Effects list
private final Map<Integer, Map<Integer, Map<Integer, List<SummonEffect>>>> _servitorEffects = new HashMap<>();
public Map<Integer, Map<Integer, Map<Integer, List<SummonEffect>>>> getServitorEffectsOwner()
{
return _servitorEffects;
}
public Map<Integer, List<SummonEffect>> getServitorEffects(L2PcInstance owner)
{
final Map<Integer, Map<Integer, List<SummonEffect>>> servitorMap = _servitorEffects.get(owner.getObjectId());
if (servitorMap == null)
{
return null;
}
return servitorMap.get(owner.getClassIndex());
}
/** Pets **/
private final Map<Integer, List<SummonEffect>> _petEffects = new HashMap<>(); // key: petItemObjectId, value: Effects list
public Map<Integer, List<SummonEffect>> getPetEffects()
{
return _petEffects;
}
public static class SummonEffect
{
Skill _skill;
int _effectCurTime;
public SummonEffect(Skill skill, int effectCurTime)
{
_skill = skill;
_effectCurTime = effectCurTime;
}
public Skill getSkill()
{
return _skill;
}
public int getEffectCurTime()
{
return _effectCurTime;
}
}
public static SummonEffectsTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SummonEffectsTable _instance = new SummonEffectsTable();
}
}

View File

@@ -0,0 +1,179 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.data.xml.impl.SkillData;
import com.l2jmobius.gameserver.model.actor.L2Summon;
public class SummonSkillsTable
{
private static Logger LOGGER = Logger.getLogger(SummonSkillsTable.class.getName());
private final Map<Integer, Map<Integer, L2PetSkillLearn>> _skillTrees = new HashMap<>();
protected SummonSkillsTable()
{
load();
}
public void load()
{
_skillTrees.clear();
int count = 0;
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT templateId, minLvl, skillId, skillLvl FROM pets_skills"))
{
while (rs.next())
{
final int npcId = rs.getInt("templateId");
Map<Integer, L2PetSkillLearn> skillTree = _skillTrees.get(npcId);
if (skillTree == null)
{
skillTree = new HashMap<>();
_skillTrees.put(npcId, skillTree);
}
final int id = rs.getInt("skillId");
final int lvl = rs.getInt("skillLvl");
skillTree.put(SkillData.getSkillHashCode(id, lvl + 1), new L2PetSkillLearn(id, lvl, rs.getInt("minLvl")));
count++;
}
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Error while loading pet skill tree:", e);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + count + " skills.");
}
public int getAvailableLevel(L2Summon cha, int skillId)
{
int lvl = 0;
if (!_skillTrees.containsKey(cha.getId()))
{
LOGGER.warning(getClass().getSimpleName() + ": Pet id " + cha.getId() + " does not have any skills assigned.");
return lvl;
}
final Collection<L2PetSkillLearn> skills = _skillTrees.get(cha.getId()).values();
for (L2PetSkillLearn temp : skills)
{
if (temp.getId() != skillId)
{
continue;
}
if (temp.getLevel() == 0)
{
if (cha.getLevel() < 70)
{
lvl = cha.getLevel() / 10;
if (lvl <= 0)
{
lvl = 1;
}
}
else
{
lvl = 7 + ((cha.getLevel() - 70) / 5);
}
// formula usable for skill that have 10 or more skill levels
final int maxLvl = SkillData.getInstance().getMaxLevel(temp.getId());
if (lvl > maxLvl)
{
lvl = maxLvl;
}
break;
}
if ((temp.getMinLevel() <= cha.getLevel()) && (temp.getLevel() > lvl))
{
lvl = temp.getLevel();
}
}
return lvl;
}
public List<Integer> getAvailableSkills(L2Summon cha)
{
final List<Integer> skillIds = new ArrayList<>();
if (!_skillTrees.containsKey(cha.getId()))
{
LOGGER.warning(getClass().getSimpleName() + ": Pet id " + cha.getId() + " does not have any skills assigned.");
return skillIds;
}
final Collection<L2PetSkillLearn> skills = _skillTrees.get(cha.getId()).values();
for (L2PetSkillLearn temp : skills)
{
if (skillIds.contains(temp.getId()))
{
continue;
}
skillIds.add(temp.getId());
}
return skillIds;
}
public static final class L2PetSkillLearn
{
private final int _id;
private final int _level;
private final int _minLevel;
public L2PetSkillLearn(int id, int lvl, int minLvl)
{
_id = id;
_level = lvl;
_minLevel = minLvl;
}
public int getId()
{
return _id;
}
public int getLevel()
{
return _level;
}
public int getMinLevel()
{
return _minLevel;
}
}
public static SummonSkillsTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SummonSkillsTable _instance = new SummonSkillsTable();
}
}

View File

@@ -0,0 +1,123 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.sql.impl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.gameserver.model.L2TeleportLocation;
public class TeleportLocationTable
{
private static Logger LOGGER = Logger.getLogger(TeleportLocationTable.class.getName());
private final Map<Integer, L2TeleportLocation> _teleports = new HashMap<>();
protected TeleportLocationTable()
{
reloadAll();
}
public void reloadAll()
{
_teleports.clear();
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id, loc_x, loc_y, loc_z, price, fornoble, itemId FROM teleport"))
{
L2TeleportLocation teleport;
while (rs.next())
{
teleport = new L2TeleportLocation();
teleport.setTeleId(rs.getInt("id"));
teleport.setLocX(rs.getInt("loc_x"));
teleport.setLocY(rs.getInt("loc_y"));
teleport.setLocZ(rs.getInt("loc_z"));
teleport.setPrice(rs.getInt("price"));
teleport.setIsForNoble(rs.getInt("fornoble") == 1);
teleport.setItemId(rs.getInt("itemId"));
_teleports.put(teleport.getTeleId(), teleport);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _teleports.size() + " Teleport Location Templates.");
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Error loading Teleport Table.", e);
}
if (Config.CUSTOM_TELEPORT_TABLE)
{
int cTeleCount = _teleports.size();
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement s = con.createStatement();
ResultSet rs = s.executeQuery("SELECT id, loc_x, loc_y, loc_z, price, fornoble, itemId FROM custom_teleport"))
{
L2TeleportLocation teleport;
while (rs.next())
{
teleport = new L2TeleportLocation();
teleport.setTeleId(rs.getInt("id"));
teleport.setLocX(rs.getInt("loc_x"));
teleport.setLocY(rs.getInt("loc_y"));
teleport.setLocZ(rs.getInt("loc_z"));
teleport.setPrice(rs.getInt("price"));
teleport.setIsForNoble(rs.getInt("fornoble") == 1);
teleport.setItemId(rs.getInt("itemId"));
_teleports.put(teleport.getTeleId(), teleport);
}
cTeleCount = _teleports.size() - cTeleCount;
if (cTeleCount > 0)
{
LOGGER.info(getClass().getSimpleName() + ": Loaded " + cTeleCount + " Custom Teleport Location Templates.");
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while creating custom teleport table " + e.getMessage(), e);
}
}
}
/**
* @param id
* @return
*/
public L2TeleportLocation getTemplate(int id)
{
return _teleports.get(id);
}
public static TeleportLocationTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final TeleportLocationTable _instance = new TeleportLocationTable();
}
}

View File

@@ -0,0 +1,113 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.holders.RangeAbilityPointsHolder;
/**
* @author UnAfraid
*/
public final class AbilityPointsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(AbilityPointsData.class.getName());
private final List<RangeAbilityPointsHolder> _points = new ArrayList<>();
protected AbilityPointsData()
{
load();
}
@Override
public synchronized void load()
{
_points.clear();
parseDatapackFile("config/AbilityPoints.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _points.size() + " range fees.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("points".equalsIgnoreCase(d.getNodeName()))
{
final NamedNodeMap attrs = d.getAttributes();
final int from = parseInteger(attrs, "from");
final int to = parseInteger(attrs, "to");
final int costs = parseInteger(attrs, "costs");
_points.add(new RangeAbilityPointsHolder(from, to, costs));
}
}
}
}
}
public RangeAbilityPointsHolder getHolder(int points)
{
for (RangeAbilityPointsHolder holder : _points)
{
if ((holder.getMin() <= points) && (holder.getMax() >= points))
{
return holder;
}
}
return null;
}
public long getPrice(int points)
{
points++; // for next point
final RangeAbilityPointsHolder holder = getHolder(points);
if (holder == null)
{
final RangeAbilityPointsHolder prevHolder = getHolder(points - 1);
if (prevHolder != null)
{
return prevHolder.getSP();
}
// No data found
return points >= 13 ? 1_000_000_000 : points >= 9 ? 750_000_000 : points >= 5 ? 500_000_000 : 250_000_000;
}
return holder.getSP();
}
public static AbilityPointsData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AbilityPointsData _instance = new AbilityPointsData();
}
}

View File

@@ -0,0 +1,96 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.ActionDataHolder;
import com.l2jmobius.gameserver.model.StatsSet;
/**
* @author UnAfraid
*/
public class ActionData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ActionData.class.getName());
private final Map<Integer, ActionDataHolder> _actionData = new HashMap<>();
private final Map<Integer, Integer> _actionSkillsData = new HashMap<>(); // skillId, actionId
protected ActionData()
{
load();
}
@Override
public void load()
{
_actionData.clear();
_actionSkillsData.clear();
parseDatapackFile("data/ActionData.xml");
_actionData.values().stream().filter(h -> h.getHandler().equals("PetSkillUse") || h.getHandler().equals("ServitorSkillUse")).forEach(h -> _actionSkillsData.put(h.getOptionId(), h.getId()));
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _actionData.size() + " player actions.");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "action", actionNode ->
{
final ActionDataHolder holder = new ActionDataHolder(new StatsSet(parseAttributes(actionNode)));
_actionData.put(holder.getId(), holder);
}));
}
/**
* @param id
* @return the ActionDataHolder for specified id
*/
public ActionDataHolder getActionData(int id)
{
return _actionData.get(id);
}
/**
* @param skillId
* @return the actionId corresponding to the skillId or -1 if no actionId is found for the specified skill.
*/
public int getSkillActionId(int skillId)
{
return _actionSkillsData.getOrDefault(skillId, -1);
}
/**
* Gets the single instance of ActionData.
* @return single instance of ActionData
*/
public static final ActionData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ActionData _instance = new ActionData();
}
}

View File

@@ -0,0 +1,355 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.L2AccessLevel;
import com.l2jmobius.gameserver.model.L2AdminCommandAccessRight;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
/**
* Loads administrator access levels and commands.
* @author UnAfraid
*/
public final class AdminData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(AdminData.class.getName());
private final Map<Integer, L2AccessLevel> _accessLevels = new HashMap<>();
private final Map<String, L2AdminCommandAccessRight> _adminCommandAccessRights = new HashMap<>();
private final Map<L2PcInstance, Boolean> _gmList = new ConcurrentHashMap<>();
private int _highestLevel = 0;
protected AdminData()
{
load();
}
@Override
public synchronized void load()
{
_accessLevels.clear();
_adminCommandAccessRights.clear();
parseDatapackFile("config/AccessLevels.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _accessLevels.size() + " Access Levels.");
parseDatapackFile("config/AdminCommands.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _adminCommandAccessRights.size() + " Access Commands.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
Node attr;
StatsSet set;
L2AccessLevel level;
L2AdminCommandAccessRight command;
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 ("access".equalsIgnoreCase(d.getNodeName()))
{
set = new StatsSet();
attrs = d.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
attr = attrs.item(i);
set.set(attr.getNodeName(), attr.getNodeValue());
}
level = new L2AccessLevel(set);
if (level.getLevel() > _highestLevel)
{
_highestLevel = level.getLevel();
}
_accessLevels.put(level.getLevel(), level);
}
else if ("admin".equalsIgnoreCase(d.getNodeName()))
{
set = new StatsSet();
attrs = d.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
attr = attrs.item(i);
set.set(attr.getNodeName(), attr.getNodeValue());
}
command = new L2AdminCommandAccessRight(set);
_adminCommandAccessRights.put(command.getAdminCommand(), command);
}
}
}
}
}
/**
* Returns the access level by characterAccessLevel.
* @param accessLevelNum as int
* @return the access level instance by char access level
*/
public L2AccessLevel getAccessLevel(int accessLevelNum)
{
if (accessLevelNum < 0)
{
return _accessLevels.get(-1);
}
return _accessLevels.get(accessLevelNum);
}
/**
* Gets the master access level.
* @return the master access level
*/
public L2AccessLevel getMasterAccessLevel()
{
return _accessLevels.get(_highestLevel);
}
/**
* Checks for access level.
* @param id the id
* @return {@code true}, if successful, {@code false} otherwise
*/
public boolean hasAccessLevel(int id)
{
return _accessLevels.containsKey(id);
}
/**
* Checks for access.
* @param adminCommand the admin command
* @param accessLevel the access level
* @return {@code true}, if successful, {@code false} otherwise
*/
public boolean hasAccess(String adminCommand, L2AccessLevel accessLevel)
{
L2AdminCommandAccessRight acar = _adminCommandAccessRights.get(adminCommand);
if (acar == null)
{
// Trying to avoid the spam for next time when the gm would try to use the same command
if ((accessLevel.getLevel() > 0) && (accessLevel.getLevel() == _highestLevel))
{
acar = new L2AdminCommandAccessRight(adminCommand, true, accessLevel.getLevel());
_adminCommandAccessRights.put(adminCommand, acar);
LOGGER.info(getClass().getSimpleName() + ": No rights defined for admin command " + adminCommand + " auto setting accesslevel: " + accessLevel.getLevel() + " !");
}
else
{
LOGGER.info(getClass().getSimpleName() + ": No rights defined for admin command " + adminCommand + " !");
return false;
}
}
return acar.hasAccess(accessLevel);
}
/**
* Require confirm.
* @param command the command
* @return {@code true}, if the command require confirmation, {@code false} otherwise
*/
public boolean requireConfirm(String command)
{
final L2AdminCommandAccessRight acar = _adminCommandAccessRights.get(command);
if (acar == null)
{
LOGGER.info(getClass().getSimpleName() + ": No rights defined for admin command " + command + ".");
return false;
}
return acar.getRequireConfirm();
}
/**
* Gets the all GMs.
* @param includeHidden the include hidden
* @return the all GMs
*/
public List<L2PcInstance> getAllGms(boolean includeHidden)
{
final List<L2PcInstance> tmpGmList = new ArrayList<>();
for (Entry<L2PcInstance, Boolean> entry : _gmList.entrySet())
{
if (includeHidden || !entry.getValue())
{
tmpGmList.add(entry.getKey());
}
}
return tmpGmList;
}
/**
* Gets the all GM names.
* @param includeHidden the include hidden
* @return the all GM names
*/
public List<String> getAllGmNames(boolean includeHidden)
{
final List<String> tmpGmList = new ArrayList<>();
for (Entry<L2PcInstance, Boolean> entry : _gmList.entrySet())
{
if (!entry.getValue())
{
tmpGmList.add(entry.getKey().getName());
}
else if (includeHidden)
{
tmpGmList.add(entry.getKey().getName() + " (invis)");
}
}
return tmpGmList;
}
/**
* Add a L2PcInstance player to the Set _gmList.
* @param player the player
* @param hidden the hidden
*/
public void addGm(L2PcInstance player, boolean hidden)
{
_gmList.put(player, hidden);
}
/**
* Delete a GM.
* @param player the player
*/
public void deleteGm(L2PcInstance player)
{
_gmList.remove(player);
}
/**
* GM will be displayed on clients GM list.
* @param player the player
*/
public void showGm(L2PcInstance player)
{
if (_gmList.containsKey(player))
{
_gmList.put(player, false);
}
}
/**
* GM will no longer be displayed on clients GM list.
* @param player the player
*/
public void hideGm(L2PcInstance player)
{
if (_gmList.containsKey(player))
{
_gmList.put(player, true);
}
}
/**
* Checks if is GM online.
* @param includeHidden the include hidden
* @return true, if is GM online
*/
public boolean isGmOnline(boolean includeHidden)
{
for (Entry<L2PcInstance, Boolean> entry : _gmList.entrySet())
{
if (includeHidden || !entry.getValue())
{
return true;
}
}
return false;
}
/**
* Send list to player.
* @param player the player
*/
public void sendListToPlayer(L2PcInstance player)
{
if (isGmOnline(player.isGM()))
{
player.sendPacket(SystemMessageId.GM_LIST);
for (String name : getAllGmNames(player.isGM()))
{
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.GM_C1);
sm.addString(name);
player.sendPacket(sm);
}
}
else
{
player.sendPacket(SystemMessageId.THERE_ARE_NO_GMS_CURRENTLY_VISIBLE_IN_THE_PUBLIC_LIST_AS_THEY_MAY_BE_PERFORMING_OTHER_FUNCTIONS_AT_THE_MOMENT);
}
}
/**
* Broadcast to GMs.
* @param packet the packet
*/
public void broadcastToGMs(IClientOutgoingPacket packet)
{
for (L2PcInstance gm : getAllGms(true))
{
gm.sendPacket(packet);
}
}
/**
* Broadcast message to GMs.
* @param message the message
* @return the message that was broadcasted
*/
public String broadcastMessageToGMs(String message)
{
for (L2PcInstance gm : getAllGms(true))
{
gm.sendMessage(message);
}
return message;
}
/**
* Gets the single instance of AdminTable.
* @return AccessLevels: the one and only instance of this class<br>
*/
public static AdminData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AdminData _instance = new AdminData();
}
}

View File

@@ -0,0 +1,141 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.alchemy.AlchemyCraftData;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
/**
* @author Sdw
*/
public class AlchemyData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(AlchemyData.class.getName());
private final Map<Integer, AlchemyCraftData> _alchemy = new HashMap<>();
protected AlchemyData()
{
load();
}
@Override
public void load()
{
_alchemy.clear();
parseDatapackFile("data/AlchemyData.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _alchemy.size() + " alchemy craft skills.");
}
@Override
public void parseDocument(Document doc, File f)
{
StatsSet set;
Node att;
NamedNodeMap attrs;
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 ("skill".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
final AlchemyCraftData alchemyCraft = new AlchemyCraftData(set);
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("ingredients".equalsIgnoreCase(c.getNodeName()))
{
for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("item".equalsIgnoreCase(b.getNodeName()))
{
final int ingId = Integer.parseInt(b.getAttributes().getNamedItem("id").getNodeValue());
final int ingCount = Integer.parseInt(b.getAttributes().getNamedItem("count").getNodeValue());
alchemyCraft.addIngredient(new ItemHolder(ingId, ingCount));
}
}
}
else if ("production".equalsIgnoreCase(c.getNodeName()))
{
for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("item".equalsIgnoreCase(b.getNodeName()))
{
final String type = b.getAttributes().getNamedItem("type").getNodeValue();
final int prodId = Integer.parseInt(b.getAttributes().getNamedItem("id").getNodeValue());
final int prodCount = Integer.parseInt(b.getAttributes().getNamedItem("count").getNodeValue());
if (type.equalsIgnoreCase("ON_SUCCESS"))
{
alchemyCraft.setProductionSuccess(new ItemHolder(prodId, prodCount));
}
else if (type.equalsIgnoreCase("ON_FAILURE"))
{
alchemyCraft.setProductionFailure(new ItemHolder(prodId, prodCount));
}
}
}
}
}
final int skillHashCode = SkillData.getSkillHashCode(set.getInt("id"), set.getInt("level"));
_alchemy.put(skillHashCode, alchemyCraft);
}
}
}
}
}
public AlchemyCraftData getCraftData(int skillId, int skillLevel)
{
return _alchemy.get(SkillData.getSkillHashCode(skillId, skillLevel));
}
/**
* Gets the single instance of AlchemyData.
* @return single instance of AlchemyData
*/
public static final AlchemyData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AlchemyData _instance = new AlchemyData();
}
}

View File

@@ -0,0 +1,159 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.enums.Race;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.items.appearance.AppearanceStone;
import com.l2jmobius.gameserver.model.items.appearance.AppearanceTargetType;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
/**
* @author UnAfraid
*/
public class AppearanceItemData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(AppearanceItemData.class.getName());
private final Map<Integer, AppearanceStone> _stones = new HashMap<>();
protected AppearanceItemData()
{
load();
}
@Override
public void load()
{
parseDatapackFile("data/AppearanceStones.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _stones.size() + " Stones");
//@formatter:off
/*
for (L2Item item : ItemTable.getInstance().getAllItems())
{
if ((item == null) || !item.getName().contains("Appearance Stone"))
{
continue;
}
if (item.getName().contains("Pack") || _stones.containsKey(item.getId()))
{
continue;
}
System.out.println("Unhandled appearance stone: " + item);
}
*/
//@formatter:on
}
@Override
public void parseDocument(Document doc, File f)
{
StatsSet set;
Node att;
NamedNodeMap attrs;
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 ("appearance_stone".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
final AppearanceStone stone = new AppearanceStone(set);
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
switch (c.getNodeName())
{
case "grade":
{
final CrystalType type = CrystalType.valueOf(c.getTextContent());
stone.addCrystalType(type);
break;
}
case "targetType":
{
final AppearanceTargetType type = AppearanceTargetType.valueOf(c.getTextContent());
stone.addTargetType(type);
break;
}
case "bodyPart":
{
final int part = ItemTable.SLOTS.get(c.getTextContent());
stone.addBodyPart(part);
break;
}
case "race":
{
final Race race = Race.valueOf(c.getTextContent());
stone.addRace(race);
break;
}
case "raceNot":
{
final Race raceNot = Race.valueOf(c.getTextContent());
stone.addRaceNot(raceNot);
break;
}
}
}
_stones.put(stone.getId(), stone);
}
}
}
}
}
public AppearanceStone getStone(int stone)
{
return _stones.get(stone);
}
/**
* Gets the single instance of AppearanceItemData.
* @return single instance of AppearanceItemData
*/
public static AppearanceItemData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final AppearanceItemData _instance = new AppearanceItemData();
}
}

View File

@@ -0,0 +1,186 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.L2ArmorSet;
import com.l2jmobius.gameserver.model.holders.ArmorsetSkillHolder;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.stats.BaseStats;
/**
* Loads armor set bonuses.
* @author godson, Luno, UnAfraid
*/
public final class ArmorSetsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ArmorSetsData.class.getName());
private final Map<Integer, L2ArmorSet> _armorSets = new HashMap<>();
private final Map<Integer, List<L2ArmorSet>> _armorSetItems = new HashMap<>();
protected ArmorSetsData()
{
load();
}
@Override
public void load()
{
_armorSets.clear();
parseDatapackDirectory("data/stats/armorsets", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _armorSets.size() + " Armor sets.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node setNode = n.getFirstChild(); setNode != null; setNode = setNode.getNextSibling())
{
if ("set".equalsIgnoreCase(setNode.getNodeName()))
{
final int id = parseInteger(setNode.getAttributes(), "id");
final int minimumPieces = parseInteger(setNode.getAttributes(), "minimumPieces", 0);
final boolean isVisual = parseBoolean(setNode.getAttributes(), "visual", false);
final L2ArmorSet set = new L2ArmorSet(id, minimumPieces, isVisual);
if (_armorSets.putIfAbsent(id, set) != null)
{
LOGGER.warning("Duplicate set entry with id: " + id + " in file: " + f.getName());
}
for (Node innerSetNode = setNode.getFirstChild(); innerSetNode != null; innerSetNode = innerSetNode.getNextSibling())
{
switch (innerSetNode.getNodeName())
{
case "requiredItems":
{
forEach(innerSetNode, b -> "item".equals(b.getNodeName()), node ->
{
final NamedNodeMap attrs = node.getAttributes();
final int itemId = parseInteger(attrs, "id");
final L2Item item = ItemTable.getInstance().getTemplate(itemId);
if (item == null)
{
LOGGER.warning("Attempting to register non existing required item: " + itemId + " to a set: " + f.getName());
}
else if (!set.addRequiredItem(itemId))
{
LOGGER.warning("Attempting to register duplicate required item " + item + " to a set: " + f.getName());
}
});
break;
}
case "optionalItems":
{
forEach(innerSetNode, b -> "item".equals(b.getNodeName()), node ->
{
final NamedNodeMap attrs = node.getAttributes();
final int itemId = parseInteger(attrs, "id");
final L2Item item = ItemTable.getInstance().getTemplate(itemId);
if (item == null)
{
LOGGER.warning("Attempting to register non existing optional item: " + itemId + " to a set: " + f.getName());
}
else if (!set.addOptionalItem(itemId))
{
LOGGER.warning("Attempting to register duplicate optional item " + item + " to a set: " + f.getName());
}
});
break;
}
case "skills":
{
forEach(innerSetNode, b -> "skill".equals(b.getNodeName()), node ->
{
final NamedNodeMap attrs = node.getAttributes();
final int skillId = parseInteger(attrs, "id");
final int skillLevel = parseInteger(attrs, "level");
final int minPieces = parseInteger(attrs, "minimumPieces", set.getMinimumPieces());
final int minEnchant = parseInteger(attrs, "minimumEnchant", 0);
final boolean isOptional = parseBoolean(attrs, "optional", false);
set.addSkill(new ArmorsetSkillHolder(skillId, skillLevel, minPieces, minEnchant, isOptional));
});
break;
}
case "stats":
{
forEach(innerSetNode, b -> "stat".equals(b.getNodeName()), node ->
{
final NamedNodeMap attrs = node.getAttributes();
set.addStatsBonus(parseEnum(attrs, BaseStats.class, "type"), parseInteger(attrs, "val"));
});
break;
}
}
}
Stream.concat(set.getRequiredItems().stream(), set.getOptionalItems().stream()).forEach(itemHolder -> _armorSetItems.computeIfAbsent(itemHolder, key -> new ArrayList<>()).add(set));
}
}
}
}
}
/**
* @param setId the set id that is attached to a set
* @return the armor set associated to the given item id
*/
public L2ArmorSet getSet(int setId)
{
return _armorSets.get(setId);
}
/**
* @param itemId the item id that is attached to a set
* @return the armor set associated to the given item id
*/
public List<L2ArmorSet> getSets(int itemId)
{
return _armorSetItems.getOrDefault(itemId, Collections.emptyList());
}
/**
* Gets the single instance of ArmorSetsData
* @return single instance of ArmorSetsData
*/
public static ArmorSetsData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ArmorSetsData _instance = new ArmorSetsData();
}
}

View File

@@ -0,0 +1,166 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.Race;
import com.l2jmobius.gameserver.enums.Sex;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.beautyshop.BeautyData;
import com.l2jmobius.gameserver.model.beautyshop.BeautyItem;
/**
* @author Sdw
*/
public final class BeautyShopData implements IGameXmlReader
{
private final Map<Race, Map<Sex, BeautyData>> _beautyList = new HashMap<>();
private final Map<Sex, BeautyData> _beautyData = new HashMap<>();
protected BeautyShopData()
{
load();
}
@Override
public synchronized void load()
{
_beautyList.clear();
_beautyData.clear();
parseDatapackFile("data/BeautyShop.xml");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
StatsSet set;
Node att;
Race race = null;
Sex sex = null;
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 ("race".equalsIgnoreCase(d.getNodeName()))
{
att = d.getAttributes().getNamedItem("type");
if (att != null)
{
race = parseEnum(att, Race.class);
}
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("sex".equalsIgnoreCase(b.getNodeName()))
{
att = b.getAttributes().getNamedItem("type");
if (att != null)
{
sex = parseEnum(att, Sex.class);
}
final BeautyData beautyData = new BeautyData();
for (Node a = b.getFirstChild(); a != null; a = a.getNextSibling())
{
if ("hair".equalsIgnoreCase(a.getNodeName()))
{
attrs = a.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
final BeautyItem hair = new BeautyItem(set);
for (Node g = a.getFirstChild(); g != null; g = g.getNextSibling())
{
if ("color".equalsIgnoreCase(g.getNodeName()))
{
attrs = g.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
hair.addColor(set);
}
}
beautyData.addHair(hair);
}
else if ("face".equalsIgnoreCase(a.getNodeName()))
{
attrs = a.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
final BeautyItem face = new BeautyItem(set);
beautyData.addFace(face);
}
}
_beautyData.put(sex, beautyData);
}
}
_beautyList.put(race, _beautyData);
}
}
}
}
}
public boolean hasBeautyData(Race race, Sex sex)
{
return _beautyList.containsKey(race) && _beautyList.get(race).containsKey(sex);
}
public BeautyData getBeautyData(Race race, Sex sex)
{
if (_beautyList.containsKey(race))
{
return _beautyList.get(race).get(sex);
}
return null;
}
public static BeautyShopData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final BeautyShopData _instance = new BeautyShopData();
}
}

View File

@@ -0,0 +1,194 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.io.FileFilter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.database.DatabaseFactory;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.file.filter.NumericNameFilter;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.buylist.L2BuyList;
import com.l2jmobius.gameserver.model.buylist.Product;
import com.l2jmobius.gameserver.model.items.L2Item;
/**
* Loads buy lists for NPCs.
* @author NosBit
*/
public final class BuyListData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(BuyListData.class.getName());
private final Map<Integer, L2BuyList> _buyLists = new HashMap<>();
private static final FileFilter NUMERIC_FILTER = new NumericNameFilter();
protected BuyListData()
{
load();
}
@Override
public synchronized void load()
{
_buyLists.clear();
parseDatapackDirectory("data/buylists", false);
if (Config.CUSTOM_BUYLIST_LOAD)
{
parseDatapackDirectory("data/buylists/custom", false);
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _buyLists.size() + " BuyLists.");
try (Connection con = DatabaseFactory.getInstance().getConnection();
Statement statement = con.createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM `buylists`"))
{
while (rs.next())
{
final int buyListId = rs.getInt("buylist_id");
final int itemId = rs.getInt("item_id");
final long count = rs.getLong("count");
final long nextRestockTime = rs.getLong("next_restock_time");
final L2BuyList buyList = getBuyList(buyListId);
if (buyList == null)
{
LOGGER.warning("BuyList found in database but not loaded from xml! BuyListId: " + buyListId);
continue;
}
final Product product = buyList.getProductByItemId(itemId);
if (product == null)
{
LOGGER.warning("ItemId found in database but not loaded from xml! BuyListId: " + buyListId + " ItemId: " + itemId);
continue;
}
if (count < product.getMaxCount())
{
product.setCount(count);
product.restartRestockTask(nextRestockTime);
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Failed to load buyList data from database.", e);
}
}
@Override
public void parseDocument(Document doc, File f)
{
try
{
final int buyListId = Integer.parseInt(f.getName().replaceAll(".xml", ""));
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equalsIgnoreCase(node.getNodeName()))
{
final L2BuyList buyList = new L2BuyList(buyListId);
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
{
if ("item".equalsIgnoreCase(list_node.getNodeName()))
{
int itemId = -1;
long price = -1;
long restockDelay = -1;
long count = -1;
final NamedNodeMap attrs = list_node.getAttributes();
Node attr = attrs.getNamedItem("id");
itemId = Integer.parseInt(attr.getNodeValue());
attr = attrs.getNamedItem("price");
if (attr != null)
{
price = Long.parseLong(attr.getNodeValue());
}
attr = attrs.getNamedItem("restock_delay");
if (attr != null)
{
restockDelay = Long.parseLong(attr.getNodeValue());
}
attr = attrs.getNamedItem("count");
if (attr != null)
{
count = Long.parseLong(attr.getNodeValue());
}
final L2Item item = ItemTable.getInstance().getTemplate(itemId);
if (item != null)
{
buyList.addProduct(new Product(buyList.getListId(), item, price, restockDelay, count));
}
else
{
LOGGER.warning("Item not found. BuyList:" + buyList.getListId() + " ItemID:" + itemId + " File:" + f.getName());
}
}
else if ("npcs".equalsIgnoreCase(list_node.getNodeName()))
{
for (Node npcs_node = list_node.getFirstChild(); npcs_node != null; npcs_node = npcs_node.getNextSibling())
{
if ("npc".equalsIgnoreCase(npcs_node.getNodeName()))
{
buyList.addAllowedNpc(Integer.parseInt(npcs_node.getTextContent()));
}
}
}
}
_buyLists.put(buyList.getListId(), buyList);
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Failed to load buyList data from xml File:" + f.getName(), e);
}
}
@Override
public FileFilter getCurrentFileFilter()
{
return NUMERIC_FILTER;
}
public L2BuyList getBuyList(int listId)
{
return _buyLists.get(listId);
}
public static BuyListData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final BuyListData _instance = new BuyListData();
}
}

View File

@@ -0,0 +1,148 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.CastleSide;
import com.l2jmobius.gameserver.enums.SiegeGuardType;
import com.l2jmobius.gameserver.model.holders.CastleSpawnHolder;
import com.l2jmobius.gameserver.model.holders.SiegeGuardHolder;
/**
* @author St3eT
*/
public final class CastleData implements IGameXmlReader
{
private final Map<Integer, List<CastleSpawnHolder>> _spawns = new HashMap<>();
private static final Map<Integer, List<SiegeGuardHolder>> _siegeGuards = new HashMap<>();
protected CastleData()
{
load();
}
@Override
public void load()
{
_spawns.clear();
_siegeGuards.clear();
parseDatapackDirectory("data/residences/castles", true);
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node listNode = doc.getFirstChild(); listNode != null; listNode = listNode.getNextSibling())
{
if ("list".equals(listNode.getNodeName()))
{
for (Node castleNode = listNode.getFirstChild(); castleNode != null; castleNode = castleNode.getNextSibling())
{
if ("castle".equals(castleNode.getNodeName()))
{
final int castleId = parseInteger(castleNode.getAttributes(), "id");
for (Node tpNode = castleNode.getFirstChild(); tpNode != null; tpNode = tpNode.getNextSibling())
{
final List<CastleSpawnHolder> spawns = new ArrayList<>();
if ("spawns".equals(tpNode.getNodeName()))
{
for (Node npcNode = tpNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
if ("npc".equals(npcNode.getNodeName()))
{
final NamedNodeMap np = npcNode.getAttributes();
final int npcId = parseInteger(np, "id");
final CastleSide side = parseEnum(np, CastleSide.class, "castleSide", CastleSide.NEUTRAL);
final int x = parseInteger(np, "x");
final int y = parseInteger(np, "y");
final int z = parseInteger(np, "z");
final int heading = parseInteger(np, "heading");
spawns.add(new CastleSpawnHolder(npcId, side, x, y, z, heading));
}
}
_spawns.put(castleId, spawns);
}
else if ("siegeGuards".equals(tpNode.getNodeName()))
{
final List<SiegeGuardHolder> guards = new ArrayList<>();
for (Node npcNode = tpNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
if ("guard".equals(npcNode.getNodeName()))
{
final NamedNodeMap np = npcNode.getAttributes();
final int itemId = parseInteger(np, "itemId");
final SiegeGuardType type = parseEnum(tpNode.getAttributes(), SiegeGuardType.class, "type");
final boolean stationary = parseBoolean(np, "stationary", false);
final int npcId = parseInteger(np, "npcId");
final int npcMaxAmount = parseInteger(np, "npcMaxAmount");
guards.add(new SiegeGuardHolder(castleId, itemId, type, stationary, npcId, npcMaxAmount));
}
}
getSiegeGuards().put(castleId, guards);
}
}
}
}
}
}
}
public final List<CastleSpawnHolder> getSpawnsForSide(int castleId, CastleSide side)
{
return _spawns.getOrDefault(castleId, Collections.emptyList()).stream().filter(s -> s.getSide() == side).collect(Collectors.toList());
}
public final List<SiegeGuardHolder> getSiegeGuardsForCastle(int castleId)
{
return _siegeGuards.getOrDefault(castleId, Collections.emptyList());
}
public final Map<Integer, List<SiegeGuardHolder>> getSiegeGuards()
{
return _siegeGuards;
}
/**
* Gets the single instance of CastleData.
* @return single instance of CastleData
*/
public static CastleData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CastleData _instance = new CastleData();
}
}

View File

@@ -0,0 +1,126 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.CategoryType;
/**
* Loads the category data with Class or NPC IDs.
* @author NosBit, xban1x
*/
public final class CategoryData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(CategoryData.class.getName());
private final Map<CategoryType, Set<Integer>> _categories = new HashMap<>();
protected CategoryData()
{
load();
}
@Override
public void load()
{
_categories.clear();
parseDatapackFile("data/CategoryData.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _categories.size() + " Categories.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equalsIgnoreCase(node.getNodeName()))
{
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
{
if ("category".equalsIgnoreCase(list_node.getNodeName()))
{
final NamedNodeMap attrs = list_node.getAttributes();
final CategoryType categoryType = CategoryType.findByName(attrs.getNamedItem("name").getNodeValue());
if (categoryType == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Can't find category by name: " + attrs.getNamedItem("name").getNodeValue());
continue;
}
final Set<Integer> ids = new HashSet<>();
for (Node category_node = list_node.getFirstChild(); category_node != null; category_node = category_node.getNextSibling())
{
if ("id".equalsIgnoreCase(category_node.getNodeName()))
{
ids.add(Integer.parseInt(category_node.getTextContent()));
}
}
_categories.put(categoryType, ids);
}
}
}
}
}
/**
* Checks if ID is in category.
* @param type The category type
* @param id The id to be checked
* @return {@code true} if id is in category, {@code false} if id is not in category or category was not found
*/
public boolean isInCategory(CategoryType type, int id)
{
final Set<Integer> category = getCategoryByType(type);
if (category == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Can't find category type: " + type);
return false;
}
return category.contains(id);
}
/**
* Gets the category by category type.
* @param type The category type
* @return A {@code Set} containing all the IDs in category if category is found, {@code null} if category was not found
*/
public Set<Integer> getCategoryByType(CategoryType type)
{
return _categories.get(type);
}
public static CategoryData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CategoryData _instance = new CategoryData();
}
}

View File

@@ -0,0 +1,212 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.ClanHallGrade;
import com.l2jmobius.gameserver.enums.ClanHallType;
import com.l2jmobius.gameserver.model.L2Clan;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.entity.ClanHall;
import com.l2jmobius.gameserver.model.holders.ClanHallTeleportHolder;
/**
* @author St3eT
*/
public final class ClanHallData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ClanHallData.class.getName());
private static final Map<Integer, ClanHall> _clanHalls = new HashMap<>();
protected ClanHallData()
{
load();
}
@Override
public void load()
{
parseDatapackDirectory("data/residences/clanHalls", true);
LOGGER.info(getClass().getSimpleName() + ": Succesfully loaded " + _clanHalls.size() + " Clan Halls.");
}
@Override
public void parseDocument(Document doc, File f)
{
final List<L2DoorInstance> doors = new ArrayList<>();
final List<Integer> npcs = new ArrayList<>();
final List<ClanHallTeleportHolder> teleports = new ArrayList<>();
final StatsSet params = new StatsSet();
for (Node listNode = doc.getFirstChild(); listNode != null; listNode = listNode.getNextSibling())
{
if ("list".equals(listNode.getNodeName()))
{
for (Node clanHallNode = listNode.getFirstChild(); clanHallNode != null; clanHallNode = clanHallNode.getNextSibling())
{
if ("clanHall".equals(clanHallNode.getNodeName()))
{
params.set("id", parseInteger(clanHallNode.getAttributes(), "id"));
params.set("name", parseString(clanHallNode.getAttributes(), "name", "None"));
params.set("grade", parseEnum(clanHallNode.getAttributes(), ClanHallGrade.class, "grade", ClanHallGrade.GRADE_NONE));
params.set("type", parseEnum(clanHallNode.getAttributes(), ClanHallType.class, "type", ClanHallType.OTHER));
for (Node tpNode = clanHallNode.getFirstChild(); tpNode != null; tpNode = tpNode.getNextSibling())
{
switch (tpNode.getNodeName())
{
case "auction":
{
final NamedNodeMap at = tpNode.getAttributes();
params.set("minBid", parseInteger(at, "minBid"));
params.set("lease", parseInteger(at, "lease"));
params.set("deposit", parseInteger(at, "deposit"));
break;
}
case "npcs":
{
for (Node npcNode = tpNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
if ("npc".equals(npcNode.getNodeName()))
{
final NamedNodeMap np = npcNode.getAttributes();
final int npcId = parseInteger(np, "id");
npcs.add(npcId);
}
}
params.set("npcList", npcs);
break;
}
case "doorlist":
{
for (Node npcNode = tpNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
if ("door".equals(npcNode.getNodeName()))
{
final NamedNodeMap np = npcNode.getAttributes();
final int doorId = parseInteger(np, "id");
final L2DoorInstance door = DoorData.getInstance().getDoor(doorId);
if (door != null)
{
doors.add(door);
}
}
}
params.set("doorList", doors);
break;
}
case "teleportList":
{
for (Node npcNode = tpNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
if ("teleport".equals(npcNode.getNodeName()))
{
final NamedNodeMap np = npcNode.getAttributes();
final int npcStringId = parseInteger(np, "npcStringId");
final int x = parseInteger(np, "x");
final int y = parseInteger(np, "y");
final int z = parseInteger(np, "z");
final int minFunctionLevel = parseInteger(np, "minFunctionLevel");
final int cost = parseInteger(np, "cost");
teleports.add(new ClanHallTeleportHolder(npcStringId, x, y, z, minFunctionLevel, cost));
}
}
params.set("teleportList", teleports);
break;
}
case "ownerRestartPoint":
{
final NamedNodeMap ol = tpNode.getAttributes();
params.set("owner_loc", new Location(parseInteger(ol, "x"), parseInteger(ol, "y"), parseInteger(ol, "z")));
break;
}
case "banishPoint":
{
final NamedNodeMap bl = tpNode.getAttributes();
params.set("banish_loc", new Location(parseInteger(bl, "x"), parseInteger(bl, "y"), parseInteger(bl, "z")));
break;
}
}
}
}
}
}
}
_clanHalls.put(params.getInt("id"), new ClanHall(params));
}
public ClanHall getClanHallById(int clanHallId)
{
return _clanHalls.get(clanHallId);
}
public Collection<ClanHall> getClanHalls()
{
return _clanHalls.values();
}
public ClanHall getClanHallByNpcId(int npcId)
{
return _clanHalls.values().stream().filter(ch -> ch.getNpcs().contains(npcId)).findFirst().orElse(null);
}
public ClanHall getClanHallByClan(L2Clan clan)
{
return _clanHalls.values().stream().filter(ch -> ch.getOwner() == clan).findFirst().orElse(null);
}
public ClanHall getClanHallByDoorId(int doorId)
{
final L2DoorInstance door = DoorData.getInstance().getDoor(doorId);
return _clanHalls.values().stream().filter(ch -> ch.getDoors().contains(door)).findFirst().orElse(null);
}
public List<ClanHall> getFreeAuctionableHall()
{
return _clanHalls.values().stream().filter(ch -> (ch.getType() == ClanHallType.AUCTIONABLE) && (ch.getOwner() == null)).sorted(Comparator.comparingInt(ClanHall::getResidenceId)).collect(Collectors.toList());
}
/**
* Gets the single instance of ClanHallData.
* @return single instance of ClanHallData
*/
public static ClanHallData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClanHallData _instance = new ClanHallData();
}
}

View File

@@ -0,0 +1,168 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.enums.ClanRewardType;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.pledge.ClanRewardBonus;
/**
* @author UnAfraid
*/
public class ClanRewardData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ClanRewardData.class.getName());
private final Map<ClanRewardType, List<ClanRewardBonus>> _clanRewards = new ConcurrentHashMap<>();
protected ClanRewardData()
{
load();
}
@Override
public void load()
{
parseDatapackFile("config/ClanReward.xml");
for (ClanRewardType type : ClanRewardType.values())
{
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + (_clanRewards.containsKey(type) ? _clanRewards.get(type).size() : 0) + " rewards for " + type);
}
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc.getFirstChild(), IXmlReader::isNode, listNode ->
{
switch (listNode.getNodeName())
{
case "membersOnline":
{
parseMembersOnline(listNode);
break;
}
case "huntingBonus":
{
parseHuntingBonus(listNode);
break;
}
}
});
}
private void parseMembersOnline(Node node)
{
forEach(node, IXmlReader::isNode, memberNode ->
{
if ("players".equalsIgnoreCase(memberNode.getNodeName()))
{
final NamedNodeMap attrs = memberNode.getAttributes();
final int requiredAmount = parseInteger(attrs, "size");
final int level = parseInteger(attrs, "level");
final ClanRewardBonus bonus = new ClanRewardBonus(ClanRewardType.MEMBERS_ONLINE, level, requiredAmount);
forEach(memberNode, IXmlReader::isNode, skillNode ->
{
if ("skill".equalsIgnoreCase(skillNode.getNodeName()))
{
final NamedNodeMap skillAttr = skillNode.getAttributes();
final int skillId = parseInteger(skillAttr, "id");
final int skillLevel = parseInteger(skillAttr, "level");
bonus.setSkillReward(new SkillHolder(skillId, skillLevel));
}
});
_clanRewards.computeIfAbsent(bonus.getType(), key -> new ArrayList<>()).add(bonus);
}
});
}
private void parseHuntingBonus(Node node)
{
forEach(node, IXmlReader::isNode, memberNode ->
{
if ("hunting".equalsIgnoreCase(memberNode.getNodeName()))
{
final NamedNodeMap attrs = memberNode.getAttributes();
final int requiredAmount = parseInteger(attrs, "points");
final int level = parseInteger(attrs, "level");
final ClanRewardBonus bonus = new ClanRewardBonus(ClanRewardType.HUNTING_MONSTERS, level, requiredAmount);
forEach(memberNode, IXmlReader::isNode, itemsNode ->
{
if ("item".equalsIgnoreCase(itemsNode.getNodeName()))
{
final NamedNodeMap itemsAttr = itemsNode.getAttributes();
final int id = parseInteger(itemsAttr, "id");
final int count = parseInteger(itemsAttr, "count");
bonus.setItemReward(new ItemHolder(id, count));
}
});
_clanRewards.computeIfAbsent(bonus.getType(), key -> new ArrayList<>()).add(bonus);
}
});
}
public List<ClanRewardBonus> getClanRewardBonuses(ClanRewardType type)
{
return _clanRewards.get(type);
}
public ClanRewardBonus getHighestReward(ClanRewardType type)
{
ClanRewardBonus selectedBonus = null;
for (ClanRewardBonus currentBonus : _clanRewards.get(type))
{
if ((selectedBonus == null) || (selectedBonus.getLevel() < currentBonus.getLevel()))
{
selectedBonus = currentBonus;
}
}
return selectedBonus;
}
public Collection<List<ClanRewardBonus>> getClanRewardBonuses()
{
return _clanRewards.values();
}
/**
* Gets the single instance of ClanRewardData.
* @return single instance of ClanRewardData
*/
public static ClanRewardData getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final ClanRewardData INSTANCE = new ClanRewardData();
}
}

View File

@@ -0,0 +1,131 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.base.ClassInfo;
/**
* Loads the the list of classes and it's info.
* @author Zoey76
*/
public final class ClassListData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ClassListData.class.getName());
private final Map<ClassId, ClassInfo> _classData = new HashMap<>();
/**
* Instantiates a new class list data.
*/
protected ClassListData()
{
load();
}
@Override
public void load()
{
_classData.clear();
parseDatapackFile("data/stats/chars/classList.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _classData.size() + " Class data.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
Node attr;
ClassId classId;
String className;
ClassId parentClassId;
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equals(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
attrs = d.getAttributes();
if ("class".equals(d.getNodeName()))
{
attr = attrs.getNamedItem("classId");
classId = ClassId.getClassId(parseInteger(attr));
attr = attrs.getNamedItem("name");
className = attr.getNodeValue();
attr = attrs.getNamedItem("parentClassId");
parentClassId = (attr != null) ? ClassId.getClassId(parseInteger(attr)) : null;
_classData.put(classId, new ClassInfo(classId, className, parentClassId));
}
}
}
}
}
/**
* Gets the class list.
* @return the complete class list.
*/
public Map<ClassId, ClassInfo> getClassList()
{
return _classData;
}
/**
* Gets the class info.
* @param classId the class Id.
* @return the class info related to the given {@code classId}.
*/
public ClassInfo getClass(ClassId classId)
{
return _classData.get(classId);
}
/**
* Gets the class info.
* @param classId the class Id as integer.
* @return the class info related to the given {@code classId}.
*/
public ClassInfo getClass(int classId)
{
final ClassId id = ClassId.getClassId(classId);
return (id != null) ? _classData.get(id) : null;
}
/**
* Gets the single instance of ClassListData.
* @return single instance of ClassListData
*/
public static ClassListData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ClassListData _instance = new ClassListData();
}
}

View File

@@ -0,0 +1,166 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.templates.L2CubicTemplate;
import com.l2jmobius.gameserver.model.cubic.CubicSkill;
import com.l2jmobius.gameserver.model.cubic.ICubicConditionHolder;
import com.l2jmobius.gameserver.model.cubic.conditions.GeneralCondition;
import com.l2jmobius.gameserver.model.cubic.conditions.GeneralCondition.GeneralConditionType;
import com.l2jmobius.gameserver.model.cubic.conditions.HealthCondition;
/**
* @author UnAfraid
*/
public class CubicData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(CubicData.class.getName());
private final Map<Integer, Map<Integer, L2CubicTemplate>> _cubics = new HashMap<>();
protected CubicData()
{
load();
}
@Override
public void load()
{
_cubics.clear();
parseDatapackDirectory("data/stats/cubics", true);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _cubics.size() + " cubics.");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "cubic", cubicNode ->
{
parseTemplate(cubicNode, new L2CubicTemplate(new StatsSet(parseAttributes(cubicNode))));
}));
}
/**
* @param cubicNode
* @param template
*/
private void parseTemplate(Node cubicNode, L2CubicTemplate template)
{
forEach(cubicNode, IXmlReader::isNode, innerNode ->
{
switch (innerNode.getNodeName())
{
case "conditions":
{
parseConditions(innerNode, template, template);
break;
}
case "skills":
{
parseSkills(innerNode, template);
break;
}
}
});
_cubics.computeIfAbsent(template.getId(), key -> new HashMap<>()).put(template.getLevel(), template);
}
/**
* @param cubicNode
* @param template
* @param holder
*/
private void parseConditions(Node cubicNode, L2CubicTemplate template, ICubicConditionHolder holder)
{
forEach(cubicNode, IXmlReader::isNode, conditionNode ->
{
switch (conditionNode.getNodeName())
{
case "general":
{
final GeneralConditionType type = parseEnum(conditionNode.getAttributes(), GeneralConditionType.class, "type");
final int hpPer = parseInteger(conditionNode.getAttributes(), "hpPercent");
final int hp = parseInteger(conditionNode.getAttributes(), "hp");
holder.addCondition(new GeneralCondition(type, hpPer, hp));
break;
}
case "healthPercent":
{
final int min = parseInteger(conditionNode.getAttributes(), "min");
final int max = parseInteger(conditionNode.getAttributes(), "max");
holder.addCondition(new HealthCondition(min, max));
break;
}
default:
{
LOGGER.warning("Attempting to use not implemented condition: " + conditionNode.getNodeName() + " for cubic id: " + template.getId() + " level: " + template.getLevel());
break;
}
}
});
}
/**
* @param cubicNode
* @param template
*/
private void parseSkills(Node cubicNode, L2CubicTemplate template)
{
forEach(cubicNode, "skill", skillNode ->
{
final CubicSkill skill = new CubicSkill(new StatsSet(parseAttributes(skillNode)));
forEach(cubicNode, "conditions", conditionNode -> parseConditions(cubicNode, template, skill));
template.getSkills().add(skill);
});
}
/**
* @param id
* @param level
* @return the L2CubicTemplate for specified id and level
*/
public L2CubicTemplate getCubicTemplate(int id, int level)
{
return _cubics.getOrDefault(id, Collections.emptyMap()).get(level);
}
/**
* Gets the single instance of CubicData.
* @return single instance of CubicData
*/
public static final CubicData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final CubicData _instance = new CubicData();
}
}

View File

@@ -0,0 +1,140 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.DailyMissionDataHolder;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
/**
* @author Sdw
*/
public class DailyMissionData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(DailyMissionData.class.getName());
private final Map<Integer, List<DailyMissionDataHolder>> _dailyMissionRewards = new LinkedHashMap<>();
protected DailyMissionData()
{
load();
}
@Override
public void load()
{
_dailyMissionRewards.clear();
parseDatapackFile("data/DailyMission.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _dailyMissionRewards.size() + " one day rewards.");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "reward", rewardNode ->
{
final StatsSet set = new StatsSet(parseAttributes(rewardNode));
final List<ItemHolder> items = new ArrayList<>(1);
forEach(rewardNode, "items", itemsNode -> forEach(itemsNode, "item", itemNode ->
{
final int itemId = parseInteger(itemNode.getAttributes(), "id");
final int itemCount = parseInteger(itemNode.getAttributes(), "count");
items.add(new ItemHolder(itemId, itemCount));
}));
set.set("items", items);
final List<ClassId> classRestriction = new ArrayList<>(1);
forEach(rewardNode, "classId", classRestrictionNode ->
{
classRestriction.add(ClassId.getClassId(Integer.parseInt(classRestrictionNode.getTextContent())));
});
set.set("classRestriction", classRestriction);
// Initial values in case handler doesn't exists
set.set("handler", "");
set.set("params", StatsSet.EMPTY_STATSET);
// Parse handler and parameters
forEach(rewardNode, "handler", handlerNode ->
{
set.set("handler", parseString(handlerNode.getAttributes(), "name"));
final StatsSet params = new StatsSet();
set.set("params", params);
forEach(handlerNode, "param", paramNode -> params.set(parseString(paramNode.getAttributes(), "name"), paramNode.getTextContent()));
});
final DailyMissionDataHolder holder = new DailyMissionDataHolder(set);
_dailyMissionRewards.computeIfAbsent(holder.getId(), k -> new ArrayList<>()).add(holder);
}));
}
public Collection<DailyMissionDataHolder> getDailyMissionData()
{
//@formatter:off
return _dailyMissionRewards.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
//@formatter:on
}
public Collection<DailyMissionDataHolder> getDailyMissionData(L2PcInstance player)
{
//@formatter:off
return _dailyMissionRewards.values()
.stream()
.flatMap(List::stream)
.filter(o -> o.isDisplayable(player))
.collect(Collectors.toList());
//@formatter:on
}
public Collection<DailyMissionDataHolder> getDailyMissionData(int id)
{
return _dailyMissionRewards.get(id);
}
/**
* Gets the single instance of DailyMissionData.
* @return single instance of DailyMissionData
*/
public static final DailyMissionData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final DailyMissionData _instance = new DailyMissionData();
}
}

View File

@@ -0,0 +1,287 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.instancemanager.MapRegionManager;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2DoorTemplate;
import com.l2jmobius.gameserver.model.instancezone.Instance;
import com.l2jmobius.gameserver.pathfinding.AbstractNodeLoc;
/**
* This class loads and hold info about doors.
* @author JIV, GodKratos, UnAfraid
*/
public final class DoorData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(DoorData.class.getName());
// Info holders
private final Map<String, Set<Integer>> _groups = new HashMap<>();
private final Map<Integer, L2DoorInstance> _doors = new HashMap<>();
private final Map<Integer, StatsSet> _templates = new HashMap<>();
private final Map<Integer, List<L2DoorInstance>> _regions = new HashMap<>();
protected DoorData()
{
load();
}
@Override
public void load()
{
_doors.clear();
_groups.clear();
_regions.clear();
parseDatapackFile("data/DoorData.xml");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "door", doorNode -> spawnDoor(parseDoor(doorNode))));
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _doors.size() + " Door Templates for " + _regions.size() + " regions.");
}
public StatsSet parseDoor(Node doorNode)
{
final StatsSet params = new StatsSet(parseAttributes(doorNode));
params.set("baseHpMax", 1); // Avoid doors without HP value created dead due to default value 0 in L2CharTemplate
forEach(doorNode, IXmlReader::isNode, innerDoorNode ->
{
final NamedNodeMap attrs = innerDoorNode.getAttributes();
if (innerDoorNode.getNodeName().equals("nodes"))
{
params.set("nodeZ", parseInteger(attrs, "nodeZ"));
final AtomicInteger count = new AtomicInteger();
forEach(innerDoorNode, IXmlReader::isNode, nodes ->
{
final NamedNodeMap nodeAttrs = nodes.getAttributes();
if ("node".equals(nodes.getNodeName()))
{
params.set("nodeX_" + count.get(), parseInteger(nodeAttrs, "x"));
params.set("nodeY_" + count.getAndIncrement(), parseInteger(nodeAttrs, "y"));
}
});
}
else if (attrs != null)
{
for (int i = 0; i < attrs.getLength(); i++)
{
final Node att = attrs.item(i);
params.set(att.getNodeName(), att.getNodeValue());
}
}
});
applyCollisions(params);
return params;
}
/**
* @param set
*/
private void applyCollisions(StatsSet set)
{
// Insert Collision data
if (set.contains("nodeX_0") && set.contains("nodeY_0") && set.contains("nodeX_1") && set.contains("nodeX_1"))
{
int posX, posY, nodeX, nodeY, height;
height = set.getInt("height", 150);
nodeX = set.getInt("nodeX_0");
nodeY = set.getInt("nodeY_0");
posX = set.getInt("nodeX_1");
posY = set.getInt("nodeX_1");
int collisionRadius; // (max) radius for movement checks
collisionRadius = Math.min(Math.abs(nodeX - posX), Math.abs(nodeY - posY));
if (collisionRadius < 20)
{
collisionRadius = 20;
}
set.set("collision_radius", collisionRadius);
set.set("collision_height", height);
}
}
/**
* Spawns the door, adds the group name and registers it to templates, regions and doors also inserts collisions data
* @param set
* @return
*/
public L2DoorInstance spawnDoor(StatsSet set)
{
// Create door template + door instance
final L2DoorTemplate template = new L2DoorTemplate(set);
final L2DoorInstance door = spawnDoor(template, null);
// Register the door
_templates.put(door.getId(), set);
_doors.put(door.getId(), door);
_regions.computeIfAbsent(MapRegionManager.getInstance().getMapRegionLocId(door), key -> new ArrayList<>()).add(door);
return door;
}
/**
* Spawns the door, adds the group name and registers it to templates
* @param template
* @param instance
* @return a new door instance based on provided template
*/
public L2DoorInstance spawnDoor(L2DoorTemplate template, Instance instance)
{
final L2DoorInstance door = new L2DoorInstance(template);
door.setCurrentHp(door.getMaxHp());
// Set instance world if provided
if (instance != null)
{
door.setInstance(instance);
}
// Spawn the door on the world
door.spawnMe(template.getX(), template.getY(), template.getZ());
// Register door's group
if (template.getGroupName() != null)
{
_groups.computeIfAbsent(door.getGroupName(), key -> new HashSet<>()).add(door.getId());
}
return door;
}
public StatsSet getDoorTemplate(int doorId)
{
return _templates.get(doorId);
}
public L2DoorInstance getDoor(int doorId)
{
return _doors.get(doorId);
}
public Set<Integer> getDoorsByGroup(String groupName)
{
return _groups.getOrDefault(groupName, Collections.emptySet());
}
public Collection<L2DoorInstance> getDoors()
{
return _doors.values();
}
public boolean checkIfDoorsBetween(AbstractNodeLoc start, AbstractNodeLoc end, Instance instance)
{
return checkIfDoorsBetween(start.getX(), start.getY(), start.getZ(), end.getX(), end.getY(), end.getZ(), instance);
}
public boolean checkIfDoorsBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance)
{
return checkIfDoorsBetween(x, y, z, tx, ty, tz, instance, false);
}
/**
* GodKratos: TODO: remove GeoData checks from door table and convert door nodes to Geo zones
* @param x
* @param y
* @param z
* @param tx
* @param ty
* @param tz
* @param instance
* @param doubleFaceCheck
* @return {@code boolean}
*/
public boolean checkIfDoorsBetween(int x, int y, int z, int tx, int ty, int tz, Instance instance, boolean doubleFaceCheck)
{
final Collection<L2DoorInstance> allDoors = (instance != null) ? instance.getDoors() : _regions.get(MapRegionManager.getInstance().getMapRegionLocId(x, y));
if (allDoors == null)
{
return false;
}
for (L2DoorInstance doorInst : allDoors)
{
// check dead and open
if (doorInst.isDead() || doorInst.isOpen() || !doorInst.checkCollision() || (doorInst.getX(0) == 0))
{
continue;
}
boolean intersectFace = false;
for (int i = 0; i < 4; i++)
{
final int j = (i + 1) < 4 ? i + 1 : 0;
// lower part of the multiplier fraction, if it is 0 we avoid an error and also know that the lines are parallel
final int denominator = ((ty - y) * (doorInst.getX(i) - doorInst.getX(j))) - ((tx - x) * (doorInst.getY(i) - doorInst.getY(j)));
if (denominator == 0)
{
continue;
}
// multipliers to the equations of the lines. If they are lower than 0 or bigger than 1, we know that segments don't intersect
final float multiplier1 = (float) (((doorInst.getX(j) - doorInst.getX(i)) * (y - doorInst.getY(i))) - ((doorInst.getY(j) - doorInst.getY(i)) * (x - doorInst.getX(i)))) / denominator;
final float multiplier2 = (float) (((tx - x) * (y - doorInst.getY(i))) - ((ty - y) * (x - doorInst.getX(i)))) / denominator;
if ((multiplier1 >= 0) && (multiplier1 <= 1) && (multiplier2 >= 0) && (multiplier2 <= 1))
{
final int intersectZ = Math.round(z + (multiplier1 * (tz - z)));
// now checking if the resulting point is between door's min and max z
if ((intersectZ > doorInst.getZMin()) && (intersectZ < doorInst.getZMax()))
{
if (!doubleFaceCheck || intersectFace)
{
return true;
}
intersectFace = true;
}
}
}
}
return false;
}
public static DoorData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final DoorData _instance = new DoorData();
}
}

View File

@@ -0,0 +1,168 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.items.enchant.EnchantScroll;
import com.l2jmobius.gameserver.model.items.enchant.EnchantSupportItem;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
/**
* Loads item enchant data.
* @author UnAfraid
*/
public class EnchantItemData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnchantItemData.class.getName());
private final Map<Integer, EnchantScroll> _scrolls = new HashMap<>();
private final Map<Integer, EnchantSupportItem> _supports = new HashMap<>();
/**
* Instantiates a new enchant item data.
*/
public EnchantItemData()
{
load();
}
@Override
public synchronized void load()
{
_scrolls.clear();
_supports.clear();
parseDatapackFile("data/EnchantItemData.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _scrolls.size() + " Enchant Scrolls.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _supports.size() + " Support Items.");
}
@Override
public void parseDocument(Document doc, File f)
{
StatsSet set;
Node att;
NamedNodeMap attrs;
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 ("enchant".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
try
{
final EnchantScroll item = new EnchantScroll(set);
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("item".equalsIgnoreCase(cd.getNodeName()))
{
item.addItem(parseInteger(cd.getAttributes(), "id"));
}
}
_scrolls.put(item.getId(), item);
}
catch (NullPointerException e)
{
LOGGER.warning(getClass().getSimpleName() + ": Unexistent enchant scroll: " + set.getString("id") + " defined in enchant data!");
}
catch (IllegalAccessError e)
{
LOGGER.warning(getClass().getSimpleName() + ": Wrong enchant scroll item type: " + set.getString("id") + " defined in enchant data!");
}
}
else if ("support".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
try
{
final EnchantSupportItem item = new EnchantSupportItem(set);
_supports.put(item.getId(), item);
}
catch (NullPointerException e)
{
LOGGER.warning(getClass().getSimpleName() + ": Unexistent enchant support item: " + set.getString("id") + " defined in enchant data!");
}
catch (IllegalAccessError e)
{
LOGGER.warning(getClass().getSimpleName() + ": Wrong enchant support item type: " + set.getString("id") + " defined in enchant data!");
}
}
}
}
}
}
/**
* Gets the enchant scroll.
* @param scroll the scroll
* @return enchant template for scroll
*/
public final EnchantScroll getEnchantScroll(L2ItemInstance scroll)
{
return _scrolls.get(scroll.getId());
}
/**
* Gets the support item.
* @param item the item
* @return enchant template for support item
*/
public final EnchantSupportItem getSupportItem(L2ItemInstance item)
{
return _supports.get(item.getId());
}
/**
* Gets the single instance of EnchantItemData.
* @return single instance of EnchantItemData
*/
public static EnchantItemData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EnchantItemData _instance = new EnchantItemData();
}
}

View File

@@ -0,0 +1,169 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.holders.RangeChanceHolder;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.enchant.EnchantItemGroup;
import com.l2jmobius.gameserver.model.items.enchant.EnchantRateItem;
import com.l2jmobius.gameserver.model.items.enchant.EnchantScrollGroup;
import com.l2jmobius.gameserver.util.Util;
/**
* @author UnAfraid
*/
public final class EnchantItemGroupsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnchantItemGroupsData.class.getName());
private final Map<String, EnchantItemGroup> _itemGroups = new HashMap<>();
private final Map<Integer, EnchantScrollGroup> _scrollGroups = new HashMap<>();
protected EnchantItemGroupsData()
{
load();
}
@Override
public synchronized void load()
{
_itemGroups.clear();
_scrollGroups.clear();
parseDatapackFile("data/EnchantItemGroups.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _itemGroups.size() + " item group templates.");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _scrollGroups.size() + " scroll group templates.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("enchantRateGroup".equalsIgnoreCase(d.getNodeName()))
{
final String name = parseString(d.getAttributes(), "name");
final EnchantItemGroup group = new EnchantItemGroup(name);
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("current".equalsIgnoreCase(cd.getNodeName()))
{
final String range = parseString(cd.getAttributes(), "enchant");
final double chance = parseDouble(cd.getAttributes(), "chance");
int min = -1;
int max = 0;
if (range.contains("-"))
{
final String[] split = range.split("-");
if ((split.length == 2) && Util.isDigit(split[0]) && Util.isDigit(split[1]))
{
min = Integer.parseInt(split[0]);
max = Integer.parseInt(split[1]);
}
}
else if (Util.isDigit(range))
{
min = Integer.parseInt(range);
max = min;
}
if ((min > -1) && (max > 0))
{
group.addChance(new RangeChanceHolder(min, max, chance));
}
}
}
_itemGroups.put(name, group);
}
else if ("enchantScrollGroup".equals(d.getNodeName()))
{
final int id = parseInteger(d.getAttributes(), "id");
final EnchantScrollGroup group = new EnchantScrollGroup(id);
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("enchantRate".equalsIgnoreCase(cd.getNodeName()))
{
final EnchantRateItem rateGroup = new EnchantRateItem(parseString(cd.getAttributes(), "group"));
for (Node z = cd.getFirstChild(); z != null; z = z.getNextSibling())
{
if ("item".equals(z.getNodeName()))
{
final NamedNodeMap attrs = z.getAttributes();
if (attrs.getNamedItem("slot") != null)
{
rateGroup.addSlot(ItemTable.SLOTS.get(parseString(attrs, "slot")));
}
if (attrs.getNamedItem("magicWeapon") != null)
{
rateGroup.setMagicWeapon(parseBoolean(attrs, "magicWeapon"));
}
if (attrs.getNamedItem("id") != null)
{
rateGroup.setItemId(parseInteger(attrs, "id"));
}
}
}
group.addRateGroup(rateGroup);
}
}
_scrollGroups.put(id, group);
}
}
}
}
}
public EnchantItemGroup getItemGroup(L2Item item, int scrollGroup)
{
final EnchantScrollGroup group = _scrollGroups.get(scrollGroup);
final EnchantRateItem rateGroup = group.getRateGroup(item);
return rateGroup != null ? _itemGroups.get(rateGroup.getName()) : null;
}
public EnchantItemGroup getItemGroup(String name)
{
return _itemGroups.get(name);
}
public EnchantScrollGroup getScrollGroup(int id)
{
return _scrollGroups.get(id);
}
public static EnchantItemGroupsData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EnchantItemGroupsData _instance = new EnchantItemGroupsData();
}
}

View File

@@ -0,0 +1,122 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
/**
* This class holds the Enchant HP Bonus Data.
* @author MrPoke, Zoey76
*/
public class EnchantItemHPBonusData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnchantItemHPBonusData.class.getName());
private final Map<CrystalType, List<Integer>> _armorHPBonuses = new EnumMap<>(CrystalType.class);
private static final float FULL_ARMOR_MODIFIER = 1.5f; // TODO: Move it to config!
/**
* Instantiates a new enchant hp bonus data.
*/
protected EnchantItemHPBonusData()
{
load();
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("enchantHP".equalsIgnoreCase(d.getNodeName()))
{
final List<Integer> bonuses = new ArrayList<>(12);
for (Node e = d.getFirstChild(); e != null; e = e.getNextSibling())
{
if ("bonus".equalsIgnoreCase(e.getNodeName()))
{
bonuses.add(Integer.parseInt(e.getTextContent()));
}
}
_armorHPBonuses.put(parseEnum(d.getAttributes(), CrystalType.class, "grade"), bonuses);
}
}
}
}
}
@Override
public void load()
{
_armorHPBonuses.clear();
parseDatapackFile("data/stats/enchantHPBonus.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _armorHPBonuses.size() + " Enchant HP Bonuses.");
}
/**
* Gets the HP bonus.
* @param item the item
* @return the HP bonus
*/
public final int getHPBonus(L2ItemInstance item)
{
final List<Integer> values = _armorHPBonuses.get(item.getItem().getCrystalTypePlus());
if ((values == null) || values.isEmpty() || (item.getOlyEnchantLevel() <= 0))
{
return 0;
}
final int bonus = values.get(Math.min(item.getOlyEnchantLevel(), values.size()) - 1);
if (item.getItem().getBodyPart() == L2Item.SLOT_FULL_ARMOR)
{
return (int) (bonus * FULL_ARMOR_MODIFIER);
}
return bonus;
}
/**
* Gets the single instance of EnchantHPBonusData.
* @return single instance of EnchantHPBonusData
*/
public static final EnchantItemHPBonusData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EnchantItemHPBonusData _instance = new EnchantItemHPBonusData();
}
}

View File

@@ -0,0 +1,131 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.model.options.EnchantOptions;
import com.l2jmobius.gameserver.util.Util;
/**
* @author UnAfraid
*/
public class EnchantItemOptionsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnchantItemOptionsData.class.getName());
private final Map<Integer, Map<Integer, EnchantOptions>> _data = new HashMap<>();
protected EnchantItemOptionsData()
{
load();
}
@Override
public synchronized void load()
{
_data.clear();
parseDatapackFile("data/EnchantItemOptions.xml");
}
@Override
public void parseDocument(Document doc, File f)
{
int counter = 0;
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()))
{
final int itemId = parseInteger(d.getAttributes(), "id");
if (!_data.containsKey(itemId))
{
_data.put(itemId, new HashMap<Integer, EnchantOptions>());
}
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
if ("options".equalsIgnoreCase(cd.getNodeName()))
{
final EnchantOptions op = new EnchantOptions(parseInteger(cd.getAttributes(), "level"));
_data.get(itemId).put(op.getLevel(), op);
for (byte i = 0; i < 3; i++)
{
final Node att = cd.getAttributes().getNamedItem("option" + (i + 1));
if ((att != null) && Util.isDigit(att.getNodeValue()))
{
op.setOption(i, parseInteger(att));
}
}
counter++;
}
}
}
}
}
}
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _data.size() + " Items and " + counter + " Options.");
}
/**
* @param itemId
* @param enchantLevel
* @return enchant effects information.
*/
public EnchantOptions getOptions(int itemId, int enchantLevel)
{
if (!_data.containsKey(itemId) || !_data.get(itemId).containsKey(enchantLevel))
{
return null;
}
return _data.get(itemId).get(enchantLevel);
}
/**
* @param item
* @return enchant effects information.
*/
public EnchantOptions getOptions(L2ItemInstance item)
{
return item != null ? getOptions(item.getId(), item.getEnchantLevel()) : null;
}
/**
* Gets the single instance of EnchantOptionsData.
* @return single instance of EnchantOptionsData
*/
public static EnchantItemOptionsData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EnchantItemOptionsData _instance = new EnchantItemOptionsData();
}
}

View File

@@ -0,0 +1,271 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.L2EnchantSkillGroup;
import com.l2jmobius.gameserver.model.L2EnchantSkillGroup.EnchantSkillHolder;
import com.l2jmobius.gameserver.model.L2EnchantSkillLearn;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* This class holds the Enchant Groups information.
* @author Micr0
*/
public class EnchantSkillGroupsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnchantSkillGroupsData.class.getName());
public static final int NORMAL_ENCHANT_COST_MULTIPLIER = Config.NORMAL_ENCHANT_COST_MULTIPLIER;
public static final int SAFE_ENCHANT_COST_MULTIPLIER = Config.SAFE_ENCHANT_COST_MULTIPLIER;
public static final int NORMAL_ENCHANT_BOOK_OLD = 6622;
public static final int SAFE_ENCHANT_BOOK_OLD = 9627;
public static final int CHANGE_ENCHANT_BOOK_OLD = 9626;
public static final int UNTRAIN_ENCHANT_BOOK_OLD = 9625;
public static final int NORMAL_ENCHANT_BOOK = 30297;
public static final int SAFE_ENCHANT_BOOK = 30298;
public static final int CHANGE_ENCHANT_BOOK = 30299;
public static final int UNTRAIN_ENCHANT_BOOK = 30300;
public static final int IMMORTAL_SCROLL = 37044;
public static final int NORMAL_ENCHANT_BOOK_V2 = 46150;
public static final int SAFE_ENCHANT_BOOK_V2 = 46151;
public static final int CHANGE_ENCHANT_BOOK_V2 = 46152;
public static final int IMMORTAL_SCROLL_V2 = 46153;
public static final int NORMAL_ENCHANT_BOOK_V3 = 46154;
public static final int SAFE_ENCHANT_BOOK_V3 = 46155;
public static final int CHANGE_ENCHANT_BOOK_V3 = 46156;
public static final int IMMORTAL_SCROLL_V3 = 46157;
private final Map<Integer, L2EnchantSkillGroup> _enchantSkillGroups = new HashMap<>();
private final Map<Integer, L2EnchantSkillLearn> _enchantSkillTrees = new HashMap<>();
/**
* Instantiates a new enchant groups table.
*/
protected EnchantSkillGroupsData()
{
load();
}
@Override
public void load()
{
_enchantSkillGroups.clear();
_enchantSkillTrees.clear();
parseDatapackFile("data/EnchantSkillGroups.xml");
int routes = 0;
for (L2EnchantSkillGroup group : _enchantSkillGroups.values())
{
routes += group.getEnchantGroupDetails().size();
}
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _enchantSkillGroups.size() + " groups and " + routes + " routes.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
StatsSet set;
Node att;
int id = 0;
L2EnchantSkillGroup group;
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 ("group".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
id = parseInteger(attrs, "id");
group = _enchantSkillGroups.get(id);
if (group == null)
{
group = new L2EnchantSkillGroup(id);
_enchantSkillGroups.put(id, group);
}
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("enchant".equalsIgnoreCase(b.getNodeName()))
{
attrs = b.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
group.addEnchantDetail(new EnchantSkillHolder(set));
}
}
}
}
}
}
}
/**
* Adds the new route for skill.
* @param skillId the skill id
* @param maxLvL the max lvl
* @param route the route
* @param group the group
* @return the int
*/
public int addNewRouteForSkill(int skillId, int maxLvL, int route, int group)
{
L2EnchantSkillLearn enchantableSkill = _enchantSkillTrees.get(skillId);
if (enchantableSkill == null)
{
enchantableSkill = new L2EnchantSkillLearn(skillId, maxLvL);
_enchantSkillTrees.put(skillId, enchantableSkill);
}
if (_enchantSkillGroups.containsKey(group))
{
enchantableSkill.addNewEnchantRoute(route, group);
return _enchantSkillGroups.get(group).getEnchantGroupDetails().size();
}
LOGGER.severe(getClass().getSimpleName() + ": Error while loading generating enchant skill id: " + skillId + "; route: " + route + " missing group: " + group);
return 0;
}
/**
* Gets the skill enchantment for skill.
* @param skill the skill
* @return the skill enchantment for skill
*/
public L2EnchantSkillLearn getSkillEnchantmentForSkill(Skill skill)
{
// there is enchantment for this skill and we have the required level of it
final L2EnchantSkillLearn esl = getSkillEnchantmentBySkillId(skill.getId());
if ((esl != null) && (skill.getLevel() >= esl.getBaseLevel()))
{
return esl;
}
return null;
}
/**
* Gets the skill enchantment by skill id.
* @param skillId the skill id
* @return the skill enchantment by skill id
*/
public L2EnchantSkillLearn getSkillEnchantmentBySkillId(int skillId)
{
return _enchantSkillTrees.get(skillId);
}
/**
* Gets the enchant skill group by id.
* @param id the id
* @return the enchant skill group by id
*/
public L2EnchantSkillGroup getEnchantSkillGroupById(int id)
{
return _enchantSkillGroups.get(id);
}
/**
* Gets the enchant skill sp cost.
* @param skill the skill
* @return the enchant skill sp cost
*/
public int getEnchantSkillSpCost(Skill skill)
{
final L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
if (enchantSkillLearn != null)
{
final EnchantSkillHolder esh = enchantSkillLearn.getEnchantSkillHolder(skill.getLevel());
if (esh != null)
{
return esh.getSpCost();
}
}
return Integer.MAX_VALUE;
}
/**
* Gets the enchant skill Adena cost.
* @param skill the skill
* @return the enchant skill Adena cost
*/
public int getEnchantSkillAdenaCost(Skill skill)
{
final L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
if (enchantSkillLearn != null)
{
final EnchantSkillHolder esh = enchantSkillLearn.getEnchantSkillHolder(skill.getLevel());
if (esh != null)
{
return esh.getAdenaCost();
}
}
return Integer.MAX_VALUE;
}
/**
* Gets the enchant skill rate.
* @param player the player
* @param skill the skill
* @return the enchant skill rate
*/
public byte getEnchantSkillRate(L2PcInstance player, Skill skill)
{
final L2EnchantSkillLearn enchantSkillLearn = _enchantSkillTrees.get(skill.getId());
if (enchantSkillLearn != null)
{
final EnchantSkillHolder esh = enchantSkillLearn.getEnchantSkillHolder(skill.getLevel());
if (esh != null)
{
return esh.getRate(player);
}
}
return 0;
}
/**
* Gets the single instance of EnchantGroupsData.
* @return single instance of EnchantGroupsData
*/
public static EnchantSkillGroupsData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EnchantSkillGroupsData _instance = new EnchantSkillGroupsData();
}
}

View File

@@ -0,0 +1,203 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.model.ensoul.EnsoulFee;
import com.l2jmobius.gameserver.model.ensoul.EnsoulOption;
import com.l2jmobius.gameserver.model.ensoul.EnsoulStone;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.items.type.CrystalType;
/**
* @author UnAfraid
*/
public class EnsoulData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EnsoulData.class.getName());
private final Map<CrystalType, EnsoulFee> _ensoulFees = new EnumMap<>(CrystalType.class);
private final Map<Integer, EnsoulOption> _ensoulOptions = new HashMap<>();
private final Map<Integer, EnsoulStone> _ensoulStones = new HashMap<>();
protected EnsoulData()
{
load();
}
@Override
public void load()
{
parseDatapackDirectory("data/stats/ensoul", true);
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _ensoulFees.size() + " fees");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _ensoulOptions.size() + " options");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _ensoulStones.size() + " stones");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, IXmlReader::isNode, ensoulNode ->
{
switch (ensoulNode.getNodeName())
{
case "fee":
{
parseFees(ensoulNode);
break;
}
case "option":
{
parseOptions(ensoulNode);
break;
}
case "stone":
{
parseStones(ensoulNode);
break;
}
}
}));
}
private void parseFees(Node ensoulNode)
{
final CrystalType type = parseEnum(ensoulNode.getAttributes(), CrystalType.class, "crystalType");
final EnsoulFee fee = new EnsoulFee(type);
forEach(ensoulNode, IXmlReader::isNode, feeNode ->
{
switch (feeNode.getNodeName())
{
case "first":
{
parseFee(feeNode, fee, 0);
break;
}
case "secondary":
{
parseFee(feeNode, fee, 1);
break;
}
case "third":
{
parseFee(feeNode, fee, 2);
break;
}
case "reNormal":
{
parseReFee(feeNode, fee, 0);
break;
}
case "reSecondary":
{
parseReFee(feeNode, fee, 1);
break;
}
case "reThird":
{
parseReFee(feeNode, fee, 2);
break;
}
}
});
}
private void parseFee(Node ensoulNode, EnsoulFee fee, int index)
{
final NamedNodeMap attrs = ensoulNode.getAttributes();
final int id = parseInteger(attrs, "itemId");
final int count = parseInteger(attrs, "count");
fee.setEnsoul(index, new ItemHolder(id, count));
_ensoulFees.put(fee.getCrystalType(), fee);
}
private void parseReFee(Node ensoulNode, EnsoulFee fee, int index)
{
final NamedNodeMap attrs = ensoulNode.getAttributes();
final int id = parseInteger(attrs, "itemId");
final int count = parseInteger(attrs, "count");
fee.setResoul(index, new ItemHolder(id, count));
}
private void parseOptions(Node ensoulNode)
{
final NamedNodeMap attrs = ensoulNode.getAttributes();
final int id = parseInteger(attrs, "id");
final String name = parseString(attrs, "name");
final String desc = parseString(attrs, "desc");
final int skillId = parseInteger(attrs, "skillId");
final int skillLevel = parseInteger(attrs, "skillLevel");
final EnsoulOption option = new EnsoulOption(id, name, desc, skillId, skillLevel);
_ensoulOptions.put(option.getId(), option);
}
private void parseStones(Node ensoulNode)
{
final NamedNodeMap attrs = ensoulNode.getAttributes();
final int id = parseInteger(attrs, "id");
final int slotType = parseInteger(attrs, "slotType");
final EnsoulStone stone = new EnsoulStone(id, slotType);
forEach(ensoulNode, "option", optionNode -> stone.addOption(parseInteger(optionNode.getAttributes(), "id")));
_ensoulStones.put(stone.getId(), stone);
}
public ItemHolder getEnsoulFee(CrystalType type, int index)
{
final EnsoulFee fee = _ensoulFees.get(type);
return fee != null ? fee.getEnsoul(index) : null;
}
public ItemHolder getResoulFee(CrystalType type, int index)
{
final EnsoulFee fee = _ensoulFees.get(type);
return fee != null ? fee.getResoul(index) : null;
}
public EnsoulOption getOption(int id)
{
return _ensoulOptions.get(id);
}
public EnsoulStone getStone(int id)
{
return _ensoulStones.get(id);
}
/**
* Gets the single instance of EnsoulData.
* @return single instance of EnsoulData
*/
public static final EnsoulData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EnsoulData _instance = new EnsoulData();
}
}

View File

@@ -0,0 +1,583 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.eventengine.AbstractEventManager;
import com.l2jmobius.gameserver.model.eventengine.EventMethodNotification;
import com.l2jmobius.gameserver.model.eventengine.EventScheduler;
import com.l2jmobius.gameserver.model.eventengine.IConditionalEventScheduler;
import com.l2jmobius.gameserver.model.eventengine.conditions.BetweenConditionalScheduler;
import com.l2jmobius.gameserver.model.eventengine.conditions.HaventRunConditionalScheduler;
import com.l2jmobius.gameserver.model.eventengine.drop.EventDropGroup;
import com.l2jmobius.gameserver.model.eventengine.drop.EventDropItem;
import com.l2jmobius.gameserver.model.eventengine.drop.EventDrops;
import com.l2jmobius.gameserver.model.eventengine.drop.GroupedDrop;
import com.l2jmobius.gameserver.model.eventengine.drop.IEventDrop;
import com.l2jmobius.gameserver.model.eventengine.drop.NormalDrop;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
/**
* @author UnAfraid
*/
public final class EventEngineData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(EventEngineData.class.getName());
protected EventEngineData()
{
load();
}
@Override
public void load()
{
parseDatapackDirectory("data/events", true);
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node listNode = doc.getFirstChild(); listNode != null; listNode = listNode.getNextSibling())
{
if ("list".equals(listNode.getNodeName()))
{
for (Node eventNode = listNode.getFirstChild(); eventNode != null; eventNode = eventNode.getNextSibling())
{
if ("event".equals(eventNode.getNodeName()))
{
parseEvent(eventNode);
}
}
}
}
}
/**
* @param eventNode
*/
private void parseEvent(Node eventNode)
{
final String eventName = parseString(eventNode.getAttributes(), "name");
final String className = parseString(eventNode.getAttributes(), "class");
AbstractEventManager<?> eventManager = null;
try
{
final Class<?> clazz = Class.forName(className);
// Attempt to find getInstance() method
for (Method method : clazz.getMethods())
{
if (Modifier.isStatic(method.getModifiers()) && AbstractEventManager.class.isAssignableFrom(method.getReturnType()) && (method.getParameterCount() == 0))
{
eventManager = (AbstractEventManager<?>) method.invoke(null);
break;
}
}
if (eventManager == null)
{
throw new NoSuchMethodError("Couldn't method that gives instance of AbstractEventManager!");
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't locate event manager instance for event: " + eventName + " !", e);
return;
}
for (Node innerNode = eventNode.getFirstChild(); innerNode != null; innerNode = innerNode.getNextSibling())
{
if ("variables".equals(innerNode.getNodeName()))
{
parseVariables(eventManager, innerNode);
}
else if ("scheduler".equals(innerNode.getNodeName()))
{
parseScheduler(eventManager, innerNode);
}
else if ("rewards".equals(innerNode.getNodeName()))
{
parseRewards(eventManager, innerNode);
}
}
// Assign event name
eventManager.setName(eventName);
// Start the scheduler
eventManager.startScheduler();
// Start conditional schedulers
eventManager.startConditionalSchedulers();
// Notify the event manager that we've done initializing its stuff
eventManager.onInitialized();
LOGGER.info(getClass().getSimpleName() + ": " + eventManager.getClass().getSimpleName() + ": Initialized");
}
/**
* @param eventManager
* @param innerNode
*/
private void parseVariables(AbstractEventManager<?> eventManager, Node innerNode)
{
final StatsSet variables = new StatsSet(LinkedHashMap::new);
for (Node variableNode = innerNode.getFirstChild(); variableNode != null; variableNode = variableNode.getNextSibling())
{
if ("variable".equals(variableNode.getNodeName()))
{
variables.set(parseString(variableNode.getAttributes(), "name"), parseString(variableNode.getAttributes(), "value"));
}
else if ("list".equals(variableNode.getNodeName()))
{
parseListVariables(eventManager, variables, variableNode);
}
else if ("map".equals(variableNode.getNodeName()))
{
parseMapVariables(eventManager, variables, variableNode);
}
}
eventManager.setVariables(variables);
}
/**
* @param eventManager
* @param innerNode
*/
private void parseScheduler(AbstractEventManager<?> eventManager, Node innerNode)
{
eventManager.stopScheduler();
final Set<EventScheduler> schedulers = new LinkedHashSet<>();
final Set<IConditionalEventScheduler> conditionalSchedulers = new LinkedHashSet<>();
for (Node scheduleNode = innerNode.getFirstChild(); scheduleNode != null; scheduleNode = scheduleNode.getNextSibling())
{
if ("schedule".equals(scheduleNode.getNodeName()))
{
final StatsSet params = new StatsSet(LinkedHashMap::new);
final NamedNodeMap attrs = scheduleNode.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node node = attrs.item(i);
params.set(node.getNodeName(), node.getNodeValue());
}
final EventScheduler scheduler = new EventScheduler(eventManager, params);
for (Node eventNode = scheduleNode.getFirstChild(); eventNode != null; eventNode = eventNode.getNextSibling())
{
if ("event".equals(eventNode.getNodeName()))
{
String methodName = parseString(eventNode.getAttributes(), "name");
if (methodName.charAt(0) == '#')
{
methodName = methodName.substring(1);
}
final List<Object> args = new ArrayList<>();
for (Node argsNode = eventNode.getFirstChild(); argsNode != null; argsNode = argsNode.getNextSibling())
{
if ("arg".equals(argsNode.getNodeName()))
{
final String type = parseString(argsNode.getAttributes(), "type");
final Object value = parseObject(eventManager, type, argsNode.getTextContent());
if (value != null)
{
args.add(value);
}
}
}
try
{
scheduler.addEventNotification(new EventMethodNotification(eventManager, methodName, args));
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Couldn't add event notification for " + eventManager.getClass().getSimpleName(), e);
}
}
}
schedulers.add(scheduler);
}
else if ("conditionalSchedule".equals(scheduleNode.getNodeName()))
{
final StatsSet params = new StatsSet(LinkedHashMap::new);
final NamedNodeMap attrs = scheduleNode.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node node = attrs.item(i);
params.set(node.getNodeName(), node.getNodeValue());
}
for (Node eventNode = scheduleNode.getFirstChild(); eventNode != null; eventNode = eventNode.getNextSibling())
{
if ("run".equals(eventNode.getNodeName()))
{
final String name = parseString(eventNode.getAttributes(), "name");
final String ifType = parseString(eventNode.getAttributes(), "if", "BETWEEN").toUpperCase();
switch (ifType)
{
case "BETWEEN":
{
final List<String> names = new ArrayList<>(2);
for (Node innerData = eventNode.getFirstChild(); innerData != null; innerData = innerData.getNextSibling())
{
if ("name".equals(innerData.getNodeName()))
{
names.add(innerData.getTextContent());
}
}
if (names.size() != 2)
{
LOGGER.warning(getClass().getSimpleName() + ": Event: " + eventManager.getClass().getSimpleName() + " has incorrect amount of scheduler names: " + names + " expected: 2 found: " + names.size());
}
else
{
conditionalSchedulers.add(new BetweenConditionalScheduler(eventManager, name, names.get(0), names.get(1)));
}
break;
}
case "HAVENT_RUN":
{
conditionalSchedulers.add(new HaventRunConditionalScheduler(eventManager, name));
break;
}
}
}
}
}
}
eventManager.setSchedulers(schedulers);
eventManager.setConditionalSchedulers(conditionalSchedulers);
}
/**
* @param eventManager
* @param innerNode
*/
private void parseRewards(AbstractEventManager<?> eventManager, Node innerNode)
{
final Map<String, IEventDrop> rewards = new LinkedHashMap<>();
forEach(innerNode, IXmlReader::isNode, rewardsNode ->
{
if ("reward".equalsIgnoreCase(rewardsNode.getNodeName()))
{
final String name = parseString(rewardsNode.getAttributes(), "name");
final EventDrops dropType = parseEnum(rewardsNode.getAttributes(), EventDrops.class, "type");
switch (dropType)
{
case GROUPED:
{
final GroupedDrop droplist = dropType.newInstance();
forEach(rewardsNode, "group", groupsNode ->
{
final EventDropGroup group = new EventDropGroup(parseDouble(groupsNode.getAttributes(), "chance"));
forEach(groupsNode, "item", itemNode ->
{
final NamedNodeMap attrs = itemNode.getAttributes();
final int id = parseInteger(attrs, "id");
final int min = parseInteger(attrs, "min");
final int max = parseInteger(attrs, "max");
final double chance = parseDouble(attrs, "chance");
group.addItem(new EventDropItem(id, min, max, chance));
});
});
rewards.put(name, droplist);
break;
}
case NORMAL:
{
final NormalDrop droplist = dropType.newInstance();
forEach(rewardsNode, "item", itemNode ->
{
final NamedNodeMap attrs = itemNode.getAttributes();
final int id = parseInteger(attrs, "id");
final int min = parseInteger(attrs, "min");
final int max = parseInteger(attrs, "max");
final double chance = parseDouble(attrs, "chance");
droplist.addItem(new EventDropItem(id, min, max, chance));
});
rewards.put(name, droplist);
break;
}
}
}
});
eventManager.setRewards(rewards);
}
/**
* @param eventManager
* @param variables
* @param variableNode
*/
@SuppressWarnings("unchecked")
private void parseListVariables(AbstractEventManager<?> eventManager, StatsSet variables, Node variableNode)
{
final String name = parseString(variableNode.getAttributes(), "name");
final String type = parseString(variableNode.getAttributes(), "type");
final Class<?> classType = getClassByName(eventManager, type);
final List<?> values = newList(classType);
switch (type)
{
case "Byte":
case "Short":
case "Integer":
case "Float":
case "Long":
case "Double":
case "String":
{
for (Node stringNode = variableNode.getFirstChild(); stringNode != null; stringNode = stringNode.getNextSibling())
{
if ("value".equals(stringNode.getNodeName()))
{
((List<Object>) values).add(parseObject(eventManager, type, stringNode.getTextContent()));
}
}
break;
}
case "ItemHolder":
{
for (Node stringNode = variableNode.getFirstChild(); stringNode != null; stringNode = stringNode.getNextSibling())
{
if ("item".equals(stringNode.getNodeName()))
{
((List<ItemHolder>) values).add(new ItemHolder(parseInteger(stringNode.getAttributes(), "id"), parseLong(stringNode.getAttributes(), "count", 1L)));
}
}
break;
}
case "SkillHolder":
{
for (Node stringNode = variableNode.getFirstChild(); stringNode != null; stringNode = stringNode.getNextSibling())
{
if ("skill".equals(stringNode.getNodeName()))
{
((List<SkillHolder>) values).add(new SkillHolder(parseInteger(stringNode.getAttributes(), "id"), parseInteger(stringNode.getAttributes(), "level", 1)));
}
}
break;
}
case "Location":
{
for (Node stringNode = variableNode.getFirstChild(); stringNode != null; stringNode = stringNode.getNextSibling())
{
if ("location".equals(stringNode.getNodeName()))
{
((List<Location>) values).add(new Location(parseInteger(stringNode.getAttributes(), "x"), parseInteger(stringNode.getAttributes(), "y"), parseInteger(stringNode.getAttributes(), "z", parseInteger(stringNode.getAttributes(), "heading", 0))));
}
}
break;
}
default:
{
LOGGER.info(getClass().getSimpleName() + ": Unhandled list case: " + type + " for event: " + eventManager.getClass().getSimpleName());
break;
}
}
variables.set(name, values);
}
/**
* @param eventManager
* @param variables
* @param variableNode
*/
@SuppressWarnings("unchecked")
private void parseMapVariables(AbstractEventManager<?> eventManager, StatsSet variables, Node variableNode)
{
final String name = parseString(variableNode.getAttributes(), "name");
final String keyType = parseString(variableNode.getAttributes(), "keyType");
final String valueType = parseString(variableNode.getAttributes(), "valueType");
final Class<?> keyClass = getClassByName(eventManager, keyType);
final Class<?> valueClass = getClassByName(eventManager, valueType);
final Map<?, ?> map = newMap(keyClass, valueClass);
forEach(variableNode, IXmlReader::isNode, stringNode ->
{
switch (stringNode.getNodeName())
{
case "entry":
{
final NamedNodeMap attrs = stringNode.getAttributes();
((Map<Object, Object>) map).put(parseObject(eventManager, keyType, parseString(attrs, "key")), parseObject(eventManager, valueType, parseString(attrs, "value")));
break;
}
case "item":
{
final NamedNodeMap attrs = stringNode.getAttributes();
((Map<Object, ItemHolder>) map).put(parseObject(eventManager, keyType, parseString(attrs, "key")), new ItemHolder(parseInteger(stringNode.getAttributes(), "id"), parseLong(stringNode.getAttributes(), "count")));
break;
}
case "skill":
{
final NamedNodeMap attrs = stringNode.getAttributes();
((Map<Object, SkillHolder>) map).put(parseObject(eventManager, keyType, parseString(attrs, "key")), new SkillHolder(parseInteger(stringNode.getAttributes(), "id"), parseInteger(stringNode.getAttributes(), "level")));
break;
}
case "location":
{
final NamedNodeMap attrs = stringNode.getAttributes();
((Map<Object, Location>) map).put(parseObject(eventManager, keyType, parseString(attrs, "key")), new Location(parseInteger(stringNode.getAttributes(), "x"), parseInteger(stringNode.getAttributes(), "y"), parseInteger(stringNode.getAttributes(), "z", parseInteger(stringNode.getAttributes(), "heading", 0))));
break;
}
default:
{
LOGGER.warning(getClass().getSimpleName() + ": Unhandled map case: " + name + " " + stringNode.getNodeName() + " for event: " + eventManager.getClass().getSimpleName());
}
}
});
variables.set(name, map);
}
private Class<?> getClassByName(AbstractEventManager<?> eventManager, String name)
{
switch (name)
{
case "Byte":
{
return Byte.class;
}
case "Short":
{
return Short.class;
}
case "Integer":
{
return Integer.class;
}
case "Float":
{
return Float.class;
}
case "Long":
{
return Long.class;
}
case "Double":
{
return Double.class;
}
case "String":
{
return String.class;
}
case "ItemHolder":
{
return ItemHolder.class;
}
case "SkillHolder":
{
return SkillHolder.class;
}
case "Location":
{
return Location.class;
}
default:
{
LOGGER.warning(getClass().getSimpleName() + ": Unhandled class case: " + name + " for event: " + eventManager.getClass().getSimpleName());
return Object.class;
}
}
}
private Object parseObject(AbstractEventManager<?> eventManager, String type, String value)
{
switch (type)
{
case "Byte":
{
return Byte.decode(value);
}
case "Short":
{
return Short.decode(value);
}
case "Integer":
{
return Integer.decode(value);
}
case "Float":
{
return Float.parseFloat(value);
}
case "Long":
{
return Long.decode(value);
}
case "Double":
{
return Double.parseDouble(value);
}
case "String":
{
return value;
}
default:
{
LOGGER.warning(getClass().getSimpleName() + ": Unhandled object case: " + type + " for event: " + eventManager.getClass().getSimpleName());
return null;
}
}
}
private static <T> List<T> newList(Class<T> type)
{
return new ArrayList<>();
}
private static <K, V> Map<K, V> newMap(Class<K> keyClass, Class<V> valueClass)
{
return new LinkedHashMap<>();
}
/**
* Gets the single instance of EventEngineData.
* @return single instance of EventEngineData
*/
public static EventEngineData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final EventEngineData _instance = new EventEngineData();
}
}

View File

@@ -0,0 +1,141 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
/**
* This class holds the Experience points for each level for players and pets.
* @author mrTJO
*/
public final class ExperienceData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ExperienceData.class.getName());
private final Map<Integer, Long> _expTable = new HashMap<>();
private byte MAX_LEVEL;
private byte MAX_PET_LEVEL;
/**
* Instantiates a new experience table.
*/
protected ExperienceData()
{
load();
}
@Override
public void load()
{
_expTable.clear();
parseDatapackFile("data/stats/experience.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _expTable.size() + " levels.");
LOGGER.info(getClass().getSimpleName() + ": Max Player Level is: " + (MAX_LEVEL - 1));
LOGGER.info(getClass().getSimpleName() + ": Max Pet Level is: " + (MAX_PET_LEVEL - 1));
}
@Override
public void parseDocument(Document doc, File f)
{
final Node table = doc.getFirstChild();
final NamedNodeMap tableAttr = table.getAttributes();
MAX_LEVEL = (byte) (Byte.parseByte(tableAttr.getNamedItem("maxLevel").getNodeValue()) + 1);
MAX_PET_LEVEL = (byte) (Byte.parseByte(tableAttr.getNamedItem("maxPetLevel").getNodeValue()) + 1);
if (MAX_LEVEL > Config.PLAYER_MAXIMUM_LEVEL)
{
MAX_LEVEL = Config.PLAYER_MAXIMUM_LEVEL;
}
if (MAX_PET_LEVEL > MAX_LEVEL)
{
MAX_PET_LEVEL = MAX_LEVEL; // Pet level should not exceed owner level.
}
int maxLevel = 0;
for (Node n = table.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("experience".equals(n.getNodeName()))
{
final NamedNodeMap attrs = n.getAttributes();
maxLevel = parseInteger(attrs, "level");
if (maxLevel > Config.PLAYER_MAXIMUM_LEVEL)
{
break;
}
_expTable.put(maxLevel, parseLong(attrs, "tolevel"));
}
}
}
/**
* Gets the exp for level.
* @param level the level required.
* @return the experience points required to reach the given level.
*/
public long getExpForLevel(int level)
{
if (level > Config.PLAYER_MAXIMUM_LEVEL)
{
level = Config.PLAYER_MAXIMUM_LEVEL;
}
return _expTable.get(level);
}
/**
* Gets the max level.
* @return the maximum level acquirable by a player.
*/
public byte getMaxLevel()
{
return MAX_LEVEL;
}
/**
* Gets the max pet level.
* @return the maximum level acquirable by a pet.
*/
public byte getMaxPetLevel()
{
return MAX_PET_LEVEL;
}
/**
* Gets the single instance of ExperienceTable.
* @return single instance of ExperienceTable
*/
public static ExperienceData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ExperienceData _instance = new ExperienceData();
}
}

View File

@@ -0,0 +1,205 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.handler.ConditionHandler;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.conditions.ICondition;
import com.l2jmobius.gameserver.model.holders.ExtendDropDataHolder;
import com.l2jmobius.gameserver.model.holders.ExtendDropItemHolder;
import com.l2jmobius.gameserver.network.SystemMessageId;
/**
* @author Sdw
*/
public class ExtendDropData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ExtendDropData.class.getName());
private final Map<Integer, ExtendDropDataHolder> _extendDrop = new HashMap<>();
protected ExtendDropData()
{
load();
}
@Override
public void load()
{
_extendDrop.clear();
parseDatapackFile("data/ExtendDrop.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _extendDrop.size() + " ExtendDrop.");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "drop", dropNode ->
{
final StatsSet set = new StatsSet(parseAttributes(dropNode));
final List<ExtendDropItemHolder> items = new ArrayList<>(1);
forEach(dropNode, "items", itemsNode -> forEach(itemsNode, "item", itemNode ->
{
final int itemId = parseInteger(itemNode.getAttributes(), "id");
final int itemCount = parseInteger(itemNode.getAttributes(), "count");
final int itemMaxCount = parseInteger(itemNode.getAttributes(), "maxCount");
final double itemChance = parseDouble(itemNode.getAttributes(), "chance");
final double itemAdditionalChance = parseDouble(itemNode.getAttributes(), "additionalChance");
items.add(new ExtendDropItemHolder(itemId, itemCount, itemMaxCount, itemChance, itemAdditionalChance));
}));
set.set("items", items);
final List<ICondition> conditions = new ArrayList<>(1);
forEach(dropNode, "conditions", conditionsNode -> forEach(conditionsNode, "condition", conditionNode ->
{
final String conditionName = parseString(conditionNode.getAttributes(), "name");
final StatsSet params = (StatsSet) parseValue(conditionNode);
final Function<StatsSet, ICondition> conditionFunction = ConditionHandler.getInstance().getHandlerFactory(conditionName);
if (conditionFunction != null)
{
conditions.add(conditionFunction.apply(params));
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Missing condition for ExtendDrop Id[" + set.getInt("id") + "] Condition Name[" + conditionName + "]");
}
}));
set.set("conditions", conditions);
final Map<Long, SystemMessageId> systemMessages = new HashMap<>();
forEach(dropNode, "systemMessages", systemMessagesNode -> forEach(systemMessagesNode, "systemMessage", systemMessageNode ->
{
final long amount = parseLong(systemMessageNode.getAttributes(), "amount");
final SystemMessageId systemMessageId = SystemMessageId.getSystemMessageId(parseInteger(systemMessageNode.getAttributes(), "id"));
systemMessages.put(amount, systemMessageId);
}));
set.set("systemMessages", systemMessages);
_extendDrop.put(set.getInt("id"), new ExtendDropDataHolder(set));
}));
}
private Object parseValue(Node node)
{
StatsSet statsSet = null;
List<Object> list = null;
Object text = null;
for (node = node.getFirstChild(); node != null; node = node.getNextSibling())
{
final String nodeName = node.getNodeName();
switch (node.getNodeName())
{
case "#text":
{
final String value = node.getNodeValue().trim();
if (!value.isEmpty())
{
text = value;
}
break;
}
case "item":
{
if (list == null)
{
list = new LinkedList<>();
}
final Object value = parseValue(node);
if (value != null)
{
list.add(value);
}
break;
}
default:
{
final Object value = parseValue(node);
if (value != null)
{
if (statsSet == null)
{
statsSet = new StatsSet();
}
statsSet.set(nodeName, value);
}
}
}
}
if (list != null)
{
if (text != null)
{
throw new IllegalArgumentException("Text and list in same node are not allowed. Node[" + node + "]");
}
if (statsSet != null)
{
statsSet.set(".", list);
}
else
{
return list;
}
}
if (text != null)
{
if (list != null)
{
throw new IllegalArgumentException("Text and list in same node are not allowed. Node[" + node + "]");
}
if (statsSet != null)
{
statsSet.set(".", text);
}
else
{
return text;
}
}
return statsSet;
}
public ExtendDropDataHolder getExtendDropById(int id)
{
return _extendDrop.getOrDefault(id, null);
}
public static ExtendDropData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ExtendDropData _instance = new ExtendDropData();
}
}

View File

@@ -0,0 +1,221 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.FishingBaitData;
/**
* This class holds the Fishing information.
* @author bit
*/
public final class FishingData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(FishingData.class.getName());
private final Map<Integer, FishingBaitData> _baitData = new HashMap<>();
private int _minPlayerLevel;
private int _baitDistanceMin;
private int _baitDistanceMax;
private int _fishingTimeMin;
private int _fishingTimeMax;
private int _fishingTimeWaitMin;
private int _fishingTimeWaitMax;
private int _expRateMin;
private int _expRateMax;
private int _spRateMin;
private int _spRateMax;
/**
* Instantiates a new fishing data.
*/
protected FishingData()
{
load();
}
@Override
public void load()
{
_baitData.clear();
parseDatapackFile("data/Fishing.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded Fishing Data.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node listItem = n.getFirstChild(); listItem != null; listItem = listItem.getNextSibling())
{
switch (listItem.getNodeName())
{
case "playerLevel":
{
_minPlayerLevel = parseInteger(listItem.getAttributes(), "min");
break;
}
case "baitDistance":
{
_baitDistanceMin = parseInteger(listItem.getAttributes(), "min");
_baitDistanceMax = parseInteger(listItem.getAttributes(), "max");
break;
}
case "fishingTime":
{
_fishingTimeMin = parseInteger(listItem.getAttributes(), "min");
_fishingTimeMax = parseInteger(listItem.getAttributes(), "max");
break;
}
case "fishingTimeWait":
{
_fishingTimeWaitMin = parseInteger(listItem.getAttributes(), "min");
_fishingTimeWaitMax = parseInteger(listItem.getAttributes(), "max");
break;
}
case "experienceRate":
{
_expRateMin = parseInteger(listItem.getAttributes(), "min");
_expRateMax = parseInteger(listItem.getAttributes(), "max");
break;
}
case "skillPointsRate":
{
_spRateMin = parseInteger(listItem.getAttributes(), "min");
_spRateMax = parseInteger(listItem.getAttributes(), "max");
break;
}
case "baits":
{
for (Node bait = listItem.getFirstChild(); bait != null; bait = bait.getNextSibling())
{
if ("bait".equalsIgnoreCase(bait.getNodeName()))
{
final NamedNodeMap attrs = bait.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
final int level = parseInteger(attrs, "level");
final double chance = parseDouble(attrs, "chance");
final FishingBaitData baitData = new FishingBaitData(itemId, level, chance);
for (Node c = bait.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("catch".equalsIgnoreCase(c.getNodeName()))
{
baitData.addReward(parseInteger(c.getAttributes(), "itemId"));
}
}
_baitData.put(baitData.getItemId(), baitData);
}
}
break;
}
}
}
}
}
}
/**
* Gets the fishing rod.
* @param baitItemId the item id
* @return A list of reward item ids
*/
public FishingBaitData getBaitData(int baitItemId)
{
return _baitData.get(baitItemId);
}
public int getMinPlayerLevel()
{
return _minPlayerLevel;
}
public int getBaitDistanceMin()
{
return _baitDistanceMin;
}
public int getBaitDistanceMax()
{
return _baitDistanceMax;
}
public int getFishingTimeMin()
{
return _fishingTimeMin;
}
public int getFishingTimeMax()
{
return _fishingTimeMax;
}
public int getFishingTimeWaitMin()
{
return _fishingTimeWaitMin;
}
public int getFishingTimeWaitMax()
{
return _fishingTimeWaitMax;
}
public int getExpRateMin()
{
return _expRateMin;
}
public int getExpRateMax()
{
return _expRateMax;
}
public int getSpRateMin()
{
return _spRateMin;
}
public int getSpRateMax()
{
return _spRateMax;
}
/**
* Gets the single instance of FishingData.
* @return single instance of FishingData
*/
public static FishingData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final FishingData _instance = new FishingData();
}
}

View File

@@ -0,0 +1,182 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.items.L2Henna;
/**
* This class holds the henna related information.<br>
* Cost and required amount to add the henna to the player.<br>
* Cost and retrieved amount for removing the henna from the player.<br>
* Allowed classes to wear each henna.
* @author Zoey76
*/
public final class HennaData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(HennaData.class.getName());
private final Map<Integer, L2Henna> _hennaList = new HashMap<>();
/**
* Instantiates a new henna data.
*/
protected HennaData()
{
load();
}
@Override
public void load()
{
_hennaList.clear();
parseDatapackFile("data/stats/hennaList.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _hennaList.size() + " Henna data.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equals(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("henna".equals(d.getNodeName()))
{
parseHenna(d);
}
}
}
}
}
/**
* Parses the henna.
* @param d the d
*/
private void parseHenna(Node d)
{
final StatsSet set = new StatsSet();
final List<ClassId> wearClassIds = new ArrayList<>();
NamedNodeMap attrs = d.getAttributes();
Node attr;
for (int i = 0; i < attrs.getLength(); i++)
{
attr = attrs.item(i);
set.set(attr.getNodeName(), attr.getNodeValue());
}
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
final String name = c.getNodeName();
attrs = c.getAttributes();
switch (name)
{
case "stats":
{
for (int i = 0; i < attrs.getLength(); i++)
{
attr = attrs.item(i);
set.set(attr.getNodeName(), attr.getNodeValue());
}
break;
}
case "wear":
{
attr = attrs.getNamedItem("count");
set.set("wear_count", attr.getNodeValue());
attr = attrs.getNamedItem("fee");
set.set("wear_fee", attr.getNodeValue());
break;
}
case "cancel":
{
attr = attrs.getNamedItem("count");
set.set("cancel_count", attr.getNodeValue());
attr = attrs.getNamedItem("fee");
set.set("cancel_fee", attr.getNodeValue());
break;
}
case "classId":
{
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
break;
}
}
}
final L2Henna henna = new L2Henna(set);
henna.setWearClassIds(wearClassIds);
_hennaList.put(henna.getDyeId(), henna);
}
/**
* Gets the henna.
* @param id of the dye.
* @return the dye with that id.
*/
public L2Henna getHenna(int id)
{
return _hennaList.get(id);
}
/**
* Gets the henna list.
* @param classId the player's class Id.
* @return the list with all the allowed dyes.
*/
public List<L2Henna> getHennaList(ClassId classId)
{
final List<L2Henna> list = new ArrayList<>();
for (L2Henna henna : _hennaList.values())
{
if (henna.isAllowedClass(classId))
{
list.add(henna);
}
}
return list;
}
/**
* Gets the single instance of HennaData.
* @return single instance of HennaData
*/
public static HennaData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final HennaData _instance = new HennaData();
}
}

View File

@@ -0,0 +1,177 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.GameTimeController;
import com.l2jmobius.gameserver.model.actor.L2Character;
/**
* This class load, holds and calculates the hit condition bonuses.
* @author Nik
*/
public final class HitConditionBonusData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(HitConditionBonusData.class.getName());
private int frontBonus = 0;
private int sideBonus = 0;
private int backBonus = 0;
private int highBonus = 0;
private int lowBonus = 0;
private int darkBonus = 0;
private int rainBonus = 0;
/**
* Instantiates a new hit condition bonus.
*/
protected HitConditionBonusData()
{
load();
}
@Override
public void load()
{
parseDatapackFile("data/stats/hitConditionBonus.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded Hit Condition bonuses.");
if (Config.DEBUG)
{
LOGGER.info(getClass().getSimpleName() + ": Front bonus: " + frontBonus);
LOGGER.info(getClass().getSimpleName() + ": Side bonus: " + sideBonus);
LOGGER.info(getClass().getSimpleName() + ": Back bonus: " + backBonus);
LOGGER.info(getClass().getSimpleName() + ": High bonus: " + highBonus);
LOGGER.info(getClass().getSimpleName() + ": Low bonus: " + lowBonus);
LOGGER.info(getClass().getSimpleName() + ": Dark bonus: " + darkBonus);
LOGGER.info(getClass().getSimpleName() + ": Rain bonus: " + rainBonus);
}
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node d = doc.getFirstChild().getFirstChild(); d != null; d = d.getNextSibling())
{
final NamedNodeMap attrs = d.getAttributes();
switch (d.getNodeName())
{
case "front":
{
frontBonus = parseInteger(attrs, "val");
break;
}
case "side":
{
sideBonus = parseInteger(attrs, "val");
break;
}
case "back":
{
backBonus = parseInteger(attrs, "val");
break;
}
case "high":
{
highBonus = parseInteger(attrs, "val");
break;
}
case "low":
{
lowBonus = parseInteger(attrs, "val");
break;
}
case "dark":
{
darkBonus = parseInteger(attrs, "val");
break;
}
case "rain":
{
rainBonus = parseInteger(attrs, "val");
break;
}
}
}
}
/**
* Gets the condition bonus.
* @param attacker the attacking character.
* @param target the attacked character.
* @return the bonus of the attacker against the target.
*/
public double getConditionBonus(L2Character attacker, L2Character target)
{
double mod = 100;
// Get high or low bonus
if ((attacker.getZ() - target.getZ()) > 50)
{
mod += highBonus;
}
else if ((attacker.getZ() - target.getZ()) < -50)
{
mod += lowBonus;
}
// Get weather bonus
if (GameTimeController.getInstance().isNight())
{
mod += darkBonus;
// else if () No rain support yet.
// chance += hitConditionBonus.rainBonus;
}
// Get side bonus
if (attacker.isBehindTarget(true))
{
mod += backBonus;
}
else if (attacker.isInFrontOfTarget())
{
mod += frontBonus;
}
else
{
mod += sideBonus;
}
// If (mod / 100) is less than 0, return 0, because we can't lower more than 100%.
return Math.max(mod / 100, 0);
}
/**
* Gets the single instance of HitConditionBonus.
* @return single instance of HitConditionBonus
*/
public static HitConditionBonusData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final HitConditionBonusData _instance = new HitConditionBonusData();
}
}

View File

@@ -0,0 +1,142 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.items.PcItemTemplate;
/**
* This class holds the Initial Equipment information.<br>
* What items get each newly created character and if this item is equipped upon creation (<b>Requires the item to be equippable</b>).
* @author Zoey76
*/
public final class InitialEquipmentData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(InitialEquipmentData.class.getName());
private final Map<ClassId, List<PcItemTemplate>> _initialEquipmentList = new HashMap<>();
private static final String NORMAL = "data/stats/initialEquipment.xml";
private static final String EVENT = "data/stats/initialEquipmentEvent.xml";
/**
* Instantiates a new initial equipment data.
*/
protected InitialEquipmentData()
{
load();
}
@Override
public void load()
{
_initialEquipmentList.clear();
parseDatapackFile(Config.INITIAL_EQUIPMENT_EVENT ? EVENT : NORMAL);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _initialEquipmentList.size() + " Initial Equipment data.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("equipment".equalsIgnoreCase(d.getNodeName()))
{
parseEquipment(d);
}
}
}
}
}
/**
* Parses the equipment.
* @param d parse an initial equipment and add it to {@link #_initialEquipmentList}
*/
private void parseEquipment(Node d)
{
NamedNodeMap attrs = d.getAttributes();
final ClassId classId = ClassId.getClassId(Integer.parseInt(attrs.getNamedItem("classId").getNodeValue()));
final List<PcItemTemplate> equipList = new ArrayList<>();
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("item".equalsIgnoreCase(c.getNodeName()))
{
final StatsSet set = new StatsSet();
attrs = c.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node attr = attrs.item(i);
set.set(attr.getNodeName(), attr.getNodeValue());
}
equipList.add(new PcItemTemplate(set));
}
}
_initialEquipmentList.put(classId, equipList);
}
/**
* Gets the equipment list.
* @param cId the class Id for the required initial equipment.
* @return the initial equipment for the given class Id.
*/
public List<PcItemTemplate> getEquipmentList(ClassId cId)
{
return _initialEquipmentList.get(cId);
}
/**
* Gets the equipment list.
* @param cId the class Id for the required initial equipment.
* @return the initial equipment for the given class Id.
*/
public List<PcItemTemplate> getEquipmentList(int cId)
{
return _initialEquipmentList.get(ClassId.getClassId(cId));
}
/**
* Gets the single instance of InitialEquipmentData.
* @return single instance of InitialEquipmentData
*/
public static InitialEquipmentData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final InitialEquipmentData _instance = new InitialEquipmentData();
}
}

View File

@@ -0,0 +1,371 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.MacroType;
import com.l2jmobius.gameserver.enums.ShortcutType;
import com.l2jmobius.gameserver.model.Macro;
import com.l2jmobius.gameserver.model.MacroCmd;
import com.l2jmobius.gameserver.model.Shortcut;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance;
import com.l2jmobius.gameserver.network.serverpackets.ShortCutRegister;
/**
* This class holds the Initial Shortcuts information.<br>
* What shortcuts get each newly created character.
* @author Zoey76
*/
public final class InitialShortcutData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(InitialShortcutData.class.getName());
private final Map<ClassId, List<Shortcut>> _initialShortcutData = new HashMap<>();
private final List<Shortcut> _initialGlobalShortcutList = new ArrayList<>();
private final Map<Integer, Macro> _macroPresets = new HashMap<>();
/**
* Instantiates a new initial shortcuts data.
*/
protected InitialShortcutData()
{
load();
}
@Override
public void load()
{
_initialShortcutData.clear();
_initialGlobalShortcutList.clear();
parseDatapackFile("data/stats/initialShortcuts.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _initialGlobalShortcutList.size() + " Initial Global Shortcuts data.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _initialShortcutData.size() + " Initial Shortcuts data.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _macroPresets.size() + " Macros presets.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equals(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
switch (d.getNodeName())
{
case "shortcuts":
{
parseShortcuts(d);
break;
}
case "macros":
{
parseMacros(d);
break;
}
}
}
}
}
}
/**
* Parses a shortcut.
* @param d the node
*/
private void parseShortcuts(Node d)
{
NamedNodeMap attrs = d.getAttributes();
final Node classIdNode = attrs.getNamedItem("classId");
final List<Shortcut> list = new ArrayList<>();
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("page".equals(c.getNodeName()))
{
attrs = c.getAttributes();
final int pageId = parseInteger(attrs, "pageId");
for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("slot".equals(b.getNodeName()))
{
list.add(createShortcut(pageId, b));
}
}
}
}
if (classIdNode != null)
{
_initialShortcutData.put(ClassId.getClassId(Integer.parseInt(classIdNode.getNodeValue())), list);
}
else
{
_initialGlobalShortcutList.addAll(list);
}
}
/**
* Parses a macro.
* @param d the node
*/
private void parseMacros(Node d)
{
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("macro".equals(c.getNodeName()))
{
NamedNodeMap attrs = c.getAttributes();
if (!parseBoolean(attrs, "enabled", true))
{
continue;
}
final int macroId = parseInteger(attrs, "macroId");
final int icon = parseInteger(attrs, "icon");
final String name = parseString(attrs, "name");
final String description = parseString(attrs, "description");
final String acronym = parseString(attrs, "acronym");
final List<MacroCmd> commands = new ArrayList<>(1);
int entry = 0;
for (Node b = c.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("command".equals(b.getNodeName()))
{
attrs = b.getAttributes();
final MacroType type = parseEnum(attrs, MacroType.class, "type");
int d1 = 0;
int d2 = 0;
final String cmd = b.getTextContent();
switch (type)
{
case SKILL:
{
d1 = parseInteger(attrs, "skillId"); // Skill ID
d2 = parseInteger(attrs, "skillLvl", 0); // Skill level
break;
}
case ACTION:
{
// Not handled by client.
d1 = parseInteger(attrs, "actionId");
break;
}
case TEXT:
{
// Doesn't have numeric parameters.
break;
}
case SHORTCUT:
{
d1 = parseInteger(attrs, "page"); // Page
d2 = parseInteger(attrs, "slot", 0); // Slot
break;
}
case ITEM:
{
// Not handled by client.
d1 = parseInteger(attrs, "itemId");
break;
}
case DELAY:
{
d1 = parseInteger(attrs, "delay"); // Delay in seconds
break;
}
}
commands.add(new MacroCmd(entry++, type, d1, d2, cmd));
}
}
_macroPresets.put(macroId, new Macro(macroId, icon, name, description, acronym, commands));
}
}
}
/**
* Parses a node an create a shortcut from it.
* @param pageId the page ID
* @param b the node to parse
* @return the new shortcut
*/
private Shortcut createShortcut(int pageId, Node b)
{
final NamedNodeMap attrs = b.getAttributes();
final int slotId = parseInteger(attrs, "slotId");
final ShortcutType shortcutType = parseEnum(attrs, ShortcutType.class, "shortcutType");
final int shortcutId = parseInteger(attrs, "shortcutId");
final int shortcutLevel = parseInteger(attrs, "shortcutLevel", 0);
final int characterType = parseInteger(attrs, "characterType", 0);
return new Shortcut(slotId, pageId, shortcutType, shortcutId, shortcutLevel, characterType);
}
/**
* Gets the shortcut list.
* @param cId the class ID for the shortcut list
* @return the shortcut list for the give class ID
*/
public List<Shortcut> getShortcutList(ClassId cId)
{
return _initialShortcutData.get(cId);
}
/**
* Gets the shortcut list.
* @param cId the class ID for the shortcut list
* @return the shortcut list for the give class ID
*/
public List<Shortcut> getShortcutList(int cId)
{
return _initialShortcutData.get(ClassId.getClassId(cId));
}
/**
* Gets the global shortcut list.
* @return the global shortcut list
*/
public List<Shortcut> getGlobalMacroList()
{
return _initialGlobalShortcutList;
}
/**
* Register all the available shortcuts for the given player.
* @param player the player
*/
public void registerAllShortcuts(L2PcInstance player)
{
if (player == null)
{
return;
}
// Register global shortcuts.
for (Shortcut shortcut : _initialGlobalShortcutList)
{
int shortcutId = shortcut.getId();
switch (shortcut.getType())
{
case ITEM:
{
final L2ItemInstance item = player.getInventory().getItemByItemId(shortcutId);
if (item == null)
{
continue;
}
shortcutId = item.getObjectId();
break;
}
case SKILL:
{
if (!player.getSkills().containsKey(shortcutId))
{
continue;
}
break;
}
case MACRO:
{
final Macro macro = _macroPresets.get(shortcutId);
if (macro == null)
{
continue;
}
player.registerMacro(macro);
break;
}
}
// Register shortcut
final Shortcut newShortcut = new Shortcut(shortcut.getSlot(), shortcut.getPage(), shortcut.getType(), shortcutId, shortcut.getLevel(), shortcut.getCharacterType());
player.sendPacket(new ShortCutRegister(newShortcut));
player.registerShortCut(newShortcut);
}
// Register class specific shortcuts.
if (_initialShortcutData.containsKey(player.getClassId()))
{
for (Shortcut shortcut : _initialShortcutData.get(player.getClassId()))
{
int shortcutId = shortcut.getId();
switch (shortcut.getType())
{
case ITEM:
{
final L2ItemInstance item = player.getInventory().getItemByItemId(shortcutId);
if (item == null)
{
continue;
}
shortcutId = item.getObjectId();
break;
}
case SKILL:
{
if (!player.getSkills().containsKey(shortcut.getId()))
{
continue;
}
break;
}
case MACRO:
{
final Macro macro = _macroPresets.get(shortcutId);
if (macro == null)
{
continue;
}
player.registerMacro(macro);
break;
}
}
// Register shortcut
final Shortcut newShortcut = new Shortcut(shortcut.getSlot(), shortcut.getPage(), shortcut.getType(), shortcutId, shortcut.getLevel(), shortcut.getCharacterType());
player.sendPacket(new ShortCutRegister(newShortcut));
player.registerShortCut(newShortcut);
}
}
}
/**
* Gets the single instance of InitialEquipmentData.
* @return single instance of InitialEquipmentData
*/
public static InitialShortcutData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final InitialShortcutData _instance = new InitialShortcutData();
}
}

View File

@@ -0,0 +1,102 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.CrystalizationData;
import com.l2jmobius.gameserver.model.holders.ItemChanceHolder;
/**
* @author UnAfraid
*/
public final class ItemCrystalizationData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ItemCrystalizationData.class.getName());
private final Map<Integer, CrystalizationData> _items = new HashMap<>();
protected ItemCrystalizationData()
{
load();
}
@Override
public void load()
{
parseDatapackFile("data/CrystalizableItems.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _items.size() + " Items");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("crystalizable_item".equalsIgnoreCase(d.getNodeName()))
{
final int id = parseInteger(d.getAttributes(), "id");
final CrystalizationData data = new CrystalizationData(id);
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("item".equalsIgnoreCase(c.getNodeName()))
{
final NamedNodeMap attrs = c.getAttributes();
final int itemId = parseInteger(attrs, "id");
final long itemCount = parseLong(attrs, "count");
final double itemChance = parseDouble(attrs, "chance");
data.addItem(new ItemChanceHolder(itemId, itemChance, itemCount));
}
}
_items.put(id, data);
}
}
}
}
}
public CrystalizationData getCrystalization(int itemId)
{
return _items.get(itemId);
}
/**
* Gets the single instance of ItemCrystalizationData.
* @return single instance of ItemCrystalizationData
*/
public static ItemCrystalizationData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ItemCrystalizationData _instance = new ItemCrystalizationData();
}
}

View File

@@ -0,0 +1,99 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
/**
* @author UnAfraid
*/
public class KarmaData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(KarmaData.class.getName());
private final Map<Integer, Double> _karmaTable = new HashMap<>();
public KarmaData()
{
load();
}
@Override
public synchronized void load()
{
_karmaTable.clear();
parseDatapackFile("data/stats/chars/pcKarmaIncrease.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _karmaTable.size() + " karma modifiers.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("pcKarmaIncrease".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("increase".equalsIgnoreCase(d.getNodeName()))
{
final NamedNodeMap attrs = d.getAttributes();
final int level = parseInteger(attrs, "lvl");
if (level >= Config.PLAYER_MAXIMUM_LEVEL)
{
break;
}
_karmaTable.put(level, parseDouble(attrs, "val"));
}
}
}
}
}
/**
* @param level
* @return {@code double} modifier used to calculate karma lost upon death.
*/
public double getMultiplier(int level)
{
return _karmaTable.get(level);
}
/**
* Gets the single instance of KarmaData.
* @return single instance of KarmaData
*/
public static KarmaData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final KarmaData _instance = new KarmaData();
}
}

View File

@@ -0,0 +1,165 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.Rnd;
import com.l2jmobius.gameserver.model.holders.ItemHolder;
/**
* @author Mathael
*/
public class LuckyGameData implements IGameXmlReader
{
private static final List<ItemHolder> _fortuneReadingTicketRewards = new ArrayList<>();
private static final List<ItemHolder> _luxuryFortuneReadingTicketRewards = new ArrayList<>();
private static final List<ItemHolder> _rareLuxuryFortuneReadingTicketRewards = new ArrayList<>();
protected LuckyGameData()
{
load();
}
@Override
public void load()
{
_fortuneReadingTicketRewards.clear();
_luxuryFortuneReadingTicketRewards.clear();
_rareLuxuryFortuneReadingTicketRewards.clear();
parseDatapackFile("data/LuckyGameData.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _fortuneReadingTicketRewards.size() + " Normal item rewards.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _luxuryFortuneReadingTicketRewards.size() + " Luxury item rewards.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _rareLuxuryFortuneReadingTicketRewards.size() + " Rare item rewards.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
final NamedNodeMap at = n.getAttributes();
final Node attribute = at.getNamedItem("enabled");
if ((attribute != null) && Boolean.parseBoolean(attribute.getNodeValue())) // <list enabled="true"
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("fortuneReadingTicketRewards".equalsIgnoreCase(d.getNodeName()))
{
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("item".equalsIgnoreCase(b.getNodeName()))
{
final NamedNodeMap attrs = b.getAttributes();
final int itemId = parseInteger(attrs, "id");
final int count = parseInteger(attrs, "count");
if ((itemId == 0) || (count == 0))
{
LOGGER.severe(getClass().getSimpleName() + ": itemId: [" + itemId + "] count: [" + count + "] cannot be zero.");
return;
}
_fortuneReadingTicketRewards.add(new ItemHolder(itemId, count));
}
}
}
else if ("luxuryFortuneReadingTicketRewards".equalsIgnoreCase(d.getNodeName()))
{
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("item".equalsIgnoreCase(b.getNodeName()))
{
final NamedNodeMap attrs = b.getAttributes();
final int itemId = parseInteger(attrs, "id");
final int count = parseInteger(attrs, "count");
if ((itemId == 0) || (count == 0))
{
LOGGER.severe(getClass().getSimpleName() + ": itemId: [" + itemId + "] count: [" + count + "] cannot be zero.");
return;
}
_luxuryFortuneReadingTicketRewards.add(new ItemHolder(itemId, count));
}
}
}
else if ("rareLuxuryFortuneReadingTicketRewards".equalsIgnoreCase(d.getNodeName()))
{
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("item".equalsIgnoreCase(b.getNodeName()))
{
final NamedNodeMap attrs = b.getAttributes();
final int itemId = parseInteger(attrs, "id");
final int count = parseInteger(attrs, "count");
if ((itemId == 0) || (count == 0))
{
LOGGER.severe(getClass().getSimpleName() + ": itemId: [" + itemId + "] count: [" + count + "] cannot be zero.");
return;
}
_rareLuxuryFortuneReadingTicketRewards.add(new ItemHolder(itemId, count));
}
}
}
}
}
}
}
}
public static ItemHolder getRandomNormalReward()
{
return _fortuneReadingTicketRewards.get(Rnd.get(_fortuneReadingTicketRewards.size()));
}
public static ItemHolder getRandomLuxuryReward()
{
return _luxuryFortuneReadingTicketRewards.get(Rnd.get(_luxuryFortuneReadingTicketRewards.size()));
}
public static ItemHolder getRandomRareReward()
{
return _rareLuxuryFortuneReadingTicketRewards.get(Rnd.get(_rareLuxuryFortuneReadingTicketRewards.size()));
}
public static LuckyGameData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final LuckyGameData _instance = new LuckyGameData();
}
}

View File

@@ -0,0 +1,456 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.io.FileFilter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.file.filter.NumericNameFilter;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.L2Npc;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.multisell.Entry;
import com.l2jmobius.gameserver.model.multisell.Ingredient;
import com.l2jmobius.gameserver.model.multisell.ListContainer;
import com.l2jmobius.gameserver.model.multisell.PreparedListContainer;
import com.l2jmobius.gameserver.network.SystemMessageId;
import com.l2jmobius.gameserver.network.serverpackets.ExPCCafePointInfo;
import com.l2jmobius.gameserver.network.serverpackets.MultiSellList;
import com.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import com.l2jmobius.gameserver.network.serverpackets.UserInfo;
import com.l2jmobius.gameserver.util.Util;
public final class MultisellData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(MultisellData.class.getName());
private final Map<Integer, ListContainer> _entries = new HashMap<>();
public static final int PAGE_SIZE = 40;
// Special IDs.
public static final int PC_CAFE_POINTS = -100;
public static final int CLAN_REPUTATION = -200;
public static final int FAME = -300;
public static final int FIELD_CYCLE_POINTS = -400;
public static final int RAIDBOSS_POINTS = -500;
// Misc
private static final FileFilter NUMERIC_FILTER = new NumericNameFilter();
protected MultisellData()
{
load();
}
@Override
public void load()
{
_entries.clear();
parseDatapackDirectory("data/multisell", false);
if (Config.CUSTOM_MULTISELL_LOAD)
{
parseDatapackDirectory("data/multisell/custom", false);
}
verify();
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _entries.size() + " multisell lists.");
}
@Override
public void parseDocument(Document doc, File f)
{
try
{
final int id = Integer.parseInt(f.getName().replaceAll(".xml", ""));
int entryId = 1;
Node att;
final ListContainer list = new ListContainer(id);
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
list.setApplyTaxes(parseBoolean(n.getAttributes(), "applyTaxes", false));
list.setNewMultisell(parseBoolean(n.getAttributes(), "isNewMultisell", false));
list.setMaintainEnchantment(parseBoolean(n.getAttributes(), "maintainEnchantment", false));
att = n.getAttributes().getNamedItem("useRate");
if (att != null)
{
try
{
list.setUseRate(Double.valueOf(att.getNodeValue()));
if (list.getUseRate() <= 1e-6)
{
throw new NumberFormatException("The value cannot be 0"); // threat 0 as invalid value
}
}
catch (NumberFormatException e)
{
try
{
list.setUseRate(Config.class.getField(att.getNodeValue()).getDouble(Config.class));
}
catch (Exception e1)
{
LOGGER.warning(e1.getMessage() + doc.getLocalName());
list.setUseRate(1.0);
}
}
catch (DOMException e)
{
LOGGER.warning(e.getMessage() + doc.getLocalName());
}
}
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
final Entry e = parseEntry(d, entryId++, list);
list.getEntries().add(e);
}
else if ("npcs".equalsIgnoreCase(d.getNodeName()))
{
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("npc".equalsIgnoreCase(b.getNodeName()))
{
if (Util.isDigit(b.getTextContent()))
{
list.allowNpc(Integer.parseInt(b.getTextContent()));
}
}
}
}
}
}
}
_entries.put(id, list);
}
catch (Exception e)
{
LOGGER.log(Level.SEVERE, getClass().getSimpleName() + ": Error in file " + f, e);
}
}
@Override
public FileFilter getCurrentFileFilter()
{
return NUMERIC_FILTER;
}
private final Entry parseEntry(Node n, int entryId, ListContainer list)
{
final Node first = n.getFirstChild();
final Entry entry = new Entry(entryId);
NamedNodeMap attrs;
Node att;
StatsSet set;
for (n = first; n != null; n = n.getNextSibling())
{
if ("ingredient".equalsIgnoreCase(n.getNodeName()))
{
attrs = n.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
entry.addIngredient(new Ingredient(set));
}
else if ("production".equalsIgnoreCase(n.getNodeName()))
{
attrs = n.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
entry.addProduct(new Ingredient(set));
}
}
return entry;
}
/**
* This will generate the multisell list for the items.<br>
* There exist various parameters in multisells that affect the way they will appear:
* <ol>
* <li>Inventory only:
* <ul>
* <li>If true, only show items of the multisell for which the "primary" ingredients are already in the player's inventory. By "primary" ingredients we mean weapon and armor.</li>
* <li>If false, show the entire list.</li>
* </ul>
* </li>
* <li>Maintain enchantment: presumably, only lists with "inventory only" set to true should sometimes have this as true. This makes no sense otherwise...
* <ul>
* <li>If true, then the product will match the enchantment level of the ingredient.<br>
* If the player has multiple items that match the ingredient list but the enchantment levels differ, then the entries need to be duplicated to show the products and ingredients for each enchantment level.<br>
* For example: If the player has a crystal staff +1 and a crystal staff +3 and goes to exchange it at the mammon, the list should have all exchange possibilities for the +1 staff, followed by all possibilities for the +3 staff.</li>
* <li>If false, then any level ingredient will be considered equal and product will always be at +0</li>
* </ul>
* </li>
* <li>Apply taxes: Uses the "taxIngredient" entry in order to add a certain amount of adena to the ingredients.
* <li>
* <li>Additional product and ingredient multipliers.</li>
* </ol>
* @param listId
* @param player
* @param npc
* @param inventoryOnly
* @param productMultiplier
* @param ingredientMultiplier
*/
public final void separateAndSend(int listId, L2PcInstance player, L2Npc npc, boolean inventoryOnly, double productMultiplier, double ingredientMultiplier)
{
final ListContainer template = _entries.get(listId);
if (template == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Cannot find list ID: " + listId + " requested by player: " + player.getName() + ", NPC ID:" + (npc != null ? npc.getId() : 0));
return;
}
if (!template.isNpcAllowed(-1) && (((npc != null) && !template.isNpcAllowed(npc.getId())) || ((npc == null) && template.isNpcOnly())))
{
LOGGER.warning(getClass().getSimpleName() + ": Player " + player + " attempted to open multisell " + listId + " from npc " + npc + " which is not allowed!");
return;
}
final PreparedListContainer list = new PreparedListContainer(template, inventoryOnly, player, npc);
// Pass through this only when multipliers are different from 1
if ((productMultiplier != 1) || (ingredientMultiplier != 1))
{
list.getEntries().forEach(entry ->
{
// Math.max used here to avoid dropping count to 0
entry.getProducts().forEach(product -> product.setItemCount((long) Math.max(product.getItemCount() * productMultiplier, 1)));
// Math.max used here to avoid dropping count to 0
entry.getIngredients().forEach(ingredient -> ingredient.setItemCount((long) Math.max(ingredient.getItemCount() * ingredientMultiplier, 1)));
});
}
int index = 0;
do
{
// send list at least once even if size = 0
player.sendPacket(new MultiSellList(list, index));
index += PAGE_SIZE;
}
while (index < list.getEntries().size());
player.setMultiSell(list);
}
public final void separateAndSend(int listId, L2PcInstance player, L2Npc npc, boolean inventoryOnly)
{
separateAndSend(listId, player, npc, inventoryOnly, 1, 1);
}
public static boolean hasSpecialIngredient(int id, long amount, L2PcInstance player)
{
switch (id)
{
case PC_CAFE_POINTS:
{
if (player.getPcCafePoints() >= amount)
{
return true;
}
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_SHORT_OF_PC_POINTS));
break;
}
case CLAN_REPUTATION:
{
if (player.getClan() == null)
{
player.sendPacket(SystemMessageId.YOU_ARE_NOT_A_CLAN_MEMBER_AND_CANNOT_PERFORM_THIS_ACTION);
return false;
}
if (!player.isClanLeader())
{
player.sendPacket(SystemMessageId.ONLY_THE_CLAN_LEADER_IS_ENABLED);
return false;
}
if (player.getClan().getReputationScore() < amount)
{
player.sendPacket(SystemMessageId.THE_CLAN_REPUTATION_IS_TOO_LOW);
return false;
}
return true;
}
case FAME:
{
if (player.getFame() < amount)
{
player.sendPacket(SystemMessageId.YOU_DON_T_HAVE_ENOUGH_FAME_TO_DO_THAT);
return false;
}
return true;
}
case RAIDBOSS_POINTS:
{
if (player.getRaidbossPoints() < amount)
{
player.sendPacket(SystemMessageId.NOT_ENOUGH_RAID_POINTS);
return false;
}
return true;
}
}
return false;
}
public static boolean takeSpecialIngredient(int id, long amount, L2PcInstance player)
{
switch (id)
{
case PC_CAFE_POINTS:
{
final int cost = player.getPcCafePoints() - (int) amount;
player.setPcCafePoints(cost);
final SystemMessage smsgpc = SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_USING_S1_POINT);
smsgpc.addLong((int) amount);
player.sendPacket(smsgpc);
player.sendPacket(new ExPCCafePointInfo(player.getPcCafePoints(), (int) amount, 1));
return true;
}
case CLAN_REPUTATION:
{
player.getClan().takeReputationScore((int) amount, true);
final SystemMessage smsg = SystemMessage.getSystemMessage(SystemMessageId.S1_POINT_S_HAVE_BEEN_DEDUCTED_FROM_THE_CLAN_S_REPUTATION);
smsg.addLong(amount);
player.sendPacket(smsg);
return true;
}
case FAME:
{
player.setFame(player.getFame() - (int) amount);
player.sendPacket(new UserInfo(player));
// player.sendPacket(new ExBrExtraUserInfo(player));
return true;
}
case RAIDBOSS_POINTS:
{
player.setRaidbossPoints(player.getRaidbossPoints() - (int) amount);
player.sendPacket(new UserInfo(player));
player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.YOU_CONSUMED_S1_RAID_POINTS).addLong(amount));
return true;
}
}
return false;
}
public static void giveSpecialProduct(int id, long amount, L2PcInstance player)
{
switch (id)
{
case CLAN_REPUTATION:
{
player.getClan().addReputationScore((int) amount, true);
break;
}
case FAME:
{
player.setFame((int) (player.getFame() + amount));
player.sendPacket(new UserInfo(player));
// player.sendPacket(new ExBrExtraUserInfo(player));
break;
}
case RAIDBOSS_POINTS:
{
player.increaseRaidbossPoints((int) amount);
player.sendPacket(new UserInfo(player));
break;
}
}
}
private final void verify()
{
ListContainer list;
final Iterator<ListContainer> iter = _entries.values().iterator();
while (iter.hasNext())
{
list = iter.next();
for (Entry ent : list.getEntries())
{
for (Ingredient ing : ent.getIngredients())
{
if (!verifyIngredient(ing))
{
LOGGER.warning(getClass().getSimpleName() + ": Cannot find ingredient with item ID: " + ing.getItemId() + " in list: " + list.getListId());
}
}
for (Ingredient ing : ent.getProducts())
{
if (!verifyIngredient(ing))
{
LOGGER.warning(getClass().getSimpleName() + ": Cannot find product with item ID: " + ing.getItemId() + " in list: " + list.getListId());
}
}
}
}
}
private final boolean verifyIngredient(Ingredient ing)
{
switch (ing.getItemId())
{
case PC_CAFE_POINTS:
case CLAN_REPUTATION:
case FAME:
case RAIDBOSS_POINTS:
{
return true;
}
default:
{
return ing.getTemplate() != null;
}
}
}
public static MultisellData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final MultisellData _instance = new MultisellData();
}
}

View File

@@ -0,0 +1,885 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.CommonUtil;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.AISkillScope;
import com.l2jmobius.gameserver.enums.MpRewardAffectType;
import com.l2jmobius.gameserver.enums.MpRewardType;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.base.ClassId;
import com.l2jmobius.gameserver.model.drops.DropListScope;
import com.l2jmobius.gameserver.model.drops.GeneralDropItem;
import com.l2jmobius.gameserver.model.drops.GroupedGeneralDropItem;
import com.l2jmobius.gameserver.model.drops.IDropItem;
import com.l2jmobius.gameserver.model.effects.L2EffectType;
import com.l2jmobius.gameserver.model.holders.MinionHolder;
import com.l2jmobius.gameserver.model.skills.Skill;
/**
* NPC data parser.
* @author NosBit
*/
public class NpcData implements IGameXmlReader
{
protected static final Logger LOGGER = Logger.getLogger(NpcData.class.getName());
private final Map<Integer, L2NpcTemplate> _npcs = new ConcurrentHashMap<>();
private final Map<String, Integer> _clans = new ConcurrentHashMap<>();
private MinionData _minionData;
protected NpcData()
{
load();
}
@Override
public synchronized void load()
{
_minionData = new MinionData();
parseDatapackDirectory("data/stats/npcs", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _npcs.size() + " NPCs.");
if (Config.CUSTOM_NPC_DATA)
{
final int npcCount = _npcs.size();
parseDatapackDirectory("data/stats/npcs/custom", true);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + (_npcs.size() - npcCount) + " Custom NPCs.");
}
_minionData = null;
loadNpcsSkillLearn();
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equalsIgnoreCase(node.getNodeName()))
{
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
{
if ("npc".equalsIgnoreCase(list_node.getNodeName()))
{
NamedNodeMap attrs = list_node.getAttributes();
final StatsSet set = new StatsSet(new HashMap<>());
final int npcId = parseInteger(attrs, "id");
Map<String, Object> parameters = null;
Map<Integer, Skill> skills = null;
Set<Integer> clans = null;
Set<Integer> ignoreClanNpcIds = null;
Map<DropListScope, List<IDropItem>> dropLists = null;
set.set("id", npcId);
set.set("displayId", parseInteger(attrs, "displayId"));
set.set("level", parseByte(attrs, "level"));
set.set("type", parseString(attrs, "type"));
set.set("name", parseString(attrs, "name"));
set.set("usingServerSideName", parseBoolean(attrs, "usingServerSideName"));
set.set("title", parseString(attrs, "title"));
set.set("usingServerSideTitle", parseBoolean(attrs, "usingServerSideTitle"));
for (Node npc_node = list_node.getFirstChild(); npc_node != null; npc_node = npc_node.getNextSibling())
{
attrs = npc_node.getAttributes();
switch (npc_node.getNodeName().toLowerCase())
{
case "parameters":
{
if (parameters == null)
{
parameters = new HashMap<>();
}
parameters.putAll(parseParameters(npc_node));
break;
}
case "race":
case "sex":
set.set(npc_node.getNodeName(), npc_node.getTextContent().toUpperCase());
break;
case "equipment":
{
set.set("chestId", parseInteger(attrs, "chest"));
set.set("rhandId", parseInteger(attrs, "rhand"));
set.set("lhandId", parseInteger(attrs, "lhand"));
set.set("weaponEnchant", parseInteger(attrs, "weaponEnchant"));
break;
}
case "acquire":
{
set.set("exp", parseDouble(attrs, "exp"));
set.set("sp", parseDouble(attrs, "sp"));
set.set("raidPoints", parseDouble(attrs, "raidPoints"));
break;
}
case "mpreward":
{
set.set("mpRewardValue", parseInteger(attrs, "value"));
set.set("mpRewardType", parseEnum(attrs, MpRewardType.class, "type"));
set.set("mpRewardTicks", parseInteger(attrs, "ticks"));
set.set("mpRewardAffectType", parseEnum(attrs, MpRewardAffectType.class, "affects"));
break;
}
case "stats":
{
set.set("baseSTR", parseInteger(attrs, "str"));
set.set("baseINT", parseInteger(attrs, "int"));
set.set("baseDEX", parseInteger(attrs, "dex"));
set.set("baseWIT", parseInteger(attrs, "wit"));
set.set("baseCON", parseInteger(attrs, "con"));
set.set("baseMEN", parseInteger(attrs, "men"));
for (Node stats_node = npc_node.getFirstChild(); stats_node != null; stats_node = stats_node.getNextSibling())
{
attrs = stats_node.getAttributes();
switch (stats_node.getNodeName().toLowerCase())
{
case "vitals":
{
set.set("baseHpMax", parseDouble(attrs, "hp"));
set.set("baseHpReg", parseDouble(attrs, "hpRegen"));
set.set("baseMpMax", parseDouble(attrs, "mp"));
set.set("baseMpReg", parseDouble(attrs, "mpRegen"));
break;
}
case "attack":
{
set.set("basePAtk", parseDouble(attrs, "physical"));
set.set("baseMAtk", parseDouble(attrs, "magical"));
set.set("baseRndDam", parseInteger(attrs, "random"));
set.set("baseCritRate", parseDouble(attrs, "critical"));
set.set("accuracy", parseFloat(attrs, "accuracy")); // TODO: Implement me
set.set("basePAtkSpd", parseFloat(attrs, "attackSpeed"));
set.set("reuseDelay", parseInteger(attrs, "reuseDelay")); // TODO: Implement me
set.set("baseAtkType", parseString(attrs, "type"));
set.set("baseAtkRange", parseInteger(attrs, "range"));
set.set("distance", parseInteger(attrs, "distance")); // TODO: Implement me
set.set("width", parseInteger(attrs, "width")); // TODO: Implement me
break;
}
case "defence":
{
set.set("basePDef", parseDouble(attrs, "physical"));
set.set("baseMDef", parseDouble(attrs, "magical"));
set.set("evasion", parseInteger(attrs, "evasion")); // TODO: Implement me
set.set("baseShldDef", parseInteger(attrs, "shield"));
set.set("baseShldRate", parseInteger(attrs, "shieldRate"));
break;
}
case "abnormalresist":
{
set.set("physicalAbnormalResist", parseDouble(attrs, "physical"));
set.set("magicAbnormalResist", parseDouble(attrs, "magic"));
break;
}
case "attribute":
{
for (Node attribute_node = stats_node.getFirstChild(); attribute_node != null; attribute_node = attribute_node.getNextSibling())
{
attrs = attribute_node.getAttributes();
switch (attribute_node.getNodeName().toLowerCase())
{
case "attack":
{
final String attackAttributeType = parseString(attrs, "type");
switch (attackAttributeType.toUpperCase())
{
case "FIRE":
set.set("baseFire", parseInteger(attrs, "value"));
break;
case "WATER":
set.set("baseWater", parseInteger(attrs, "value"));
break;
case "WIND":
set.set("baseWind", parseInteger(attrs, "value"));
break;
case "EARTH":
set.set("baseEarth", parseInteger(attrs, "value"));
break;
case "DARK":
set.set("baseDark", parseInteger(attrs, "value"));
break;
case "HOLY":
set.set("baseHoly", parseInteger(attrs, "value"));
break;
}
break;
}
case "defence":
{
set.set("baseFireRes", parseInteger(attrs, "fire"));
set.set("baseWaterRes", parseInteger(attrs, "water"));
set.set("baseWindRes", parseInteger(attrs, "wind"));
set.set("baseEarthRes", parseInteger(attrs, "earth"));
set.set("baseHolyRes", parseInteger(attrs, "holy"));
set.set("baseDarkRes", parseInteger(attrs, "dark"));
set.set("baseElementRes", parseInteger(attrs, "default"));
break;
}
}
}
break;
}
case "speed":
{
for (Node speed_node = stats_node.getFirstChild(); speed_node != null; speed_node = speed_node.getNextSibling())
{
attrs = speed_node.getAttributes();
switch (speed_node.getNodeName().toLowerCase())
{
case "walk":
{
set.set("baseWalkSpd", parseDouble(attrs, "ground"));
set.set("baseSwimWalkSpd", parseDouble(attrs, "swim"));
set.set("baseFlyWalkSpd", parseDouble(attrs, "fly"));
break;
}
case "run":
{
set.set("baseRunSpd", parseDouble(attrs, "ground"));
set.set("baseSwimRunSpd", parseDouble(attrs, "swim"));
set.set("baseFlyRunSpd", parseDouble(attrs, "fly"));
break;
}
}
}
break;
}
case "hit_time":
set.set("hit_time", npc_node.getTextContent()); // TODO: Implement me default 600 (value in ms)
break;
}
}
break;
}
case "status":
{
set.set("unique", parseBoolean(attrs, "unique"));
set.set("attackable", parseBoolean(attrs, "attackable"));
set.set("targetable", parseBoolean(attrs, "targetable"));
set.set("talkable", parseBoolean(attrs, "talkable"));
set.set("undying", parseBoolean(attrs, "undying"));
set.set("showName", parseBoolean(attrs, "showName"));
set.set("randomWalk", parseBoolean(attrs, "randomWalk"));
set.set("randomAnimation", parseBoolean(attrs, "randomAnimation"));
set.set("flying", parseBoolean(attrs, "flying"));
set.set("canMove", parseBoolean(attrs, "canMove"));
set.set("noSleepMode", parseBoolean(attrs, "noSleepMode"));
set.set("passableDoor", parseBoolean(attrs, "passableDoor"));
set.set("hasSummoner", parseBoolean(attrs, "hasSummoner"));
set.set("canBeSown", parseBoolean(attrs, "canBeSown"));
break;
}
case "skill_list":
{
skills = new HashMap<>();
for (Node skill_list_node = npc_node.getFirstChild(); skill_list_node != null; skill_list_node = skill_list_node.getNextSibling())
{
if ("skill".equalsIgnoreCase(skill_list_node.getNodeName()))
{
attrs = skill_list_node.getAttributes();
final int skillId = parseInteger(attrs, "id");
final int skillLevel = parseInteger(attrs, "level");
final Skill skill = SkillData.getInstance().getSkill(skillId, skillLevel);
if (skill != null)
{
skills.put(skill.getId(), skill);
}
else
{
LOGGER.warning("[" + f.getName() + "] skill not found. NPC ID: " + npcId + " Skill ID: " + skillId + " Skill Level: " + skillLevel);
}
}
}
break;
}
case "shots":
{
set.set("soulShot", parseInteger(attrs, "soul"));
set.set("spiritShot", parseInteger(attrs, "spirit"));
set.set("shotShotChance", parseInteger(attrs, "shotChance"));
set.set("spiritShotChance", parseInteger(attrs, "spiritChance"));
break;
}
case "corpse_time":
{
set.set("corpseTime", npc_node.getTextContent());
break;
}
case "ex_crt_effect":
{
set.set("ex_crt_effect", npc_node.getTextContent()); // TODO: Implement me default ? type boolean
break;
}
case "s_npc_prop_hp_rate":
{
set.set("s_npc_prop_hp_rate", npc_node.getTextContent()); // TODO: Implement me default 1 type double
break;
}
case "ai":
{
set.set("aiType", parseString(attrs, "type"));
set.set("aggroRange", parseInteger(attrs, "aggroRange"));
set.set("clanHelpRange", parseInteger(attrs, "clanHelpRange"));
set.set("dodge", parseInteger(attrs, "dodge"));
set.set("isChaos", parseBoolean(attrs, "isChaos"));
set.set("isAggressive", parseBoolean(attrs, "isAggressive"));
for (Node ai_node = npc_node.getFirstChild(); ai_node != null; ai_node = ai_node.getNextSibling())
{
attrs = ai_node.getAttributes();
switch (ai_node.getNodeName().toLowerCase())
{
case "skill":
{
set.set("minSkillChance", parseInteger(attrs, "minChance"));
set.set("maxSkillChance", parseInteger(attrs, "maxChance"));
set.set("primarySkillId", parseInteger(attrs, "primaryId"));
set.set("shortRangeSkillId", parseInteger(attrs, "shortRangeId"));
set.set("shortRangeSkillChance", parseInteger(attrs, "shortRangeChance"));
set.set("longRangeSkillId", parseInteger(attrs, "longRangeId"));
set.set("longRangeSkillChance", parseInteger(attrs, "longRangeChance"));
break;
}
case "clan_list":
{
for (Node clan_list_node = ai_node.getFirstChild(); clan_list_node != null; clan_list_node = clan_list_node.getNextSibling())
{
attrs = clan_list_node.getAttributes();
switch (clan_list_node.getNodeName().toLowerCase())
{
case "clan":
{
if (clans == null)
{
clans = new HashSet<>(1);
}
clans.add(getOrCreateClanId(clan_list_node.getTextContent()));
break;
}
case "ignore_npc_id":
{
if (ignoreClanNpcIds == null)
{
ignoreClanNpcIds = new HashSet<>(1);
}
ignoreClanNpcIds.add(Integer.parseInt(clan_list_node.getTextContent()));
break;
}
}
}
break;
}
}
}
break;
}
case "drop_lists":
{
for (Node drop_lists_node = npc_node.getFirstChild(); drop_lists_node != null; drop_lists_node = drop_lists_node.getNextSibling())
{
DropListScope dropListScope = null;
try
{
dropListScope = Enum.valueOf(DropListScope.class, drop_lists_node.getNodeName().toUpperCase());
}
catch (Exception e)
{
}
if (dropListScope != null)
{
if (dropLists == null)
{
dropLists = new EnumMap<>(DropListScope.class);
}
final List<IDropItem> dropList = new ArrayList<>();
parseDropList(f, drop_lists_node, dropListScope, dropList);
dropLists.put(dropListScope, Collections.unmodifiableList(dropList));
}
}
break;
}
case "extend_drop":
{
final List<Integer> extendDrop = new ArrayList<>();
forEach(npc_node, "id", idNode ->
{
extendDrop.add(Integer.parseInt(idNode.getTextContent()));
});
set.set("extend_drop", extendDrop);
break;
}
case "collision":
{
for (Node collision_node = npc_node.getFirstChild(); collision_node != null; collision_node = collision_node.getNextSibling())
{
attrs = collision_node.getAttributes();
switch (collision_node.getNodeName().toLowerCase())
{
case "radius":
{
set.set("collision_radius", parseDouble(attrs, "normal"));
set.set("collisionRadiusGrown", parseDouble(attrs, "grown"));
break;
}
case "height":
{
set.set("collision_height", parseDouble(attrs, "normal"));
set.set("collisionHeightGrown", parseDouble(attrs, "grown"));
break;
}
}
}
break;
}
}
}
L2NpcTemplate template = _npcs.get(npcId);
if (template == null)
{
template = new L2NpcTemplate(set);
_npcs.put(template.getId(), template);
}
else
{
template.set(set);
}
if (_minionData._tempMinions.containsKey(npcId))
{
if (parameters == null)
{
parameters = new HashMap<>();
}
parameters.putIfAbsent("Privates", _minionData._tempMinions.get(npcId));
}
if (parameters != null)
{
// Using unmodifiable map parameters of template are not meant to be changed at runtime.
template.setParameters(new StatsSet(Collections.unmodifiableMap(parameters)));
}
else
{
template.setParameters(StatsSet.EMPTY_STATSET);
}
if (skills != null)
{
Map<AISkillScope, List<Skill>> aiSkillLists = null;
for (Skill skill : skills.values())
{
if (!skill.isPassive())
{
if (aiSkillLists == null)
{
aiSkillLists = new EnumMap<>(AISkillScope.class);
}
final List<AISkillScope> aiSkillScopes = new ArrayList<>();
final AISkillScope shortOrLongRangeScope = skill.getCastRange() <= 150 ? AISkillScope.SHORT_RANGE : AISkillScope.LONG_RANGE;
if (skill.isSuicideAttack())
{
aiSkillScopes.add(AISkillScope.SUICIDE);
}
else
{
aiSkillScopes.add(AISkillScope.GENERAL);
if (skill.isContinuous())
{
if (!skill.isDebuff())
{
aiSkillScopes.add(AISkillScope.BUFF);
}
else
{
aiSkillScopes.add(AISkillScope.DEBUFF);
aiSkillScopes.add(AISkillScope.COT);
aiSkillScopes.add(shortOrLongRangeScope);
}
}
else
{
if (skill.hasEffectType(L2EffectType.DISPEL, L2EffectType.DISPEL_BY_SLOT))
{
aiSkillScopes.add(AISkillScope.NEGATIVE);
aiSkillScopes.add(shortOrLongRangeScope);
}
else if (skill.hasEffectType(L2EffectType.HEAL))
{
aiSkillScopes.add(AISkillScope.HEAL);
}
else if (skill.hasEffectType(L2EffectType.PHYSICAL_ATTACK, L2EffectType.PHYSICAL_ATTACK_HP_LINK, L2EffectType.MAGICAL_ATTACK, L2EffectType.DEATH_LINK, L2EffectType.HP_DRAIN))
{
aiSkillScopes.add(AISkillScope.ATTACK);
aiSkillScopes.add(AISkillScope.UNIVERSAL);
aiSkillScopes.add(shortOrLongRangeScope);
}
else if (skill.hasEffectType(L2EffectType.SLEEP))
{
aiSkillScopes.add(AISkillScope.IMMOBILIZE);
}
else if (skill.hasEffectType(L2EffectType.BLOCK_ACTIONS, L2EffectType.ROOT))
{
aiSkillScopes.add(AISkillScope.IMMOBILIZE);
aiSkillScopes.add(shortOrLongRangeScope);
}
else if (skill.hasEffectType(L2EffectType.MUTE, L2EffectType.BLOCK_CONTROL))
{
aiSkillScopes.add(AISkillScope.COT);
aiSkillScopes.add(shortOrLongRangeScope);
}
else if (skill.hasEffectType(L2EffectType.DMG_OVER_TIME, L2EffectType.DMG_OVER_TIME_PERCENT))
{
aiSkillScopes.add(shortOrLongRangeScope);
}
else if (skill.hasEffectType(L2EffectType.RESURRECTION))
{
aiSkillScopes.add(AISkillScope.RES);
}
else
{
aiSkillScopes.add(AISkillScope.UNIVERSAL);
}
}
}
for (AISkillScope aiSkillScope : aiSkillScopes)
{
List<Skill> aiSkills = aiSkillLists.get(aiSkillScope);
if (aiSkills == null)
{
aiSkills = new ArrayList<>();
aiSkillLists.put(aiSkillScope, aiSkills);
}
aiSkills.add(skill);
}
}
}
template.setSkills(skills);
template.setAISkillLists(aiSkillLists);
}
else
{
template.setSkills(null);
template.setAISkillLists(null);
}
template.setClans(clans);
template.setIgnoreClanNpcIds(ignoreClanNpcIds);
template.setDropLists(dropLists);
}
}
}
}
}
private void parseDropList(File f, Node drop_list_node, DropListScope dropListScope, List<IDropItem> drops)
{
for (Node drop_node = drop_list_node.getFirstChild(); drop_node != null; drop_node = drop_node.getNextSibling())
{
final NamedNodeMap attrs = drop_node.getAttributes();
switch (drop_node.getNodeName().toLowerCase())
{
case "group":
{
final GroupedGeneralDropItem dropItem = dropListScope.newGroupedDropItem(parseDouble(attrs, "chance"));
final List<IDropItem> groupedDropList = new ArrayList<>(2);
for (Node group_node = drop_node.getFirstChild(); group_node != null; group_node = group_node.getNextSibling())
{
parseDropListItem(group_node, dropListScope, groupedDropList);
}
final List<GeneralDropItem> items = new ArrayList<>(groupedDropList.size());
for (IDropItem item : groupedDropList)
{
if (item instanceof GeneralDropItem)
{
items.add((GeneralDropItem) item);
}
else
{
LOGGER.warning("[" + f + "] grouped general drop item supports only general drop item.");
}
}
dropItem.setItems(items);
drops.add(dropItem);
break;
}
default:
{
parseDropListItem(drop_node, dropListScope, drops);
break;
}
}
}
}
private void parseDropListItem(Node drop_list_item, DropListScope dropListScope, List<IDropItem> drops)
{
final NamedNodeMap attrs = drop_list_item.getAttributes();
switch (drop_list_item.getNodeName().toLowerCase())
{
case "item":
{
final IDropItem dropItem = dropListScope.newDropItem(parseInteger(attrs, "id"), parseLong(attrs, "min"), parseLong(attrs, "max"), parseDouble(attrs, "chance"));
if (dropItem != null)
{
drops.add(dropItem);
}
break;
}
}
}
/**
* Gets or creates a clan id if it doesnt exists.
* @param clanName the clan name to get or create its id
* @return the clan id for the given clan name
*/
private int getOrCreateClanId(String clanName)
{
Integer id = _clans.get(clanName);
if (id == null)
{
id = _clans.size();
_clans.put(clanName, id);
}
return id;
}
/**
* Gets the clan id
* @param clanName the clan name to get its id
* @return the clan id for the given clan name if it exists, -1 otherwise
*/
public int getClanId(String clanName)
{
final Integer id = _clans.get(clanName);
return id != null ? id : -1;
}
public Set<String> getClansByIds(Set<Integer> clanIds)
{
final Set<String> result = new HashSet<>();
if (clanIds == null)
{
return result;
}
for (Entry<String, Integer> record : _clans.entrySet())
{
for (int id : clanIds)
{
if (record.getValue() == id)
{
result.add(record.getKey());
}
}
}
return result;
}
/**
* Gets the template.
* @param id the template Id to get.
* @return the template for the given id.
*/
public L2NpcTemplate getTemplate(int id)
{
return _npcs.get(id);
}
/**
* Gets the template by name.
* @param name of the template to get.
* @return the template for the given name.
*/
public L2NpcTemplate getTemplateByName(String name)
{
for (L2NpcTemplate npcTemplate : _npcs.values())
{
if (npcTemplate.getName().equalsIgnoreCase(name))
{
return npcTemplate;
}
}
return null;
}
/**
* Gets all templates matching the filter.
* @param filter
* @return the template list for the given filter
*/
public List<L2NpcTemplate> getTemplates(Predicate<L2NpcTemplate> filter)
{
//@formatter:off
return _npcs.values().stream()
.filter(filter)
.collect(Collectors.toList());
//@formatter:on
}
/**
* Gets the all of level.
* @param lvls of all the templates to get.
* @return the template list for the given level.
*/
public List<L2NpcTemplate> getAllOfLevel(int... lvls)
{
return getTemplates(template -> CommonUtil.contains(lvls, template.getLevel()));
}
/**
* Gets the all monsters of level.
* @param lvls of all the monster templates to get.
* @return the template list for the given level.
*/
public List<L2NpcTemplate> getAllMonstersOfLevel(int... lvls)
{
return getTemplates(template -> CommonUtil.contains(lvls, template.getLevel()) && template.isType("L2Monster"));
}
/**
* Gets the all npc starting with.
* @param text of all the NPC templates which its name start with.
* @return the template list for the given letter.
*/
public List<L2NpcTemplate> getAllNpcStartingWith(String text)
{
return getTemplates(template -> template.isType("L2Npc") && template.getName().startsWith(text));
}
/**
* Gets the all npc of class type.
* @param classTypes of all the templates to get.
* @return the template list for the given class type.
*/
public List<L2NpcTemplate> getAllNpcOfClassType(String... classTypes)
{
return getTemplates(template -> CommonUtil.contains(classTypes, template.getType(), true));
}
public void loadNpcsSkillLearn()
{
_npcs.values().forEach(template ->
{
final List<ClassId> teachInfo = SkillLearnData.getInstance().getSkillLearnData(template.getId());
if (teachInfo != null)
{
template.addTeachInfo(teachInfo);
}
});
}
/**
* This class handles minions from Spawn System<br>
* Once Spawn System gets reworked delete this class<br>
* @author Zealar
*/
private static final class MinionData implements IGameXmlReader
{
private static final Logger MINION_LOGGER = Logger.getLogger(MinionData.class.getName());
public final Map<Integer, List<MinionHolder>> _tempMinions = new HashMap<>();
protected MinionData()
{
load();
}
@Override
public void load()
{
_tempMinions.clear();
parseDatapackFile("data/MinionData.xml");
MINION_LOGGER.info(getClass().getSimpleName() + ": Loaded " + _tempMinions.size() + " minions data.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equals(node.getNodeName()))
{
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
{
if ("npc".equals(list_node.getNodeName()))
{
final List<MinionHolder> minions = new ArrayList<>(1);
NamedNodeMap attrs = list_node.getAttributes();
final int id = parseInteger(attrs, "id");
for (Node npc_node = list_node.getFirstChild(); npc_node != null; npc_node = npc_node.getNextSibling())
{
if ("minion".equals(npc_node.getNodeName()))
{
attrs = npc_node.getAttributes();
minions.add(new MinionHolder(parseInteger(attrs, "id"), parseInteger(attrs, "count"), parseInteger(attrs, "respawnTime"), 0));
}
}
_tempMinions.put(id, minions);
}
}
}
}
}
}
/**
* Gets the single instance of NpcData.
* @return single instance of NpcData
*/
public static NpcData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final NpcData _instance = new NpcData();
}
}

View File

@@ -0,0 +1,133 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.handler.EffectHandler;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.model.options.Options;
import com.l2jmobius.gameserver.model.options.OptionsSkillHolder;
import com.l2jmobius.gameserver.model.options.OptionsSkillType;
/**
* @author UnAfraid
*/
public class OptionData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(OptionData.class.getName());
private final Map<Integer, Options> _optionData = new HashMap<>();
protected OptionData()
{
load();
}
@Override
public synchronized void load()
{
_optionData.clear();
parseDatapackDirectory("data/stats/options", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _optionData.size() + " Options.");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "option", optionNode ->
{
final int id = parseInteger(optionNode.getAttributes(), "id");
final Options option = new Options(id);
forEach(optionNode, IXmlReader::isNode, innerNode ->
{
switch (innerNode.getNodeName())
{
case "effects":
{
forEach(innerNode, "effect", effectNode ->
{
final String name = parseString(effectNode.getAttributes(), "name");
final StatsSet params = new StatsSet();
forEach(effectNode, IXmlReader::isNode, paramNode ->
{
params.set(paramNode.getNodeName(), SkillData.getInstance().parseValue(paramNode, true, false, Collections.emptyMap()));
});
option.addEffect(EffectHandler.getInstance().getHandlerFactory(name).apply(params));
});
break;
}
case "active_skill":
{
option.setActiveSkill(new SkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level")));
break;
}
case "passive_skill":
{
option.setPassiveSkill(new SkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level")));
break;
}
case "attack_skill":
{
option.addActivationSkill(new OptionsSkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level"), parseDouble(innerNode.getAttributes(), "chance"), OptionsSkillType.ATTACK));
break;
}
case "magic_skill":
{
option.addActivationSkill(new OptionsSkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level"), parseDouble(innerNode.getAttributes(), "chance"), OptionsSkillType.MAGIC));
break;
}
case "critical_skill":
{
option.addActivationSkill(new OptionsSkillHolder(parseInteger(innerNode.getAttributes(), "id"), parseInteger(innerNode.getAttributes(), "level"), parseDouble(innerNode.getAttributes(), "chance"), OptionsSkillType.CRITICAL));
break;
}
}
});
_optionData.put(option.getId(), option);
}));
}
public Options getOptions(int id)
{
return _optionData.get(id);
}
/**
* Gets the single instance of OptionsData.
* @return single instance of OptionsData
*/
public static final OptionData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final OptionData _instance = new OptionData();
}
}

View File

@@ -0,0 +1,245 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.enums.MountType;
import com.l2jmobius.gameserver.model.L2PetData;
import com.l2jmobius.gameserver.model.L2PetLevelData;
import com.l2jmobius.gameserver.model.StatsSet;
/**
* This class parse and hold all pet parameters.<br>
* TODO: load and use all pet parameters.
* @author Zoey76 (rework)
*/
public final class PetDataTable implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PetDataTable.class.getName());
private final Map<Integer, L2PetData> _pets = new HashMap<>();
/**
* Instantiates a new pet data table.
*/
protected PetDataTable()
{
load();
}
@Override
public void load()
{
_pets.clear();
parseDatapackDirectory("data/stats/pets", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _pets.size() + " Pets.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
final Node n = doc.getFirstChild();
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if (d.getNodeName().equals("pet"))
{
final int npcId = parseInteger(d.getAttributes(), "id");
final int itemId = parseInteger(d.getAttributes(), "itemId");
// index ignored for now
final L2PetData data = new L2PetData(npcId, itemId);
for (Node p = d.getFirstChild(); p != null; p = p.getNextSibling())
{
if (p.getNodeName().equals("set"))
{
attrs = p.getAttributes();
final String type = attrs.getNamedItem("name").getNodeValue();
if ("food".equals(type))
{
for (String foodId : attrs.getNamedItem("val").getNodeValue().split(";"))
{
data.addFood(Integer.valueOf(foodId));
}
}
else if ("load".equals(type))
{
data.setLoad(parseInteger(attrs, "val"));
}
else if ("hungry_limit".equals(type))
{
data.setHungryLimit(parseInteger(attrs, "val"));
}
else if ("sync_level".equals(type))
{
data.setSyncLevel(parseInteger(attrs, "val") == 1);
}
// evolve ignored
}
else if (p.getNodeName().equals("skills"))
{
for (Node s = p.getFirstChild(); s != null; s = s.getNextSibling())
{
if (s.getNodeName().equals("skill"))
{
attrs = s.getAttributes();
data.addNewSkill(parseInteger(attrs, "skillId"), parseInteger(attrs, "skillLvl"), parseInteger(attrs, "minLvl"));
}
}
}
else if (p.getNodeName().equals("stats"))
{
for (Node s = p.getFirstChild(); s != null; s = s.getNextSibling())
{
if (s.getNodeName().equals("stat"))
{
final int level = Integer.parseInt(s.getAttributes().getNamedItem("level").getNodeValue());
final StatsSet set = new StatsSet();
for (Node bean = s.getFirstChild(); bean != null; bean = bean.getNextSibling())
{
if (bean.getNodeName().equals("set"))
{
attrs = bean.getAttributes();
if (attrs.getNamedItem("name").getNodeValue().equals("speed_on_ride"))
{
set.set("walkSpeedOnRide", attrs.getNamedItem("walk").getNodeValue());
set.set("runSpeedOnRide", attrs.getNamedItem("run").getNodeValue());
set.set("slowSwimSpeedOnRide", attrs.getNamedItem("slowSwim").getNodeValue());
set.set("fastSwimSpeedOnRide", attrs.getNamedItem("fastSwim").getNodeValue());
if (attrs.getNamedItem("slowFly") != null)
{
set.set("slowFlySpeedOnRide", attrs.getNamedItem("slowFly").getNodeValue());
}
if (attrs.getNamedItem("fastFly") != null)
{
set.set("fastFlySpeedOnRide", attrs.getNamedItem("fastFly").getNodeValue());
}
}
else
{
set.set(attrs.getNamedItem("name").getNodeValue(), attrs.getNamedItem("val").getNodeValue());
}
}
}
data.addNewStat(level, new L2PetLevelData(set));
}
}
}
}
_pets.put(npcId, data);
}
}
}
/**
* @param itemId
* @return
*/
public L2PetData getPetDataByItemId(int itemId)
{
for (L2PetData data : _pets.values())
{
if (data.getItemId() == itemId)
{
return data;
}
}
return null;
}
/**
* Gets the pet level data.
* @param petId the pet Id.
* @param petLevel the pet level.
* @return the pet's parameters for the given Id and level.
*/
public L2PetLevelData getPetLevelData(int petId, int petLevel)
{
final L2PetData pd = getPetData(petId);
if (pd != null)
{
return pd.getPetLevelData(petLevel);
}
return null;
}
/**
* Gets the pet data.
* @param petId the pet Id.
* @return the pet data
*/
public L2PetData getPetData(int petId)
{
if (!_pets.containsKey(petId))
{
LOGGER.info(getClass().getSimpleName() + ": Missing pet data for npcid: " + petId);
}
return _pets.get(petId);
}
/**
* Gets the pet min level.
* @param petId the pet Id.
* @return the pet min level
*/
public int getPetMinLevel(int petId)
{
return _pets.get(petId).getMinLevel();
}
/**
* Gets the pet items by npc.
* @param npcId the NPC ID to get its summoning item
* @return summoning item for the given NPC ID
*/
public int getPetItemsByNpc(int npcId)
{
return _pets.get(npcId).getItemId();
}
/**
* Checks if is mountable.
* @param npcId the NPC Id to verify.
* @return {@code true} if the given Id is from a mountable pet, {@code false} otherwise.
*/
public static boolean isMountable(int npcId)
{
return MountType.findByNpcId(npcId) != MountType.NONE;
}
/**
* Gets the single instance of PetDataTable.
* @return this class unique instance.
*/
public static PetDataTable getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PetDataTable _instance = new PetDataTable();
}
}

View File

@@ -0,0 +1,194 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.Config;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.templates.L2PcTemplate;
import com.l2jmobius.gameserver.model.base.ClassId;
/**
* Loads player's base stats.
* @author Forsaiken, Zoey76, GKR
*/
public final class PlayerTemplateData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PlayerTemplateData.class.getName());
private final Map<ClassId, L2PcTemplate> _playerTemplates = new HashMap<>();
private int _dataCount = 0;
protected PlayerTemplateData()
{
load();
}
@Override
public void load()
{
_playerTemplates.clear();
parseDatapackDirectory("data/stats/chars/baseStats", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _playerTemplates.size() + " character templates.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _dataCount + " level up gain records.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
int classId = 0;
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 ("classId".equalsIgnoreCase(d.getNodeName()))
{
classId = Integer.parseInt(d.getTextContent());
}
else if ("staticData".equalsIgnoreCase(d.getNodeName()))
{
final StatsSet set = new StatsSet();
set.set("classId", classId);
final List<Location> creationPoints = new ArrayList<>();
for (Node nd = d.getFirstChild(); nd != null; nd = nd.getNextSibling())
{
// Skip odd nodes
if (nd.getNodeName().equals("#text"))
{
continue;
}
if (nd.getChildNodes().getLength() > 1)
{
for (Node cnd = nd.getFirstChild(); cnd != null; cnd = cnd.getNextSibling())
{
// use L2CharTemplate(superclass) fields for male collision height and collision radius
if (nd.getNodeName().equalsIgnoreCase("collisionMale"))
{
if (cnd.getNodeName().equalsIgnoreCase("radius"))
{
set.set("collision_radius", cnd.getTextContent());
}
else if (cnd.getNodeName().equalsIgnoreCase("height"))
{
set.set("collision_height", cnd.getTextContent());
}
}
if ("node".equalsIgnoreCase(cnd.getNodeName()))
{
attrs = cnd.getAttributes();
creationPoints.add(new Location(parseInteger(attrs, "x"), parseInteger(attrs, "y"), parseInteger(attrs, "z")));
}
else if ("walk".equalsIgnoreCase(cnd.getNodeName()))
{
set.set("baseWalkSpd", cnd.getTextContent());
}
else if ("run".equalsIgnoreCase(cnd.getNodeName()))
{
set.set("baseRunSpd", cnd.getTextContent());
}
else if ("slowSwim".equals(cnd.getNodeName()))
{
set.set("baseSwimWalkSpd", cnd.getTextContent());
}
else if ("fastSwim".equals(cnd.getNodeName()))
{
set.set("baseSwimRunSpd", cnd.getTextContent());
}
else if (!cnd.getNodeName().equals("#text"))
{
set.set((nd.getNodeName() + cnd.getNodeName()), cnd.getTextContent());
}
}
}
else
{
set.set(nd.getNodeName(), nd.getTextContent());
}
}
// calculate total pdef and mdef from parts
set.set("basePDef", (set.getInt("basePDefchest", 0) + set.getInt("basePDeflegs", 0) + set.getInt("basePDefhead", 0) + set.getInt("basePDeffeet", 0) + set.getInt("basePDefgloves", 0) + set.getInt("basePDefunderwear", 0) + set.getInt("basePDefcloak", 0)));
set.set("baseMDef", (set.getInt("baseMDefrear", 0) + set.getInt("baseMDeflear", 0) + set.getInt("baseMDefrfinger", 0) + set.getInt("baseMDefrfinger", 0) + set.getInt("baseMDefneck", 0)));
_playerTemplates.put(ClassId.getClassId(classId), new L2PcTemplate(set, creationPoints));
}
else if ("lvlUpgainData".equalsIgnoreCase(d.getNodeName()))
{
for (Node lvlNode = d.getFirstChild(); lvlNode != null; lvlNode = lvlNode.getNextSibling())
{
if ("level".equalsIgnoreCase(lvlNode.getNodeName()))
{
attrs = lvlNode.getAttributes();
final int level = parseInteger(attrs, "val");
for (Node valNode = lvlNode.getFirstChild(); valNode != null; valNode = valNode.getNextSibling())
{
final String nodeName = valNode.getNodeName();
if ((level < Config.PLAYER_MAXIMUM_LEVEL) && (nodeName.startsWith("hp") || nodeName.startsWith("mp") || nodeName.startsWith("cp")) && _playerTemplates.containsKey(ClassId.getClassId(classId)))
{
_playerTemplates.get(ClassId.getClassId(classId)).setUpgainValue(nodeName, level, Double.parseDouble(valNode.getTextContent()));
_dataCount++;
}
}
}
}
// TODO: Generate stats automatically.
}
}
}
}
}
public L2PcTemplate getTemplate(ClassId classId)
{
return _playerTemplates.get(classId);
}
public L2PcTemplate getTemplate(int classId)
{
return _playerTemplates.get(ClassId.getClassId(classId));
}
public static final PlayerTemplateData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PlayerTemplateData _instance = new PlayerTemplateData();
}
}

View File

@@ -0,0 +1,99 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.Arrays;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
/**
* This class holds the Player Xp Percent Lost Data for each level for players.
* @author Zealar
*/
public final class PlayerXpPercentLostData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PlayerXpPercentLostData.class.getName());
private final int _maxlevel = ExperienceData.getInstance().getMaxLevel();
private final double[] _playerXpPercentLost = new double[_maxlevel + 1];
protected PlayerXpPercentLostData()
{
Arrays.fill(_playerXpPercentLost, 1.);
load();
}
@Override
public void load()
{
parseDatapackFile("data/stats/chars/playerXpPercentLost.xml");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("xpLost".equalsIgnoreCase(d.getNodeName()))
{
final NamedNodeMap attrs = d.getAttributes();
final Integer level = parseInteger(attrs, "level");
if (level > _maxlevel)
{
break;
}
_playerXpPercentLost[level] = parseDouble(attrs, "val");
}
}
}
}
}
public double getXpPercent(int level)
{
if (level > _maxlevel)
{
LOGGER.warning("Require to high level inside PlayerXpPercentLostData (" + level + ")");
return _playerXpPercentLost[_maxlevel];
}
return _playerXpPercentLost[level];
}
/**
* Gets the single instance of PlayerXpPercentLostData.
* @return single instance of PlayerXpPercentLostData.
*/
public static PlayerXpPercentLostData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PlayerXpPercentLostData _instance = new PlayerXpPercentLostData();
}
}

View File

@@ -0,0 +1,153 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.datatables.ItemTable;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.items.L2Item;
import com.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import com.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
import com.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
/**
* @author Gnacik, UnAfraid
*/
public class PrimeShopData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
private final Map<Integer, PrimeShopGroup> _primeItems = new LinkedHashMap<>();
protected PrimeShopData()
{
load();
}
@Override
public void load()
{
_primeItems.clear();
parseDatapackFile("data/PrimeShop.xml");
if (!_primeItems.isEmpty())
{
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _primeItems.size() + " items");
}
else
{
LOGGER.info(getClass().getSimpleName() + ": System is disabled.");
}
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
final NamedNodeMap at = n.getAttributes();
final Node attribute = at.getNamedItem("enabled");
if ((attribute != null) && Boolean.parseBoolean(attribute.getNodeValue()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
Node att;
final StatsSet set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
final List<PrimeShopItem> items = new ArrayList<>();
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("item".equalsIgnoreCase(b.getNodeName()))
{
attrs = b.getAttributes();
final int itemId = parseInteger(attrs, "itemId");
final int count = parseInteger(attrs, "count");
final L2Item item = ItemTable.getInstance().getTemplate(itemId);
if (item == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Item template null for itemId: " + itemId + " brId: " + set.getInt("id"));
return;
}
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
_primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
}
}
}
}
}
}
public void showProductInfo(L2PcInstance player, int brId)
{
final PrimeShopGroup item = _primeItems.get(brId);
if ((player == null) || (item == null))
{
return;
}
player.sendPacket(new ExBRProductInfo(item, player));
}
public PrimeShopGroup getItem(int brId)
{
return _primeItems.get(brId);
}
public Map<Integer, PrimeShopGroup> getPrimeItems()
{
return _primeItems;
}
public static PrimeShopData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final PrimeShopData _instance = new PrimeShopData();
}
}

View File

@@ -0,0 +1,283 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.L2RecipeInstance;
import com.l2jmobius.gameserver.model.L2RecipeList;
import com.l2jmobius.gameserver.model.L2RecipeStatInstance;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
/**
* The Class RecipeData.
* @author Zoey76
*/
public class RecipeData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(RecipeData.class.getName());
private final Map<Integer, L2RecipeList> _recipes = new HashMap<>();
/**
* Instantiates a new recipe data.
*/
protected RecipeData()
{
load();
}
@Override
public void load()
{
_recipes.clear();
parseDatapackFile("data/Recipes.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _recipes.size() + " recipes.");
}
@Override
public void parseDocument(Document doc, File f)
{
// TODO: Cleanup checks enforced by XSD.
final List<L2RecipeInstance> recipePartList = new ArrayList<>();
final List<L2RecipeStatInstance> recipeStatUseList = new ArrayList<>();
final List<L2RecipeStatInstance> recipeAltStatChangeList = new ArrayList<>();
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
RECIPES_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
recipePartList.clear();
recipeStatUseList.clear();
recipeAltStatChangeList.clear();
final NamedNodeMap attrs = d.getAttributes();
Node att;
int id = -1;
boolean haveRare = false;
final StatsSet set = new StatsSet();
att = attrs.getNamedItem("id");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing id for recipe item, skipping");
continue;
}
id = Integer.parseInt(att.getNodeValue());
set.set("id", id);
att = attrs.getNamedItem("recipeId");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing recipeId for recipe item id: " + id + ", skipping");
continue;
}
set.set("recipeId", Integer.parseInt(att.getNodeValue()));
att = attrs.getNamedItem("name");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing name for recipe item id: " + id + ", skipping");
continue;
}
set.set("recipeName", att.getNodeValue());
att = attrs.getNamedItem("craftLevel");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing level for recipe item id: " + id + ", skipping");
continue;
}
set.set("craftLevel", Integer.parseInt(att.getNodeValue()));
att = attrs.getNamedItem("type");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing type for recipe item id: " + id + ", skipping");
continue;
}
set.set("isDwarvenRecipe", att.getNodeValue().equalsIgnoreCase("dwarven"));
att = attrs.getNamedItem("successRate");
if (att == null)
{
LOGGER.severe(getClass().getSimpleName() + ": Missing successRate for recipe item id: " + id + ", skipping");
continue;
}
set.set("successRate", Integer.parseInt(att.getNodeValue()));
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("statUse".equalsIgnoreCase(c.getNodeName()))
{
final String statName = c.getAttributes().getNamedItem("name").getNodeValue();
final int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
try
{
recipeStatUseList.add(new L2RecipeStatInstance(statName, value));
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Error in StatUse parameter for recipe item id: " + id + ", skipping");
continue RECIPES_FILE;
}
}
else if ("altStatChange".equalsIgnoreCase(c.getNodeName()))
{
final String statName = c.getAttributes().getNamedItem("name").getNodeValue();
final int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
try
{
recipeAltStatChangeList.add(new L2RecipeStatInstance(statName, value));
}
catch (Exception e)
{
LOGGER.severe(getClass().getSimpleName() + ": Error in AltStatChange parameter for recipe item id: " + id + ", skipping");
continue RECIPES_FILE;
}
}
else if ("ingredient".equalsIgnoreCase(c.getNodeName()))
{
final int ingId = Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue());
final int ingCount = Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue());
recipePartList.add(new L2RecipeInstance(ingId, ingCount));
}
else if ("production".equalsIgnoreCase(c.getNodeName()))
{
set.set("itemId", Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue()));
set.set("count", Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue()));
}
else if ("productionRare".equalsIgnoreCase(c.getNodeName()))
{
set.set("rareItemId", Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue()));
set.set("rareCount", Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue()));
set.set("rarity", Integer.parseInt(c.getAttributes().getNamedItem("rarity").getNodeValue()));
haveRare = true;
}
}
final L2RecipeList recipeList = new L2RecipeList(set, haveRare);
for (L2RecipeInstance recipePart : recipePartList)
{
recipeList.addRecipe(recipePart);
}
for (L2RecipeStatInstance recipeStatUse : recipeStatUseList)
{
recipeList.addStatUse(recipeStatUse);
}
for (L2RecipeStatInstance recipeAltStatChange : recipeAltStatChangeList)
{
recipeList.addAltStatChange(recipeAltStatChange);
}
_recipes.put(id, recipeList);
}
}
}
}
}
/**
* Gets the recipe list.
* @param listId the list id
* @return the recipe list
*/
public L2RecipeList getRecipeList(int listId)
{
return _recipes.get(listId);
}
/**
* Gets the recipe by item id.
* @param itemId the item id
* @return the recipe by item id
*/
public L2RecipeList getRecipeByItemId(int itemId)
{
for (L2RecipeList find : _recipes.values())
{
if (find.getRecipeId() == itemId)
{
return find;
}
}
return null;
}
/**
* Gets the all item ids.
* @return the all item ids
*/
public int[] getAllItemIds()
{
final int[] idList = new int[_recipes.size()];
int i = 0;
for (L2RecipeList rec : _recipes.values())
{
idList[i++] = rec.getRecipeId();
}
return idList;
}
/**
* Gets the valid recipe list.
* @param player the player
* @param id the recipe list id
* @return the valid recipe list
*/
public L2RecipeList getValidRecipeList(L2PcInstance player, int id)
{
final L2RecipeList recipeList = _recipes.get(id);
if ((recipeList == null) || (recipeList.getRecipes().length == 0))
{
player.sendMessage("No recipe for: " + id);
player.isInCraftMode(false);
return null;
}
return recipeList;
}
/**
* Gets the single instance of RecipeData.
* @return single instance of RecipeData
*/
public static RecipeData getInstance()
{
return SingletonHolder._instance;
}
/**
* The Class SingletonHolder.
*/
private static class SingletonHolder
{
protected static final RecipeData _instance = new RecipeData();
}
}

View File

@@ -0,0 +1,113 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.residences.ResidenceFunctionTemplate;
/**
* The residence functions data
* @author UnAfraid
*/
public final class ResidenceFunctionsData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ResidenceFunctionsData.class.getName());
private final Map<Integer, List<ResidenceFunctionTemplate>> _functions = new HashMap<>();
protected ResidenceFunctionsData()
{
load();
}
@Override
public synchronized void load()
{
_functions.clear();
parseDatapackFile("data/ResidenceFunctions.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _functions.size() + " functions.");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", list -> forEach(list, "function", func ->
{
final NamedNodeMap attrs = func.getAttributes();
final StatsSet set = new StatsSet(HashMap::new);
for (int i = 0; i < attrs.getLength(); i++)
{
final Node node = attrs.item(i);
set.set(node.getNodeName(), node.getNodeValue());
}
forEach(func, "function", levelNode ->
{
final NamedNodeMap levelAttrs = levelNode.getAttributes();
final StatsSet levelSet = new StatsSet(HashMap::new);
levelSet.merge(set);
for (int i = 0; i < levelAttrs.getLength(); i++)
{
final Node node = levelAttrs.item(i);
levelSet.set(node.getNodeName(), node.getNodeValue());
}
final ResidenceFunctionTemplate template = new ResidenceFunctionTemplate(levelSet);
_functions.computeIfAbsent(template.getId(), key -> new ArrayList<>()).add(template);
});
}));
}
/**
* @param id
* @param level
* @return function template by id and level, null if not available
*/
public ResidenceFunctionTemplate getFunction(int id, int level)
{
return _functions.getOrDefault(id, Collections.emptyList()).stream().filter(template -> template.getLevel() == level).findAny().orElse(null);
}
/**
* @param id
* @return function template by id, null if not available
*/
public List<ResidenceFunctionTemplate> getFunctions(int id)
{
return _functions.get(id);
}
public static final ResidenceFunctionsData getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final ResidenceFunctionsData INSTANCE = new ResidenceFunctionsData();
}
}

View File

@@ -0,0 +1,115 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.SayuneEntry;
/**
* @author UnAfraid
*/
public class SayuneData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SayuneData.class.getName());
private final Map<Integer, SayuneEntry> _maps = new HashMap<>();
protected SayuneData()
{
load();
}
@Override
public void load()
{
parseDatapackFile("data/SayuneData.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _maps.size() + " maps.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("map".equalsIgnoreCase(d.getNodeName()))
{
final int id = parseInteger(d.getAttributes(), "id");
final SayuneEntry map = new SayuneEntry(id);
parseEntries(map, d);
_maps.put(map.getId(), map);
}
}
}
}
}
private final void parseEntries(SayuneEntry lastEntry, Node n)
{
NamedNodeMap attrs;
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("selector".equals(d.getNodeName()) || "choice".equals(d.getNodeName()) || "loc".equals(d.getNodeName()))
{
attrs = d.getAttributes();
final int id = parseInteger(attrs, "id");
final int x = parseInteger(attrs, "x");
final int y = parseInteger(attrs, "y");
final int z = parseInteger(attrs, "z");
parseEntries(lastEntry.addInnerEntry(new SayuneEntry("selector".equals(d.getNodeName()), id, x, y, z)), d);
}
}
}
public SayuneEntry getMap(int id)
{
return _maps.get(id);
}
public Collection<SayuneEntry> getMaps()
{
return _maps.values();
}
/**
* Gets the single instance of SayuneData.
* @return single instance of SayuneData
*/
public static final SayuneData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SayuneData _instance = new SayuneData();
}
}

View File

@@ -0,0 +1,142 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
/**
* @author NosBit
*/
public class SecondaryAuthData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SecondaryAuthData.class.getName());
private final Set<String> _forbiddenPasswords = new HashSet<>();
private boolean _enabled = false;
private int _maxAttempts = 5;
private int _banTime = 480;
private String _recoveryLink = "";
protected SecondaryAuthData()
{
load();
}
@Override
public synchronized void load()
{
_forbiddenPasswords.clear();
parseFile(new File("config/SecondaryAuth.xml"));
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _forbiddenPasswords.size() + " forbidden passwords.");
}
@Override
public void parseDocument(Document doc, File f)
{
try
{
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equalsIgnoreCase(node.getNodeName()))
{
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
{
if ("enabled".equalsIgnoreCase(list_node.getNodeName()))
{
_enabled = Boolean.parseBoolean(list_node.getTextContent());
}
else if ("maxAttempts".equalsIgnoreCase(list_node.getNodeName()))
{
_maxAttempts = Integer.parseInt(list_node.getTextContent());
}
else if ("banTime".equalsIgnoreCase(list_node.getNodeName()))
{
_banTime = Integer.parseInt(list_node.getTextContent());
}
else if ("recoveryLink".equalsIgnoreCase(list_node.getNodeName()))
{
_recoveryLink = list_node.getTextContent();
}
else if ("forbiddenPasswords".equalsIgnoreCase(list_node.getNodeName()))
{
for (Node forbiddenPasswords_node = list_node.getFirstChild(); forbiddenPasswords_node != null; forbiddenPasswords_node = forbiddenPasswords_node.getNextSibling())
{
if ("password".equalsIgnoreCase(forbiddenPasswords_node.getNodeName()))
{
_forbiddenPasswords.add(forbiddenPasswords_node.getTextContent());
}
}
}
}
}
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Failed to load secondary auth data from xml.", e);
}
}
public boolean isEnabled()
{
return _enabled;
}
public int getMaxAttempts()
{
return _maxAttempts;
}
public int getBanTime()
{
return _banTime;
}
public String getRecoveryLink()
{
return _recoveryLink;
}
public Set<String> getForbiddenPasswords()
{
return _forbiddenPasswords;
}
public boolean isForbiddenPassword(String password)
{
return _forbiddenPasswords.contains(password);
}
public static SecondaryAuthData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SecondaryAuthData _instance = new SecondaryAuthData();
}
}

View File

@@ -0,0 +1,202 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.Location;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.VehiclePathPoint;
import com.l2jmobius.gameserver.model.actor.instance.L2ShuttleInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2CharTemplate;
import com.l2jmobius.gameserver.model.shuttle.L2ShuttleData;
import com.l2jmobius.gameserver.model.shuttle.L2ShuttleEngine;
import com.l2jmobius.gameserver.model.shuttle.L2ShuttleStop;
/**
* @author UnAfraid
*/
public final class ShuttleData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(ShuttleData.class.getName());
private final Map<Integer, L2ShuttleData> _shuttles = new HashMap<>();
private final Map<Integer, L2ShuttleInstance> _shuttleInstances = new HashMap<>();
protected ShuttleData()
{
load();
}
@Override
public synchronized void load()
{
if (!_shuttleInstances.isEmpty())
{
for (L2ShuttleInstance shuttle : _shuttleInstances.values())
{
shuttle.deleteMe();
}
_shuttleInstances.clear();
}
parseDatapackFile("data/ShuttleData.xml");
init();
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _shuttles.size() + " Shuttles.");
}
@Override
public void parseDocument(Document doc, File f)
{
NamedNodeMap attrs;
StatsSet set;
Node att;
L2ShuttleData data;
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 ("shuttle".equalsIgnoreCase(d.getNodeName()))
{
attrs = d.getAttributes();
set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
data = new L2ShuttleData(set);
for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling())
{
if ("doors".equalsIgnoreCase(b.getNodeName()))
{
for (Node a = b.getFirstChild(); a != null; a = a.getNextSibling())
{
if ("door".equalsIgnoreCase(a.getNodeName()))
{
attrs = a.getAttributes();
data.addDoor(parseInteger(attrs, "id"));
}
}
}
else if ("stops".equalsIgnoreCase(b.getNodeName()))
{
for (Node a = b.getFirstChild(); a != null; a = a.getNextSibling())
{
if ("stop".equalsIgnoreCase(a.getNodeName()))
{
attrs = a.getAttributes();
final L2ShuttleStop stop = new L2ShuttleStop(parseInteger(attrs, "id"));
for (Node z = a.getFirstChild(); z != null; z = z.getNextSibling())
{
if ("dimension".equalsIgnoreCase(z.getNodeName()))
{
attrs = z.getAttributes();
stop.addDimension(new Location(parseInteger(attrs, "x"), parseInteger(attrs, "y"), parseInteger(attrs, "z")));
}
}
data.addStop(stop);
}
}
}
else if ("routes".equalsIgnoreCase(b.getNodeName()))
{
for (Node a = b.getFirstChild(); a != null; a = a.getNextSibling())
{
if ("route".equalsIgnoreCase(a.getNodeName()))
{
attrs = a.getAttributes();
final List<Location> locs = new ArrayList<>();
for (Node z = a.getFirstChild(); z != null; z = z.getNextSibling())
{
if ("loc".equalsIgnoreCase(z.getNodeName()))
{
attrs = z.getAttributes();
locs.add(new Location(parseInteger(attrs, "x"), parseInteger(attrs, "y"), parseInteger(attrs, "z")));
}
}
final VehiclePathPoint[] route = new VehiclePathPoint[locs.size()];
int i = 0;
for (Location loc : locs)
{
route[i++] = new VehiclePathPoint(loc);
}
data.addRoute(route);
}
}
}
}
_shuttles.put(data.getId(), data);
}
}
}
}
}
private void init()
{
for (L2ShuttleData data : _shuttles.values())
{
final L2ShuttleInstance shuttle = new L2ShuttleInstance(new L2CharTemplate(new StatsSet()));
shuttle.setData(data);
shuttle.setHeading(data.getLocation().getHeading());
shuttle.setLocationInvisible(data.getLocation());
shuttle.spawnMe();
shuttle.getStat().setMoveSpeed(300);
shuttle.getStat().setRotationSpeed(0);
shuttle.registerEngine(new L2ShuttleEngine(data, shuttle));
shuttle.runEngine(1000);
_shuttleInstances.put(shuttle.getObjectId(), shuttle);
}
}
public L2ShuttleInstance getShuttle(int id)
{
for (L2ShuttleInstance shuttle : _shuttleInstances.values())
{
if ((shuttle.getObjectId() == id) || (shuttle.getId() == id))
{
return shuttle;
}
}
return null;
}
public static ShuttleData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final ShuttleData _instance = new ShuttleData();
}
}

View File

@@ -0,0 +1,128 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.SiegeScheduleDate;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.util.Util;
/**
* @author UnAfraid
*/
public class SiegeScheduleData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SiegeScheduleData.class.getName());
private final List<SiegeScheduleDate> _scheduleData = new ArrayList<>();
protected SiegeScheduleData()
{
load();
}
@Override
public synchronized void load()
{
_scheduleData.clear();
parseDatapackFile("config/SiegeSchedule.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _scheduleData.size() + " siege schedulers.");
if (_scheduleData.isEmpty())
{
_scheduleData.add(new SiegeScheduleDate(new StatsSet()));
LOGGER.info(getClass().getSimpleName() + ": Emergency Loaded: " + _scheduleData.size() + " default siege schedulers.");
}
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node cd = n.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
switch (cd.getNodeName())
{
case "schedule":
{
final StatsSet set = new StatsSet();
final NamedNodeMap attrs = cd.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node node = attrs.item(i);
final String key = node.getNodeName();
String val = node.getNodeValue();
if ("day".equals(key))
{
if (!Util.isDigit(val))
{
val = Integer.toString(getValueForField(val));
}
}
set.set(key, val);
}
_scheduleData.add(new SiegeScheduleDate(set));
break;
}
}
}
}
}
}
private int getValueForField(String field)
{
try
{
return Calendar.class.getField(field).getInt(Calendar.class.getName());
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "", e);
return -1;
}
}
public List<SiegeScheduleDate> getScheduleDates()
{
return _scheduleData;
}
public static final SiegeScheduleData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SiegeScheduleData _instance = new SiegeScheduleData();
}
}

View File

@@ -0,0 +1,692 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.handler.EffectHandler;
import com.l2jmobius.gameserver.handler.SkillConditionHandler;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.effects.AbstractEffect;
import com.l2jmobius.gameserver.model.skills.CommonSkill;
import com.l2jmobius.gameserver.model.skills.EffectScope;
import com.l2jmobius.gameserver.model.skills.ISkillCondition;
import com.l2jmobius.gameserver.model.skills.Skill;
import com.l2jmobius.gameserver.model.skills.SkillConditionScope;
import net.objecthunter.exp4j.ExpressionBuilder;
/**
* Skill data parser.
* @author NosBit
*/
public class SkillData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SkillData.class.getName());
private final Map<Integer, Skill> _skills = new HashMap<>();
private final Map<Integer, Integer> _skillsMaxLevel = new HashMap<>();
private final Set<Integer> _enchantable = new HashSet<>();
private class NamedParamInfo
{
private final String _name;
private final Integer _fromLevel;
private final Integer _toLevel;
private final Integer _fromSubLevel;
private final Integer _toSubLevel;
private final Map<Integer, Map<Integer, StatsSet>> _info;
private final StatsSet _generalInfo;
public NamedParamInfo(String name, Integer fromLevel, Integer toLevel, Integer fromSubLevel, Integer toSubLevel, Map<Integer, Map<Integer, StatsSet>> info, StatsSet generalInfo)
{
_name = name;
_fromLevel = fromLevel;
_toLevel = toLevel;
_fromSubLevel = fromSubLevel;
_toSubLevel = toSubLevel;
_info = info;
_generalInfo = generalInfo;
}
public String getName()
{
return _name;
}
public Integer getFromLevel()
{
return _fromLevel;
}
public Integer getToLevel()
{
return _toLevel;
}
public Integer getFromSubLevel()
{
return _fromSubLevel;
}
public Integer getToSubLevel()
{
return _toSubLevel;
}
public Map<Integer, Map<Integer, StatsSet>> getInfo()
{
return _info;
}
public StatsSet getGeneralInfo()
{
return _generalInfo;
}
}
protected SkillData()
{
load();
}
/**
* Provides the skill hash
* @param skill The L2Skill to be hashed
* @return getSkillHashCode(skill.getId(), skill.getLevel())
*/
public static int getSkillHashCode(Skill skill)
{
return getSkillHashCode(skill.getId(), skill.getLevel());
}
/**
* Centralized method for easier change of the hashing sys
* @param skillId The Skill Id
* @param skillLevel The Skill Level
* @return The Skill hash number
*/
public static int getSkillHashCode(int skillId, int skillLevel)
{
return (skillId * 1031) + skillLevel;
}
public Skill getSkill(int skillId, int level)
{
final Skill result = _skills.get(getSkillHashCode(skillId, level));
if (result != null)
{
return result;
}
// skill/level not found, fix for transformation scripts
final int maxLvl = getMaxLevel(skillId);
// requested level too high
if ((maxLvl > 0) && (level > maxLvl))
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Call to unexisting skill level id: " + skillId + " requested level: " + level + " max level: " + maxLvl, new Throwable());
return _skills.get(getSkillHashCode(skillId, maxLvl));
}
LOGGER.warning(getClass().getSimpleName() + ": No skill info found for skill id " + skillId + " and skill level " + level);
return null;
}
public int getMaxLevel(int skillId)
{
final Integer maxLevel = _skillsMaxLevel.get(skillId);
return maxLevel != null ? maxLevel : 0;
}
/**
* Verifies if the given skill ID correspond to an enchantable skill.
* @param skillId the skill ID
* @return {@code true} if the skill is enchantable, {@code false} otherwise
*/
public boolean isEnchantable(int skillId)
{
return _enchantable.contains(skillId);
}
/**
* @param addNoble
* @param hasCastle
* @return an array with siege skills. If addNoble == true, will add also Advanced headquarters.
*/
public List<Skill> getSiegeSkills(boolean addNoble, boolean hasCastle)
{
final List<Skill> temp = new LinkedList<>();
temp.add(_skills.get(SkillData.getSkillHashCode(CommonSkill.IMPRIT_OF_LIGHT.getId(), 1)));
temp.add(_skills.get(SkillData.getSkillHashCode(CommonSkill.IMPRIT_OF_DARKNESS.getId(), 1)));
temp.add(_skills.get(SkillData.getSkillHashCode(247, 1))); // Build Headquarters
if (addNoble)
{
temp.add(_skills.get(SkillData.getSkillHashCode(326, 1))); // Build Advanced Headquarters
}
if (hasCastle)
{
temp.add(_skills.get(SkillData.getSkillHashCode(844, 1))); // Outpost Construction
temp.add(_skills.get(SkillData.getSkillHashCode(845, 1))); // Outpost Demolition
}
return temp;
}
@Override
public boolean isValidating()
{
return false;
}
@Override
public synchronized void load()
{
_skills.clear();
_skillsMaxLevel.clear();
_enchantable.clear();
parseDatapackDirectory("data/stats/skills/", true);
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _skills.size() + " Skills.");
}
public void reload()
{
load();
// Reload Skill Tree as well.
SkillTreesData.getInstance().load();
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equalsIgnoreCase(node.getNodeName()))
{
for (Node listNode = node.getFirstChild(); listNode != null; listNode = listNode.getNextSibling())
{
if ("skill".equalsIgnoreCase(listNode.getNodeName()))
{
NamedNodeMap attributes = listNode.getAttributes();
final Map<Integer, Set<Integer>> levels = new HashMap<>();
final Map<Integer, Map<Integer, StatsSet>> skillInfo = new HashMap<>();
final StatsSet generalSkillInfo = new StatsSet();
parseAttributes(attributes, "", generalSkillInfo);
final Map<String, Map<Integer, Map<Integer, Object>>> variableValues = new HashMap<>();
final Map<String, Object> variableGeneralValues = new HashMap<>();
final Map<EffectScope, List<NamedParamInfo>> effectParamInfo = new HashMap<>();
final Map<SkillConditionScope, List<NamedParamInfo>> conditionParamInfo = new HashMap<>();
for (Node skillNode = listNode.getFirstChild(); skillNode != null; skillNode = skillNode.getNextSibling())
{
final String skillNodeName = skillNode.getNodeName();
switch (skillNodeName.toLowerCase())
{
case "variable":
{
attributes = skillNode.getAttributes();
final String name = "@" + parseString(attributes, "name");
variableGeneralValues.put(name, parseValues(skillNode, variableValues.computeIfAbsent(name, k -> new HashMap<>())));
break;
}
case "#text":
{
break;
}
default:
{
final EffectScope effectScope = EffectScope.findByXmlNodeName(skillNodeName);
if (effectScope != null)
{
for (Node effectsNode = skillNode.getFirstChild(); effectsNode != null; effectsNode = effectsNode.getNextSibling())
{
switch (effectsNode.getNodeName().toLowerCase())
{
case "effect":
{
effectParamInfo.computeIfAbsent(effectScope, k -> new LinkedList<>()).add(parseNamedParamInfo(effectsNode, variableValues, variableGeneralValues));
break;
}
}
}
break;
}
final SkillConditionScope skillConditionScope = SkillConditionScope.findByXmlNodeName(skillNodeName);
if (skillConditionScope != null)
{
for (Node conditionNode = skillNode.getFirstChild(); conditionNode != null; conditionNode = conditionNode.getNextSibling())
{
switch (conditionNode.getNodeName().toLowerCase())
{
case "condition":
{
conditionParamInfo.computeIfAbsent(skillConditionScope, k -> new LinkedList<>()).add(parseNamedParamInfo(conditionNode, variableValues, variableGeneralValues));
break;
}
}
}
}
else
{
parseInfo(skillNode, variableValues, variableGeneralValues, skillInfo, generalSkillInfo);
}
break;
}
}
}
final int fromLevel = generalSkillInfo.getInt(".fromLevel", 1);
final int toLevel = generalSkillInfo.getInt(".toLevel", 0);
for (int i = fromLevel; i <= toLevel; i++)
{
levels.computeIfAbsent(i, k -> new HashSet<>()).add(0);
}
skillInfo.forEach((level, subLevelMap) ->
{
subLevelMap.forEach((subLevel, statsSet) ->
{
levels.computeIfAbsent(level, k -> new HashSet<>()).add(subLevel);
});
});
Stream.concat(effectParamInfo.values().stream(), conditionParamInfo.values().stream()).forEach(namedParamInfos ->
{
namedParamInfos.forEach(namedParamInfo ->
{
namedParamInfo.getInfo().forEach((level, subLevelMap) ->
{
subLevelMap.forEach((subLevel, statsSet) ->
{
levels.computeIfAbsent(level, k -> new HashSet<>()).add(subLevel);
});
});
if ((namedParamInfo.getFromLevel() != null) && (namedParamInfo.getToLevel() != null))
{
for (int i = namedParamInfo.getFromLevel(); i <= namedParamInfo.getToLevel(); i++)
{
if ((namedParamInfo.getFromSubLevel() != null) && (namedParamInfo.getToSubLevel() != null))
{
for (int j = namedParamInfo.getFromSubLevel(); j <= namedParamInfo.getToSubLevel(); j++)
{
levels.computeIfAbsent(i, k -> new HashSet<>()).add(j);
}
}
else
{
levels.computeIfAbsent(i, k -> new HashSet<>()).add(0);
}
}
}
});
});
levels.forEach((level, subLevels) ->
{
subLevels.forEach(subLevel ->
{
final StatsSet statsSet = Optional.ofNullable(skillInfo.getOrDefault(level, Collections.emptyMap()).get(subLevel)).orElseGet(() -> new StatsSet());
generalSkillInfo.getSet().forEach((k, v) -> statsSet.getSet().putIfAbsent(k, v));
statsSet.set(".level", level);
statsSet.set(".subLevel", subLevel);
final Skill skill = new Skill(statsSet);
forEachNamedParamInfoParam(effectParamInfo, level, subLevel, ((effectScope, params) ->
{
final String effectName = params.getString(".name");
params.remove(".name");
try
{
final Function<StatsSet, AbstractEffect> effectFunction = EffectHandler.getInstance().getHandlerFactory(effectName);
if (effectFunction != null)
{
skill.addEffect(effectScope, effectFunction.apply(params));
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Missing effect for Skill Id[" + statsSet.getInt(".id") + "] Level[" + level + "] SubLevel[" + subLevel + "] Effect Scope[" + effectScope + "] Effect Name[" + effectName + "]");
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed loading effect for Skill Id[" + statsSet.getInt(".id") + "] Level[" + level + "] SubLevel[" + subLevel + "] Effect Scope[" + effectScope + "] Effect Name[" + effectName + "]", e);
}
}));
forEachNamedParamInfoParam(conditionParamInfo, level, subLevel, ((skillConditionScope, params) ->
{
final String conditionName = params.getString(".name");
params.remove(".name");
try
{
final Function<StatsSet, ISkillCondition> conditionFunction = SkillConditionHandler.getInstance().getHandlerFactory(conditionName);
if (conditionFunction != null)
{
skill.addCondition(skillConditionScope, conditionFunction.apply(params));
}
else
{
LOGGER.warning(getClass().getSimpleName() + ": Missing condition for Skill Id[" + statsSet.getInt(".id") + "] Level[" + level + "] SubLevel[" + subLevel + "] Effect Scope[" + skillConditionScope + "] Effect Name[" + conditionName + "]");
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Failed loading condition for Skill Id[" + statsSet.getInt(".id") + "] Level[" + level + "] SubLevel[" + subLevel + "] Condition Scope[" + skillConditionScope + "] Condition Name[" + conditionName + "]", e);
}
}));
_skills.put(getSkillHashCode(skill), skill);
_skillsMaxLevel.merge(skill.getId(), skill.getLevel(), Integer::max);
if ((skill.getLevel() > 99) && !_enchantable.contains(skill.getId()))
{
_enchantable.add(skill.getId());
}
});
});
}
}
}
}
}
private <T> void forEachNamedParamInfoParam(Map<T, List<NamedParamInfo>> paramInfo, int level, int subLevel, BiConsumer<T, StatsSet> consumer)
{
paramInfo.forEach((scope, namedParamInfos) ->
{
namedParamInfos.forEach(namedParamInfo ->
{
if (((namedParamInfo.getFromLevel() == null) && (namedParamInfo.getToLevel() == null)) || ((namedParamInfo.getFromLevel() <= level) && (namedParamInfo.getToLevel() >= level)))
{
if (((namedParamInfo.getFromSubLevel() == null) && (namedParamInfo.getToSubLevel() == null)) || ((namedParamInfo.getFromSubLevel() <= subLevel) && (namedParamInfo.getToSubLevel() >= subLevel)))
{
final StatsSet params = Optional.ofNullable(namedParamInfo.getInfo().getOrDefault(level, Collections.emptyMap()).get(subLevel)).orElseGet(() -> new StatsSet());
namedParamInfo.getGeneralInfo().getSet().forEach((k, v) -> params.getSet().putIfAbsent(k, v));
params.set(".name", namedParamInfo.getName());
consumer.accept(scope, params);
}
}
});
});
}
private NamedParamInfo parseNamedParamInfo(Node node, Map<String, Map<Integer, Map<Integer, Object>>> variableValues, Map<String, Object> variableGeneralValues)
{
final NamedNodeMap attributes = node.getAttributes();
final String name = parseString(attributes, "name");
final Integer level = parseInteger(attributes, "level");
final Integer fromLevel = parseInteger(attributes, "fromLevel", level);
final Integer toLevel = parseInteger(attributes, "toLevel", level);
final Integer subLevel = parseInteger(attributes, "subLevel", 0);
final Integer fromSubLevel = parseInteger(attributes, "fromSubLevel", subLevel);
final Integer toSubLevel = parseInteger(attributes, "toSubLevel", subLevel);
final Map<Integer, Map<Integer, StatsSet>> info = new HashMap<>();
final StatsSet generalInfo = new StatsSet();
for (node = node.getFirstChild(); node != null; node = node.getNextSibling())
{
if (!node.getNodeName().equals("#text"))
{
parseInfo(node, variableValues, variableGeneralValues, info, generalInfo);
}
}
return new NamedParamInfo(name, fromLevel, toLevel, fromSubLevel, toSubLevel, info, generalInfo);
}
private void parseInfo(Node node, Map<String, Map<Integer, Map<Integer, Object>>> variableValues, Map<String, Object> variableGeneralValues, Map<Integer, Map<Integer, StatsSet>> info, StatsSet generalInfo)
{
Map<Integer, Map<Integer, Object>> values = new HashMap<>();
final Object generalValue = parseValues(node, values);
if (generalValue != null)
{
final String stringGeneralValue = String.valueOf(generalValue);
if (stringGeneralValue.startsWith("@"))
{
final Map<Integer, Map<Integer, Object>> tableValue = variableValues.get(stringGeneralValue);
if (tableValue != null)
{
if (!tableValue.isEmpty())
{
values = tableValue;
}
else
{
generalInfo.set(node.getNodeName(), variableGeneralValues.get(stringGeneralValue));
}
}
else
{
throw new IllegalArgumentException("undefined variable " + stringGeneralValue);
}
}
else
{
generalInfo.set(node.getNodeName(), generalValue);
}
}
values.forEach((level, subLevelMap) ->
{
subLevelMap.forEach((subLevel, value) ->
{
info.computeIfAbsent(level, k -> new HashMap<>()).computeIfAbsent(subLevel, k -> new StatsSet()).set(node.getNodeName(), value);
});
});
}
private Object parseValues(Node node, Map<Integer, Map<Integer, Object>> values)
{
Object parsedValue = parseValue(node, true, false, Collections.emptyMap());
if (parsedValue != null)
{
return parsedValue;
}
final List<Object> list = null;
for (node = node.getFirstChild(); node != null; node = node.getNextSibling())
{
if (node.getNodeName().equalsIgnoreCase("value"))
{
final NamedNodeMap attributes = node.getAttributes();
final Integer level = parseInteger(attributes, "level");
if (level != null)
{
parsedValue = parseValue(node, false, false, Collections.emptyMap());
if (parsedValue != null)
{
final Integer subLevel = parseInteger(attributes, "subLevel", 0);
values.computeIfAbsent(level, k -> new HashMap<>()).put(subLevel, parsedValue);
}
}
else
{
final int fromLevel = parseInteger(attributes, "fromLevel");
final int toLevel = parseInteger(attributes, "toLevel");
final int fromSubLevel = parseInteger(attributes, "fromSubLevel", 0);
final int toSubLevel = parseInteger(attributes, "toSubLevel", 0);
for (int i = fromLevel; i <= toLevel; i++)
{
for (int j = fromSubLevel; j <= toSubLevel; j++)
{
final Map<Integer, Object> subValues = values.computeIfAbsent(i, k -> new HashMap<>());
final Map<String, Double> variables = new HashMap<>();
variables.put("index", (i - fromLevel) + 1d);
variables.put("subIndex", (j - fromSubLevel) + 1d);
final Object base = values.getOrDefault(i, Collections.emptyMap()).get(0);
if ((base != null) && !(base instanceof StatsSet))
{
variables.put("base", Double.parseDouble(String.valueOf(base)));
}
parsedValue = parseValue(node, false, false, variables);
if (parsedValue != null)
{
subValues.put(j, parsedValue);
}
}
}
}
}
}
return list;
}
Object parseValue(Node node, boolean blockValue, boolean parseAttributes, Map<String, Double> variables)
{
StatsSet statsSet = null;
List<Object> list = null;
Object text = null;
if (parseAttributes && (!node.getNodeName().equals("value") || !blockValue) && (node.getAttributes().getLength() > 0))
{
statsSet = new StatsSet();
parseAttributes(node.getAttributes(), "", statsSet, variables);
}
for (node = node.getFirstChild(); node != null; node = node.getNextSibling())
{
final String nodeName = node.getNodeName();
switch (node.getNodeName())
{
case "#text":
{
final String value = node.getNodeValue().trim();
if (!value.isEmpty())
{
text = parseNodeValue(value, variables);
}
break;
}
case "item":
{
if (list == null)
{
list = new LinkedList<>();
}
final Object value = parseValue(node, false, true, variables);
if (value != null)
{
list.add(value);
}
break;
}
case "value":
{
if (blockValue)
{
break;
}
}
default:
{
final Object value = parseValue(node, false, true, variables);
if (value != null)
{
if (statsSet == null)
{
statsSet = new StatsSet();
}
statsSet.set(nodeName, value);
}
}
}
}
if (list != null)
{
if (text != null)
{
throw new IllegalArgumentException("Text and list in same node are not allowed. Node[" + node + "]");
}
if (statsSet != null)
{
statsSet.set(".", list);
}
else
{
return list;
}
}
if (text != null)
{
if (list != null)
{
throw new IllegalArgumentException("Text and list in same node are not allowed. Node[" + node + "]");
}
if (statsSet != null)
{
statsSet.set(".", text);
}
else
{
return text;
}
}
return statsSet;
}
private void parseAttributes(NamedNodeMap attributes, String prefix, StatsSet statsSet, Map<String, Double> variables)
{
for (int i = 0; i < attributes.getLength(); i++)
{
final Node attributeNode = attributes.item(i);
statsSet.set(prefix + "." + attributeNode.getNodeName(), parseNodeValue(attributeNode.getNodeValue(), variables));
}
}
private void parseAttributes(NamedNodeMap attributes, String prefix, StatsSet statsSet)
{
parseAttributes(attributes, prefix, statsSet, Collections.emptyMap());
}
private Object parseNodeValue(String value, Map<String, Double> variables)
{
if (value.startsWith("{") && value.endsWith("}"))
{
return new ExpressionBuilder(value).variables(variables.keySet()).build().setVariables(variables).evaluate();
}
return value;
}
public static SkillData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SkillData _instance = new SkillData();
}
}

View File

@@ -0,0 +1,103 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.base.ClassId;
/**
* Holds all skill learn data for all npcs.
* @author xban1x
*/
public final class SkillLearnData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(SkillLearnData.class.getName());
private final Map<Integer, List<ClassId>> _skillLearn = new HashMap<>();
protected SkillLearnData()
{
load();
}
@Override
public synchronized void load()
{
_skillLearn.clear();
parseDatapackFile("data/SkillLearn.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _skillLearn.size() + " Skill Learn data.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node node = doc.getFirstChild(); node != null; node = node.getNextSibling())
{
if ("list".equalsIgnoreCase(node.getNodeName()))
{
for (Node list_node = node.getFirstChild(); list_node != null; list_node = list_node.getNextSibling())
{
if ("npc".equalsIgnoreCase(list_node.getNodeName()))
{
final List<ClassId> classIds = new ArrayList<>();
for (Node c = list_node.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("classId".equalsIgnoreCase(c.getNodeName()))
{
classIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
}
}
_skillLearn.put(parseInteger(list_node.getAttributes(), "id"), classIds);
}
}
}
}
}
/**
* @param npcId
* @return {@link List} of {@link ClassId}'s that this npcId can teach.
*/
public List<ClassId> getSkillLearnData(int npcId)
{
return _skillLearn.get(npcId);
}
/**
* Gets the single instance of SkillLearnData.
* @return single instance of SkillLearnData
*/
public static SkillLearnData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SkillLearnData _instance = new SkillLearnData();
}
}

View File

@@ -0,0 +1,310 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.commons.util.IXmlReader;
import com.l2jmobius.gameserver.model.ChanceLocation;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jmobius.gameserver.model.holders.MinionHolder;
import com.l2jmobius.gameserver.model.interfaces.IParameterized;
import com.l2jmobius.gameserver.model.interfaces.ITerritorized;
import com.l2jmobius.gameserver.model.spawns.NpcSpawnTemplate;
import com.l2jmobius.gameserver.model.spawns.SpawnGroup;
import com.l2jmobius.gameserver.model.spawns.SpawnTemplate;
import com.l2jmobius.gameserver.model.zone.form.ZoneNPoly;
import com.l2jmobius.gameserver.model.zone.type.L2BannedSpawnTerritory;
import com.l2jmobius.gameserver.model.zone.type.L2SpawnTerritory;
/**
* @author UnAfraid
*/
public class SpawnsData implements IGameXmlReader
{
protected static final Logger LOGGER = Logger.getLogger(SpawnsData.class.getName());
private final List<SpawnTemplate> _spawns = new LinkedList<>();
protected SpawnsData()
{
load();
}
@Override
public void load()
{
parseDatapackDirectory("data/spawns", true);
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _spawns.stream().flatMap(c -> c.getGroups().stream()).flatMap(c -> c.getSpawns().stream()).count() + " spawns");
}
@Override
public void parseDocument(Document doc, File f)
{
forEach(doc, "list", listNode -> forEach(listNode, "spawn", spawnNode ->
{
try
{
parseSpawn(spawnNode, f, _spawns);
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error while processing spawn in file: " + f.getAbsolutePath(), e);
}
}));
}
/**
* Initializing all spawns
*/
public void init()
{
LOGGER.info(getClass().getSimpleName() + ": Initializing spawns...");
_spawns.stream().filter(SpawnTemplate::isSpawningByDefault).forEach(template ->
{
template.spawnAll(null);
template.notifyActivate();
});
LOGGER.info(getClass().getSimpleName() + ": All spawns has been initialized!");
}
/**
* Removing all spawns
*/
public void despawnAll()
{
LOGGER.info(getClass().getSimpleName() + ": Removing all spawns...");
_spawns.forEach(SpawnTemplate::despawnAll);
LOGGER.info(getClass().getSimpleName() + ": All spawns has been removed!");
}
public List<SpawnTemplate> getSpawns()
{
return _spawns;
}
public List<NpcSpawnTemplate> getSpawns(Predicate<NpcSpawnTemplate> condition)
{
return _spawns.stream().flatMap(template -> template.getGroups().stream()).flatMap(group -> group.getSpawns().stream()).filter(condition).collect(Collectors.toList());
}
public void parseSpawn(Node spawnsNode, File file, List<SpawnTemplate> spawns)
{
final SpawnTemplate spawnTemplate = new SpawnTemplate(new StatsSet(parseAttributes(spawnsNode)), file);
SpawnGroup defaultGroup = null;
for (Node innerNode = spawnsNode.getFirstChild(); innerNode != null; innerNode = innerNode.getNextSibling())
{
if ("territories".equalsIgnoreCase(innerNode.getNodeName()))
{
parseTerritories(innerNode, spawnTemplate.getFile(), spawnTemplate);
}
else if ("group".equalsIgnoreCase(innerNode.getNodeName()))
{
parseGroup(innerNode, spawnTemplate);
}
else if ("npc".equalsIgnoreCase(innerNode.getNodeName()))
{
if (defaultGroup == null)
{
defaultGroup = new SpawnGroup(StatsSet.EMPTY_STATSET);
}
parseNpc(innerNode, spawnTemplate, defaultGroup);
}
else if ("parameters".equalsIgnoreCase(innerNode.getNodeName()))
{
parseParameters(spawnsNode, spawnTemplate);
}
}
// One static group for all npcs outside group scope
if (defaultGroup != null)
{
spawnTemplate.addGroup(defaultGroup);
}
spawns.add(spawnTemplate);
}
/**
* @param innerNode
* @param file
* @param spawnTemplate
*/
private void parseTerritories(Node innerNode, File file, ITerritorized spawnTemplate)
{
forEach(innerNode, IXmlReader::isNode, territoryNode ->
{
final String name = parseString(territoryNode.getAttributes(), "name", file.getName() + "_" + (spawnTemplate.getTerritories().size() + 1));
final int minZ = parseInteger(territoryNode.getAttributes(), "minZ");
final int maxZ = parseInteger(territoryNode.getAttributes(), "maxZ");
final List<Integer> xNodes = new ArrayList<>();
final List<Integer> yNodes = new ArrayList<>();
forEach(territoryNode, "node", node ->
{
xNodes.add(parseInteger(node.getAttributes(), "x"));
yNodes.add(parseInteger(node.getAttributes(), "y"));
});
final int[] x = xNodes.stream().mapToInt(Integer::valueOf).toArray();
final int[] y = yNodes.stream().mapToInt(Integer::valueOf).toArray();
switch (territoryNode.getNodeName())
{
case "territory":
{
spawnTemplate.addTerritory(new L2SpawnTerritory(name, new ZoneNPoly(x, y, minZ, maxZ)));
break;
}
case "banned_territory":
{
spawnTemplate.addBannedTerritory(new L2BannedSpawnTerritory(name, new ZoneNPoly(x, y, minZ, maxZ)));
break;
}
}
});
}
private void parseGroup(Node n, SpawnTemplate spawnTemplate)
{
final SpawnGroup group = new SpawnGroup(new StatsSet(parseAttributes(n)));
forEach(n, IXmlReader::isNode, npcNode ->
{
switch (npcNode.getNodeName())
{
case "territories":
{
parseTerritories(npcNode, spawnTemplate.getFile(), group);
break;
}
case "npc":
{
parseNpc(npcNode, spawnTemplate, group);
break;
}
}
});
spawnTemplate.addGroup(group);
}
/**
* @param n
* @param spawnTemplate
* @param group
*/
private void parseNpc(Node n, SpawnTemplate spawnTemplate, SpawnGroup group)
{
final NpcSpawnTemplate npcTemplate = new NpcSpawnTemplate(spawnTemplate, group, new StatsSet(parseAttributes(n)));
final L2NpcTemplate template = NpcData.getInstance().getTemplate(npcTemplate.getId());
if (template == null)
{
LOGGER.warning(getClass().getSimpleName() + ": Requested spawn for non existing npc: " + npcTemplate.getId() + " in file: " + spawnTemplate.getFile().getName());
return;
}
if (template.isType("L2Servitor") || template.isType("L2Pet"))
{
LOGGER.warning(getClass().getSimpleName() + ": Requested spawn for " + template.getType() + " " + template.getName() + "(" + template.getId() + ") file: " + spawnTemplate.getFile().getName());
return;
}
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("parameters".equalsIgnoreCase(d.getNodeName()))
{
parseParameters(d, npcTemplate);
}
else if ("minions".equalsIgnoreCase(d.getNodeName()))
{
parseMinions(d, npcTemplate);
}
else if ("locations".equalsIgnoreCase(d.getNodeName()))
{
parseLocations(d, npcTemplate);
}
}
group.addSpawn(npcTemplate);
}
/**
* @param n
* @param npcTemplate
*/
private void parseLocations(Node n, NpcSpawnTemplate npcTemplate)
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("location".equalsIgnoreCase(d.getNodeName()))
{
final int x = parseInteger(d.getAttributes(), "x");
final int y = parseInteger(d.getAttributes(), "y");
final int z = parseInteger(d.getAttributes(), "z");
final int heading = parseInteger(d.getAttributes(), "heading", 0);
final double chance = parseDouble(d.getAttributes(), "chance");
npcTemplate.addSpawnLocation(new ChanceLocation(x, y, z, heading, chance));
}
}
}
/**
* @param n
* @param npcTemplate
*/
private void parseParameters(Node n, IParameterized<StatsSet> npcTemplate)
{
final Map<String, Object> params = parseParameters(n);
npcTemplate.setParameters(!params.isEmpty() ? new StatsSet(Collections.unmodifiableMap(params)) : StatsSet.EMPTY_STATSET);
}
/**
* @param n
* @param npcTemplate
*/
private void parseMinions(Node n, NpcSpawnTemplate npcTemplate)
{
forEach(n, "minion", minionNode ->
{
npcTemplate.addMinion(new MinionHolder(new StatsSet(parseAttributes(minionNode))));
});
}
/**
* Gets the single instance of SpawnsData.
* @return single instance of SpawnsData
*/
public static SpawnsData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final SpawnsData _instance = new SpawnsData();
}
}

View File

@@ -0,0 +1,121 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.instance.L2StaticObjectInstance;
import com.l2jmobius.gameserver.model.actor.templates.L2CharTemplate;
/**
* This class loads and holds all static object data.
* @author UnAfraid
*/
public final class StaticObjectData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(StaticObjectData.class.getName());
private final Map<Integer, L2StaticObjectInstance> _staticObjects = new HashMap<>();
/**
* Instantiates a new static objects.
*/
protected StaticObjectData()
{
load();
}
@Override
public void load()
{
_staticObjects.clear();
parseDatapackFile("data/StaticObjects.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _staticObjects.size() + " static object templates.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("object".equalsIgnoreCase(d.getNodeName()))
{
final NamedNodeMap attrs = d.getAttributes();
final StatsSet set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
addObject(set);
}
}
}
}
}
/**
* Initialize an static object based on the stats set and add it to the map.
* @param set the stats set to add.
*/
private void addObject(StatsSet set)
{
final L2StaticObjectInstance obj = new L2StaticObjectInstance(new L2CharTemplate(new StatsSet()), set.getInt("id"));
obj.setType(set.getInt("type", 0));
obj.setName(set.getString("name"));
obj.setMap(set.getString("texture", "none"), set.getInt("map_x", 0), set.getInt("map_y", 0));
obj.spawnMe(set.getInt("x"), set.getInt("y"), set.getInt("z"));
_staticObjects.put(obj.getObjectId(), obj);
}
/**
* Gets the static objects.
* @return a collection of static objects.
*/
public Collection<L2StaticObjectInstance> getStaticObjects()
{
return _staticObjects.values();
}
/**
* Gets the single instance of StaticObjects.
* @return single instance of StaticObjects
*/
public static StaticObjectData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final StaticObjectData _instance = new StaticObjectData();
}
}

View File

@@ -0,0 +1,134 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.teleporter.TeleportHolder;
import com.l2jmobius.gameserver.model.teleporter.TeleportLocation;
import com.l2jmobius.gameserver.model.teleporter.TeleportType;
/**
* @author UnAfraid
*/
public class TeleportersData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(TeleportersData.class.getName());
private final Map<Integer, TeleportHolder> _teleporters = new HashMap<>();
protected TeleportersData()
{
load();
}
@Override
public void load()
{
_teleporters.clear();
parseDatapackDirectory("data/teleporters", true);
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _teleporters.size() + " npc teleporters.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node listNode = doc.getFirstChild(); listNode != null; listNode = listNode.getNextSibling())
{
if ("list".equals(listNode.getNodeName()))
{
for (Node npcNode = listNode.getFirstChild(); npcNode != null; npcNode = npcNode.getNextSibling())
{
if ("npc".equals(npcNode.getNodeName()))
{
final int id = parseInteger(npcNode.getAttributes(), "id");
final TeleportHolder holder = new TeleportHolder(id);
for (Node tpNode = npcNode.getFirstChild(); tpNode != null; tpNode = tpNode.getNextSibling())
{
if ("teleport".equals(tpNode.getNodeName()))
{
final TeleportType type = parseEnum(tpNode.getAttributes(), TeleportType.class, "type", TeleportType.NORMAL);
for (Node locNode = tpNode.getFirstChild(); locNode != null; locNode = locNode.getNextSibling())
{
if ("location".equals(locNode.getNodeName()))
{
final NamedNodeMap attrs = locNode.getAttributes();
final int nextId = holder.getLocations(type).size() + 1;
final StatsSet set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node locationNode = attrs.item(i);
set.set(locationNode.getNodeName(), locationNode.getNodeValue());
}
holder.addLocation(type, new TeleportLocation(nextId, set));
}
}
}
else if ("npcs".equals(tpNode.getNodeName()))
{
for (Node locNode = tpNode.getFirstChild(); locNode != null; locNode = locNode.getNextSibling())
{
if ("npc".equals(locNode.getNodeName()))
{
final int npcId = parseInteger(locNode.getAttributes(), "id");
if (_teleporters.putIfAbsent(npcId, holder) != null)
{
LOGGER.warning(getClass().getSimpleName() + ": Duplicate location entires for npc: " + npcId);
}
}
}
}
}
if (_teleporters.putIfAbsent(id, holder) != null)
{
LOGGER.warning(getClass().getSimpleName() + ": Duplicate location entires for npc: " + id);
}
}
}
}
}
}
public TeleportHolder getHolder(int npcId)
{
return _teleporters.get(npcId);
}
/**
* Gets the single instance of TeleportersData.
* @return single instance of TeleportersData
*/
public static TeleportersData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final TeleportersData _instance = new TeleportersData();
}
}

View File

@@ -0,0 +1,236 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.StatsSet;
import com.l2jmobius.gameserver.model.actor.transform.Transform;
import com.l2jmobius.gameserver.model.actor.transform.TransformLevelData;
import com.l2jmobius.gameserver.model.actor.transform.TransformTemplate;
import com.l2jmobius.gameserver.model.holders.AdditionalItemHolder;
import com.l2jmobius.gameserver.model.holders.AdditionalSkillHolder;
import com.l2jmobius.gameserver.model.holders.SkillHolder;
import com.l2jmobius.gameserver.network.serverpackets.ExBasicActionList;
/**
* Transformation data.
* @author UnAfraid
*/
public final class TransformData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(TransformData.class.getName());
private final Map<Integer, Transform> _transformData = new HashMap<>();
protected TransformData()
{
load();
}
@Override
public synchronized void load()
{
_transformData.clear();
parseDatapackDirectory("data/stats/transformations", false);
LOGGER.info(getClass().getSimpleName() + ": Loaded: " + _transformData.size() + " transform templates.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("transform".equalsIgnoreCase(d.getNodeName()))
{
NamedNodeMap attrs = d.getAttributes();
final StatsSet set = new StatsSet();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
final Transform transform = new Transform(set);
for (Node cd = d.getFirstChild(); cd != null; cd = cd.getNextSibling())
{
final boolean isMale = "Male".equalsIgnoreCase(cd.getNodeName());
if ("Male".equalsIgnoreCase(cd.getNodeName()) || "Female".equalsIgnoreCase(cd.getNodeName()))
{
TransformTemplate templateData = null;
for (Node z = cd.getFirstChild(); z != null; z = z.getNextSibling())
{
switch (z.getNodeName())
{
case "common":
{
for (Node s = z.getFirstChild(); s != null; s = s.getNextSibling())
{
switch (s.getNodeName())
{
case "base":
case "stats":
case "defense":
case "magicDefense":
case "collision":
case "moving":
{
attrs = s.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node att = attrs.item(i);
set.set(att.getNodeName(), att.getNodeValue());
}
break;
}
}
}
templateData = new TransformTemplate(set);
transform.setTemplate(isMale, templateData);
break;
}
case "skills":
{
if (templateData == null)
{
templateData = new TransformTemplate(set);
transform.setTemplate(isMale, templateData);
}
for (Node s = z.getFirstChild(); s != null; s = s.getNextSibling())
{
if ("skill".equals(s.getNodeName()))
{
attrs = s.getAttributes();
final int skillId = parseInteger(attrs, "id");
final int skillLevel = parseInteger(attrs, "level");
templateData.addSkill(new SkillHolder(skillId, skillLevel));
}
}
break;
}
case "actions":
{
if (templateData == null)
{
templateData = new TransformTemplate(set);
transform.setTemplate(isMale, templateData);
}
set.set("actions", z.getTextContent());
final int[] actions = set.getIntArray("actions", " ");
templateData.setBasicActionList(new ExBasicActionList(actions));
break;
}
case "additionalSkills":
{
if (templateData == null)
{
templateData = new TransformTemplate(set);
transform.setTemplate(isMale, templateData);
}
for (Node s = z.getFirstChild(); s != null; s = s.getNextSibling())
{
if ("skill".equals(s.getNodeName()))
{
attrs = s.getAttributes();
final int skillId = parseInteger(attrs, "id");
final int skillLevel = parseInteger(attrs, "level");
final int minLevel = parseInteger(attrs, "minLevel");
templateData.addAdditionalSkill(new AdditionalSkillHolder(skillId, skillLevel, minLevel));
}
}
break;
}
case "items":
{
if (templateData == null)
{
templateData = new TransformTemplate(set);
transform.setTemplate(isMale, templateData);
}
for (Node s = z.getFirstChild(); s != null; s = s.getNextSibling())
{
if ("item".equals(s.getNodeName()))
{
attrs = s.getAttributes();
final int itemId = parseInteger(attrs, "id");
final boolean allowed = parseBoolean(attrs, "allowed");
templateData.addAdditionalItem(new AdditionalItemHolder(itemId, allowed));
}
}
break;
}
case "levels":
{
if (templateData == null)
{
templateData = new TransformTemplate(set);
transform.setTemplate(isMale, templateData);
}
final StatsSet levelsSet = new StatsSet();
for (Node s = z.getFirstChild(); s != null; s = s.getNextSibling())
{
if ("level".equals(s.getNodeName()))
{
attrs = s.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Node att = attrs.item(i);
levelsSet.set(att.getNodeName(), att.getNodeValue());
}
}
}
templateData.addLevelData(new TransformLevelData(levelsSet));
break;
}
}
}
}
}
_transformData.put(transform.getId(), transform);
}
}
}
}
}
public Transform getTransform(int id)
{
return _transformData.get(id);
}
public static TransformData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final TransformData _instance = new TransformData();
}
}

View File

@@ -0,0 +1,194 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.l2jmobius.gameserver.data.xml.impl;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import com.l2jmobius.commons.util.IGameXmlReader;
import com.l2jmobius.gameserver.model.ActionKey;
/**
* UI Data parser.
* @author Zoey76
*/
public class UIData implements IGameXmlReader
{
private static final Logger LOGGER = Logger.getLogger(UIData.class.getName());
private final Map<Integer, List<ActionKey>> _storedKeys = new HashMap<>();
private final Map<Integer, List<Integer>> _storedCategories = new HashMap<>();
protected UIData()
{
load();
}
@Override
public void load()
{
_storedKeys.clear();
_storedCategories.clear();
parseDatapackFile("data/ui/ui_en.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _storedKeys.size() + " keys " + _storedCategories.size() + " categories.");
}
@Override
public void parseDocument(Document doc, File f)
{
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("category".equalsIgnoreCase(d.getNodeName()))
{
parseCategory(d);
}
}
}
}
}
private void parseCategory(Node n)
{
final int cat = parseInteger(n.getAttributes(), "id");
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("commands".equalsIgnoreCase(d.getNodeName()))
{
parseCommands(cat, d);
}
else if ("keys".equalsIgnoreCase(d.getNodeName()))
{
parseKeys(cat, d);
}
}
}
private void parseCommands(int cat, Node d)
{
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("cmd".equalsIgnoreCase(c.getNodeName()))
{
addCategory(_storedCategories, cat, Integer.parseInt(c.getTextContent()));
}
}
}
private void parseKeys(int cat, Node d)
{
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("key".equalsIgnoreCase(c.getNodeName()))
{
final ActionKey akey = new ActionKey(cat);
for (int i = 0; i < c.getAttributes().getLength(); i++)
{
final Node att = c.getAttributes().item(i);
final int val = Integer.parseInt(att.getNodeValue());
switch (att.getNodeName())
{
case "cmd":
{
akey.setCommandId(val);
break;
}
case "key":
{
akey.setKeyId(val);
break;
}
case "toggleKey1":
{
akey.setToogleKey1(val);
break;
}
case "toggleKey2":
{
akey.setToogleKey2(val);
break;
}
case "showType":
{
akey.setShowStatus(val);
break;
}
}
}
addKey(_storedKeys, cat, akey);
}
}
}
/**
* Add a category to the stored categories.
* @param map the map to store the category
* @param cat the category
* @param cmd the command
*/
public static void addCategory(Map<Integer, List<Integer>> map, int cat, int cmd)
{
map.computeIfAbsent(cat, k -> new ArrayList<>()).add(cmd);
}
/**
* Create and insert an Action Key into the stored keys.
* @param map the map to store the key
* @param cat the category
* @param akey the action key
*/
public static void addKey(Map<Integer, List<ActionKey>> map, int cat, ActionKey akey)
{
map.computeIfAbsent(cat, k -> new ArrayList<>()).add(akey);
}
/**
* @return the categories
*/
public Map<Integer, List<Integer>> getCategories()
{
return _storedCategories;
}
/**
* @return the keys
*/
public Map<Integer, List<ActionKey>> getKeys()
{
return _storedKeys;
}
public static UIData getInstance()
{
return SingletonHolder._instance;
}
private static class SingletonHolder
{
protected static final UIData _instance = new UIData();
}
}