LongTimeEvent.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (C) 2004-2014 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver.model.event;
  20. import java.io.File;
  21. import java.text.SimpleDateFormat;
  22. import java.util.ArrayList;
  23. import java.util.Date;
  24. import java.util.List;
  25. import java.util.Locale;
  26. import java.util.logging.Level;
  27. import javax.xml.parsers.DocumentBuilder;
  28. import javax.xml.parsers.DocumentBuilderFactory;
  29. import org.w3c.dom.Document;
  30. import org.w3c.dom.Node;
  31. import com.l2jserver.gameserver.Announcements;
  32. import com.l2jserver.gameserver.ThreadPoolManager;
  33. import com.l2jserver.gameserver.datatables.EventDroplist;
  34. import com.l2jserver.gameserver.datatables.ItemTable;
  35. import com.l2jserver.gameserver.datatables.NpcData;
  36. import com.l2jserver.gameserver.model.Location;
  37. import com.l2jserver.gameserver.model.drops.GeneralDropItem;
  38. import com.l2jserver.gameserver.model.quest.Quest;
  39. import com.l2jserver.gameserver.script.DateRange;
  40. /**
  41. * Parent class for long time events.<br>
  42. * Maintains config reading, spawn of NPC's, adding of event's drop.
  43. * @author GKR
  44. */
  45. public class LongTimeEvent extends Quest
  46. {
  47. private String _eventName;
  48. // Messages
  49. private String _onEnterMsg = "Event is in process";
  50. protected String _endMsg = "Event ends!";
  51. private DateRange _eventPeriod = null;
  52. private DateRange _dropPeriod;
  53. // NPC's to spawm and their spawn points
  54. private final List<NpcSpawn> _spawnList = new ArrayList<>();
  55. // Drop data for event
  56. private final List<GeneralDropItem> _dropList = new ArrayList<>();
  57. private class NpcSpawn
  58. {
  59. protected final Location loc;
  60. protected final int npcId;
  61. protected NpcSpawn(int pNpcId, Location spawnLoc)
  62. {
  63. loc = spawnLoc;
  64. npcId = pNpcId;
  65. }
  66. }
  67. public LongTimeEvent(String name, String descr)
  68. {
  69. super(-1, name, descr);
  70. loadConfig();
  71. if (_eventPeriod != null)
  72. {
  73. if (_eventPeriod.isWithinRange(new Date()))
  74. {
  75. startEvent();
  76. _log.info("Event " + _eventName + " active till " + _eventPeriod.getEndDate());
  77. }
  78. else if (_eventPeriod.getStartDate().after(new Date()))
  79. {
  80. long delay = _eventPeriod.getStartDate().getTime() - System.currentTimeMillis();
  81. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleStart(), delay);
  82. _log.info("Event " + _eventName + " will be started at " + _eventPeriod.getEndDate());
  83. }
  84. else
  85. {
  86. _log.info("Event " + _eventName + " has passed... Ignored ");
  87. }
  88. }
  89. }
  90. /**
  91. * Load event configuration file
  92. */
  93. private void loadConfig()
  94. {
  95. File configFile = new File("data/scripts/events/" + getScriptName() + "/config.xml");
  96. try
  97. {
  98. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  99. DocumentBuilder db = dbf.newDocumentBuilder();
  100. Document doc = db.parse(configFile);
  101. if (!doc.getDocumentElement().getNodeName().equalsIgnoreCase("event"))
  102. {
  103. throw new NullPointerException("WARNING!!! " + getScriptName() + " event: bad config file!");
  104. }
  105. _eventName = doc.getDocumentElement().getAttributes().getNamedItem("name").getNodeValue();
  106. String period = doc.getDocumentElement().getAttributes().getNamedItem("active").getNodeValue();
  107. _eventPeriod = DateRange.parse(period, new SimpleDateFormat("dd MM yyyy", Locale.US));
  108. if (doc.getDocumentElement().getAttributes().getNamedItem("dropPeriod") != null)
  109. {
  110. String dropPeriod = doc.getDocumentElement().getAttributes().getNamedItem("dropPeriod").getNodeValue();
  111. _dropPeriod = DateRange.parse(dropPeriod, new SimpleDateFormat("dd MM yyyy", Locale.US));
  112. // Check if drop period is within range of event period
  113. if (!_eventPeriod.isWithinRange(_dropPeriod.getStartDate()) || !_eventPeriod.isWithinRange(_dropPeriod.getEndDate()))
  114. {
  115. _dropPeriod = _eventPeriod;
  116. }
  117. }
  118. else
  119. {
  120. _dropPeriod = _eventPeriod; // Drop period, if not specified, assumes all event period.
  121. }
  122. if (_eventPeriod == null)
  123. {
  124. throw new NullPointerException("WARNING!!! " + getScriptName() + " event: illegal event period");
  125. }
  126. Date today = new Date();
  127. if (_eventPeriod.getStartDate().after(today) || _eventPeriod.isWithinRange(today))
  128. {
  129. Node first = doc.getDocumentElement().getFirstChild();
  130. for (Node n = first; n != null; n = n.getNextSibling())
  131. {
  132. // Loading droplist
  133. if (n.getNodeName().equalsIgnoreCase("droplist"))
  134. {
  135. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  136. {
  137. if (d.getNodeName().equalsIgnoreCase("add"))
  138. {
  139. try
  140. {
  141. int itemId = Integer.parseInt(d.getAttributes().getNamedItem("item").getNodeValue());
  142. int minCount = Integer.parseInt(d.getAttributes().getNamedItem("min").getNodeValue());
  143. int maxCount = Integer.parseInt(d.getAttributes().getNamedItem("max").getNodeValue());
  144. String chance = d.getAttributes().getNamedItem("chance").getNodeValue();
  145. int finalChance = 0;
  146. if (!chance.isEmpty() && chance.endsWith("%"))
  147. {
  148. finalChance = Integer.parseInt(chance.substring(0, chance.length() - 1)) * 10000;
  149. }
  150. if (ItemTable.getInstance().getTemplate(itemId) == null)
  151. {
  152. _log.warning(getScriptName() + " event: " + itemId + " is wrong item id, item was not added in droplist");
  153. continue;
  154. }
  155. if (minCount > maxCount)
  156. {
  157. _log.warning(getScriptName() + " event: item " + itemId + " - min greater than max, item was not added in droplist");
  158. continue;
  159. }
  160. if ((finalChance < 10000) || (finalChance > 1000000))
  161. {
  162. _log.warning(getScriptName() + " event: item " + itemId + " - incorrect drop chance, item was not added in droplist");
  163. continue;
  164. }
  165. _dropList.add(new GeneralDropItem(itemId, minCount, maxCount, finalChance));
  166. }
  167. catch (NumberFormatException nfe)
  168. {
  169. _log.warning("Wrong number format in config.xml droplist block for " + getScriptName() + " event");
  170. }
  171. }
  172. }
  173. }
  174. else if (n.getNodeName().equalsIgnoreCase("spawnlist"))
  175. {
  176. // Loading spawnlist
  177. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  178. {
  179. if (d.getNodeName().equalsIgnoreCase("add"))
  180. {
  181. try
  182. {
  183. int npcId = Integer.parseInt(d.getAttributes().getNamedItem("npc").getNodeValue());
  184. int xPos = Integer.parseInt(d.getAttributes().getNamedItem("x").getNodeValue());
  185. int yPos = Integer.parseInt(d.getAttributes().getNamedItem("y").getNodeValue());
  186. int zPos = Integer.parseInt(d.getAttributes().getNamedItem("z").getNodeValue());
  187. int heading = d.getAttributes().getNamedItem("heading").getNodeValue() != null ? Integer.parseInt(d.getAttributes().getNamedItem("heading").getNodeValue()) : 0;
  188. if (NpcData.getInstance().getTemplate(npcId) == null)
  189. {
  190. _log.warning(getScriptName() + " event: " + npcId + " is wrong NPC id, NPC was not added in spawnlist");
  191. continue;
  192. }
  193. _spawnList.add(new NpcSpawn(npcId, new Location(xPos, yPos, zPos, heading)));
  194. }
  195. catch (NumberFormatException nfe)
  196. {
  197. _log.warning("Wrong number format in config.xml spawnlist block for " + getScriptName() + " event");
  198. }
  199. }
  200. }
  201. }
  202. else if (n.getNodeName().equalsIgnoreCase("messages"))
  203. {
  204. // Loading Messages
  205. for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
  206. {
  207. if (d.getNodeName().equalsIgnoreCase("add"))
  208. {
  209. String msgType = d.getAttributes().getNamedItem("type").getNodeValue();
  210. String msgText = d.getAttributes().getNamedItem("text").getNodeValue();
  211. if ((msgType != null) && (msgText != null))
  212. {
  213. if (msgType.equalsIgnoreCase("onEnd"))
  214. {
  215. _endMsg = msgText;
  216. }
  217. else if (msgType.equalsIgnoreCase("onEnter"))
  218. {
  219. _onEnterMsg = msgText;
  220. }
  221. }
  222. }
  223. }
  224. }
  225. }
  226. }
  227. }
  228. catch (Exception e)
  229. {
  230. _log.log(Level.WARNING, getScriptName() + " event: error reading " + configFile.getAbsolutePath() + " ! " + e.getMessage(), e);
  231. }
  232. }
  233. /**
  234. * Maintenance event start - adds global drop, spawns event NPC's, shows start announcement.
  235. */
  236. protected void startEvent()
  237. {
  238. // Add drop
  239. if (_dropList != null)
  240. {
  241. for (GeneralDropItem drop : _dropList)
  242. {
  243. EventDroplist.getInstance().addGlobalDrop(drop.getItemId(), drop.getMin(), drop.getMax(), (int) drop.getChance(), _dropPeriod);
  244. }
  245. }
  246. // Add spawns
  247. Long millisToEventEnd = _eventPeriod.getEndDate().getTime() - System.currentTimeMillis();
  248. if (_spawnList != null)
  249. {
  250. for (NpcSpawn spawn : _spawnList)
  251. {
  252. addSpawn(spawn.npcId, spawn.loc.getX(), spawn.loc.getY(), spawn.loc.getZ(), spawn.loc.getHeading(), false, millisToEventEnd, false);
  253. }
  254. }
  255. // Send message on begin
  256. Announcements.getInstance().announceToAll(_onEnterMsg);
  257. // Add announce for entering players
  258. Announcements.getInstance().addEventAnnouncement(_eventPeriod, _onEnterMsg);
  259. // Schedule event end (now only for message sending)
  260. ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEnd(), millisToEventEnd);
  261. }
  262. /**
  263. * @return event period
  264. */
  265. public DateRange getEventPeriod()
  266. {
  267. return _eventPeriod;
  268. }
  269. /**
  270. * @return {@code true} if now is event period
  271. */
  272. public boolean isEventPeriod()
  273. {
  274. return _eventPeriod.isWithinRange(new Date());
  275. }
  276. /**
  277. * @return {@code true} if now is drop period
  278. */
  279. public boolean isDropPeriod()
  280. {
  281. return _dropPeriod.isWithinRange(new Date());
  282. }
  283. protected class ScheduleStart implements Runnable
  284. {
  285. @Override
  286. public void run()
  287. {
  288. startEvent();
  289. }
  290. }
  291. protected class ScheduleEnd implements Runnable
  292. {
  293. @Override
  294. public void run()
  295. {
  296. // Send message on end
  297. Announcements.getInstance().announceToAll(_endMsg);
  298. }
  299. }
  300. }