LongTimeEvent.java 11 KB

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