QuestManager.java 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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.instancemanager;
  20. import java.io.File;
  21. import java.io.IOException;
  22. import java.util.Map;
  23. import java.util.concurrent.ConcurrentHashMap;
  24. import java.util.logging.Level;
  25. import java.util.logging.Logger;
  26. import com.l2jserver.Config;
  27. import com.l2jserver.gameserver.model.quest.Quest;
  28. import com.l2jserver.gameserver.scripting.L2ScriptEngineManager;
  29. import com.l2jserver.gameserver.scripting.ScriptManager;
  30. import com.l2jserver.util.Util;
  31. /**
  32. * Quests and scripts manager.
  33. * @author Zoey76
  34. */
  35. public final class QuestManager extends ScriptManager<Quest>
  36. {
  37. protected static final Logger _log = Logger.getLogger(QuestManager.class.getName());
  38. /** Map containing all the quests. */
  39. private final Map<String, Quest> _quests = new ConcurrentHashMap<>();
  40. /** Map containing all the scripts. */
  41. private final Map<String, Quest> _scripts = new ConcurrentHashMap<>();
  42. protected QuestManager()
  43. {
  44. // Prevent initialization.
  45. }
  46. public boolean reload(String questFolder)
  47. {
  48. final Quest q = getQuest(questFolder);
  49. if (q == null)
  50. {
  51. return false;
  52. }
  53. return q.reload();
  54. }
  55. /**
  56. * Reloads a the quest by ID.
  57. * @param questId the ID of the quest to be reloaded
  58. * @return {@code true} if reload was successful, {@code false} otherwise
  59. */
  60. public boolean reload(int questId)
  61. {
  62. final Quest q = getQuest(questId);
  63. if (q == null)
  64. {
  65. return false;
  66. }
  67. return q.reload();
  68. }
  69. /**
  70. * Reload all quests and scripts.<br>
  71. * Unload all quests and scripts and load scripts.cfg.
  72. */
  73. public void reloadAllScripts()
  74. {
  75. _log.info(getClass().getSimpleName() + ": Reloading all server scripts.");
  76. // Unload quests.
  77. for (Quest quest : _quests.values())
  78. {
  79. if (quest != null)
  80. {
  81. quest.unload(false);
  82. }
  83. }
  84. _quests.clear();
  85. // Unload scripts.
  86. for (Quest script : _scripts.values())
  87. {
  88. if (script != null)
  89. {
  90. script.unload(false);
  91. }
  92. }
  93. _scripts.clear();
  94. try
  95. {
  96. L2ScriptEngineManager.getInstance().executeScriptList(new File(Config.DATAPACK_ROOT, "data/scripts.cfg"));
  97. }
  98. catch (IOException e)
  99. {
  100. _log.log(Level.SEVERE, getClass().getSimpleName() + ": Failed loading scripts.cfg, no script going to be loaded!", e);
  101. }
  102. QuestManager.getInstance().report();
  103. }
  104. /**
  105. * Logs how many quests and scripts are loaded.
  106. */
  107. public void report()
  108. {
  109. _log.info(getClass().getSimpleName() + ": Loaded: " + _quests.size() + " quests.");
  110. _log.info(getClass().getSimpleName() + ": Loaded: " + _scripts.size() + " scripts.");
  111. }
  112. /**
  113. * Calls {@link Quest#saveGlobalData()} in all quests and scripts.
  114. */
  115. public void save()
  116. {
  117. // Save quests.
  118. for (Quest quest : _quests.values())
  119. {
  120. quest.saveGlobalData();
  121. }
  122. // Save scripts.
  123. for (Quest script : _scripts.values())
  124. {
  125. script.saveGlobalData();
  126. }
  127. }
  128. /**
  129. * Gets a quest by name.<br>
  130. * <i>For backwards compatibility, verifies scripts with the given name if the quest is not found.</i>
  131. * @param name the quest name
  132. * @return the quest
  133. */
  134. public Quest getQuest(String name)
  135. {
  136. if (_quests.containsKey(name))
  137. {
  138. return _quests.get(name);
  139. }
  140. return _scripts.get(name);
  141. }
  142. /**
  143. * Gets a quest by ID.
  144. * @param questId the ID of the quest to get
  145. * @return if found, the quest, {@code null} otherwise
  146. */
  147. public Quest getQuest(int questId)
  148. {
  149. for (Quest q : _quests.values())
  150. {
  151. if (q.getId() == questId)
  152. {
  153. return q;
  154. }
  155. }
  156. return null;
  157. }
  158. /**
  159. * Adds a new quest.
  160. * @param quest the quest to be added
  161. */
  162. public void addQuest(Quest quest)
  163. {
  164. if (quest == null)
  165. {
  166. throw new IllegalArgumentException("Quest argument cannot be null");
  167. }
  168. // FIXME: unloading the old quest at this point is a tad too late.
  169. // the new quest has already initialized itself and read the data, starting
  170. // an unpredictable number of tasks with that data. The old quest will now
  171. // save data which will never be read.
  172. // However, requesting the newQuest to re-read the data is not necessarily a
  173. // good option, since the newQuest may have already started timers, spawned NPCs
  174. // or taken any other action which it might re-take by re-reading the data.
  175. // the current solution properly closes the running tasks of the old quest but
  176. // ignores the data; perhaps the least of all evils...
  177. final Quest old = _quests.put(quest.getName(), quest);
  178. if (old != null)
  179. {
  180. old.unload();
  181. _log.info(getClass().getSimpleName() + ": Replaced quest " + old.getName() + " (" + old.getId() + ") with a new version!");
  182. }
  183. if (Config.ALT_DEV_SHOW_QUESTS_LOAD_IN_LOGS)
  184. {
  185. final String questName = quest.getName().contains("_") ? quest.getName().substring(quest.getName().indexOf('_') + 1) : quest.getName();
  186. _log.info("Loaded quest " + Util.splitWords(questName) + ".");
  187. }
  188. }
  189. /**
  190. * Removes a script.
  191. * @param script the script to remove
  192. * @return {@code true} if the script was removed, {@code false} otherwise
  193. */
  194. public boolean removeScript(Quest script)
  195. {
  196. if (_quests.containsKey(script.getName()))
  197. {
  198. _quests.remove(script.getName());
  199. return true;
  200. }
  201. else if (_scripts.containsKey(script.getName()))
  202. {
  203. _scripts.remove(script.getName());
  204. return true;
  205. }
  206. return false;
  207. }
  208. public Map<String, Quest> getQuests()
  209. {
  210. return _quests;
  211. }
  212. @Override
  213. public boolean unload(Quest ms)
  214. {
  215. ms.saveGlobalData();
  216. return removeScript(ms);
  217. }
  218. @Override
  219. public String getScriptManagerName()
  220. {
  221. return getClass().getSimpleName();
  222. }
  223. /**
  224. * Gets all the registered scripts.
  225. * @return all the scripts
  226. */
  227. @Override
  228. public Map<String, Quest> getScripts()
  229. {
  230. return _scripts;
  231. }
  232. /**
  233. * Adds a script.
  234. * @param script the script to be added
  235. */
  236. public void addScript(Quest script)
  237. {
  238. final Quest old = _scripts.put(script.getClass().getSimpleName(), script);
  239. if (old != null)
  240. {
  241. old.unload();
  242. _log.info(getClass().getSimpleName() + ": Replaced script " + old.getName() + " with a new version!");
  243. }
  244. if (Config.ALT_DEV_SHOW_SCRIPTS_LOAD_IN_LOGS)
  245. {
  246. _log.info("Loaded script " + Util.splitWords(script.getClass().getSimpleName()) + ".");
  247. }
  248. }
  249. /**
  250. * Gets the single instance of {@code QuestManager}.
  251. * @return single instance of {@code QuestManager}
  252. */
  253. public static QuestManager getInstance()
  254. {
  255. return SingletonHolder._instance;
  256. }
  257. private static class SingletonHolder
  258. {
  259. protected static final QuestManager _instance = new QuestManager();
  260. }
  261. }