/* * Copyright (C) 2004-2014 L2J Server * * This file is part of L2J Server. * * L2J Server is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * L2J Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.l2jserver.gameserver.model.event; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.logging.Level; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import com.l2jserver.gameserver.Announcements; import com.l2jserver.gameserver.ThreadPoolManager; import com.l2jserver.gameserver.datatables.EventDroplist; import com.l2jserver.gameserver.datatables.ItemTable; import com.l2jserver.gameserver.datatables.NpcData; import com.l2jserver.gameserver.model.Location; import com.l2jserver.gameserver.model.drops.GeneralDropItem; import com.l2jserver.gameserver.model.quest.Quest; import com.l2jserver.gameserver.script.DateRange; /** * Parent class for long time events.
* Maintains config reading, spawn of NPC's, adding of event's drop. * @author GKR */ public class LongTimeEvent extends Quest { private String _eventName; // Messages private String _onEnterMsg = "Event is in process"; protected String _endMsg = "Event ends!"; private DateRange _eventPeriod = null; private DateRange _dropPeriod; // NPC's to spawm and their spawn points private final List _spawnList = new ArrayList<>(); // Drop data for event private final List _dropList = new ArrayList<>(); private class NpcSpawn { protected final Location loc; protected final int npcId; protected NpcSpawn(int pNpcId, Location spawnLoc) { loc = spawnLoc; npcId = pNpcId; } } public LongTimeEvent(String name, String descr) { super(-1, name, descr); loadConfig(); if (_eventPeriod != null) { if (_eventPeriod.isWithinRange(new Date())) { startEvent(); _log.info("Event " + _eventName + " active till " + _eventPeriod.getEndDate()); } else if (_eventPeriod.getStartDate().after(new Date())) { long delay = _eventPeriod.getStartDate().getTime() - System.currentTimeMillis(); ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStart(), delay); _log.info("Event " + _eventName + " will be started at " + _eventPeriod.getEndDate()); } else { _log.info("Event " + _eventName + " has passed... Ignored "); } } } /** * Load event configuration file */ private void loadConfig() { File configFile = new File("data/scripts/events/" + getScriptName() + "/config.xml"); try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(configFile); if (!doc.getDocumentElement().getNodeName().equalsIgnoreCase("event")) { throw new NullPointerException("WARNING!!! " + getScriptName() + " event: bad config file!"); } _eventName = doc.getDocumentElement().getAttributes().getNamedItem("name").getNodeValue(); String period = doc.getDocumentElement().getAttributes().getNamedItem("active").getNodeValue(); _eventPeriod = DateRange.parse(period, new SimpleDateFormat("dd MM yyyy", Locale.US)); if (doc.getDocumentElement().getAttributes().getNamedItem("dropPeriod") != null) { String dropPeriod = doc.getDocumentElement().getAttributes().getNamedItem("dropPeriod").getNodeValue(); _dropPeriod = DateRange.parse(dropPeriod, new SimpleDateFormat("dd MM yyyy", Locale.US)); // Check if drop period is within range of event period if (!_eventPeriod.isWithinRange(_dropPeriod.getStartDate()) || !_eventPeriod.isWithinRange(_dropPeriod.getEndDate())) { _dropPeriod = _eventPeriod; } } else { _dropPeriod = _eventPeriod; // Drop period, if not specified, assumes all event period. } if (_eventPeriod == null) { throw new NullPointerException("WARNING!!! " + getScriptName() + " event: illegal event period"); } Date today = new Date(); if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today)) { Node first = doc.getDocumentElement().getFirstChild(); for (Node n = first; n != null; n = n.getNextSibling()) { // Loading droplist if (n.getNodeName().equalsIgnoreCase("droplist")) { for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) { if (d.getNodeName().equalsIgnoreCase("add")) { try { int itemId = Integer.parseInt(d.getAttributes().getNamedItem("item").getNodeValue()); int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue()); int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue()); String chance = d.getAttributes().getNamedItem("chance").getNodeValue(); int finalChance = 0; if (!chance.isEmpty() && chance.endsWith("%")) { finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000; } if (ItemTable.getInstance().getTemplate(itemId) == null) { _log.warning(getScriptName() + " event: " + itemId + " is wrong item id, item was not added in droplist"); continue; } if (minCount > maxCount) { _log.warning(getScriptName() + " event: item " + itemId + " - min greater than max, item was not added in droplist"); continue; } if ((finalChance < 10000) || (finalChance > 1000000)) { _log.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist"); continue; } _dropList.add(new GeneralDropItem(itemId, minCount, maxCount, finalChance)); } catch (NumberFormatException nfe) { _log.warning("Wrong number format in config.xml droplist block for " + getScriptName() + " event"); } } } } else if (n.getNodeName().equalsIgnoreCase("spawnlist")) { // Loading spawnlist for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) { if (d.getNodeName().equalsIgnoreCase("add")) { try { int npcId = Integer.parseInt(d.getAttributes().getNamedItem("npc").getNodeValue()); int xPos = Integer.parseInt(d.getAttributes().getNamedItem("x").getNodeValue()); int yPos = Integer.parseInt(d.getAttributes().getNamedItem("y").getNodeValue()); int zPos = Integer.parseInt(d.getAttributes().getNamedItem("z").getNodeValue()); int heading = d.getAttributes().getNamedItem("heading").getNodeValue() != null ? Integer.parseInt(d.getAttributes().getNamedItem("heading").getNodeValue()) : 0; if (NpcData.getInstance().getTemplate(npcId) == null) { _log.warning(getScriptName() + " event: " + npcId + " is wrong NPC id, NPC was not added in spawnlist"); continue; } _spawnList.add(new NpcSpawn(npcId, new Location(xPos, yPos, zPos, heading))); } catch (NumberFormatException nfe) { _log.warning("Wrong number format in config.xml spawnlist block for " + getScriptName() + " event"); } } } } else if (n.getNodeName().equalsIgnoreCase("messages")) { // Loading Messages for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) { if (d.getNodeName().equalsIgnoreCase("add")) { String msgType = d.getAttributes().getNamedItem("type").getNodeValue(); String msgText = d.getAttributes().getNamedItem("text").getNodeValue(); if ((msgType != null) && (msgText != null)) { if (msgType.equalsIgnoreCase("onEnd")) { _endMsg = msgText; } else if (msgType.equalsIgnoreCase("onEnter")) { _onEnterMsg = msgText; } } } } } } } } catch (Exception e) { _log.log(Level.WARNING, getScriptName() + " event: error reading " + configFile.getAbsolutePath() + " ! " + e.getMessage(), e); } } /** * Maintenance event start - adds global drop, spawns event NPC's, shows start announcement. */ protected void startEvent() { // Add drop if (_dropList != null) { for (GeneralDropItem drop : _dropList) { EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod); } } // Add spawns Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis(); if (_spawnList != null) { for (NpcSpawn spawn : _spawnList) { addSpawn(spawn.npcId, spawn.loc.getX(), spawn.loc.getY(), spawn.loc.getZ(), spawn.loc.getHeading(), false, millisToEventEnd, false); } } // Send message on begin Announcements.getInstance().announceToAll(_onEnterMsg); // Add announce for entering players Announcements.getInstance().addEventAnnouncement(_eventPeriod, _onEnterMsg); // Schedule event end (now only for message sending) ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEnd(), millisToEventEnd); } /** * @return event period */ public DateRange getEventPeriod() { return _eventPeriod; } /** * @return {@code true} if now is event period */ public boolean isEventPeriod() { return _eventPeriod.isWithinRange(new Date()); } /** * @return {@code true} if now is drop period */ public boolean isDropPeriod() { return _dropPeriod.isWithinRange(new Date()); } protected class ScheduleStart implements Runnable { @Override public void run() { startEvent(); } } protected class ScheduleEnd implements Runnable { @Override public void run() { // Send message on end Announcements.getInstance().announceToAll(_endMsg); } } }