PetitionManager.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.l2jserver.gameserver.instancemanager;
  16. import java.text.SimpleDateFormat;
  17. import java.util.Date;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.logging.Logger;
  21. import javolution.util.FastList;
  22. import javolution.util.FastMap;
  23. import com.l2jserver.Config;
  24. import com.l2jserver.gameserver.GmListTable;
  25. import com.l2jserver.gameserver.idfactory.IdFactory;
  26. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  27. import com.l2jserver.gameserver.network.SystemMessageId;
  28. import com.l2jserver.gameserver.network.clientpackets.Say2;
  29. import com.l2jserver.gameserver.network.serverpackets.CreatureSay;
  30. import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
  31. import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
  32. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  33. import com.l2jserver.util.StringUtil;
  34. /**
  35. * Petition Manager
  36. *
  37. * @author Tempy
  38. *
  39. */
  40. public final class PetitionManager
  41. {
  42. protected static final Logger _log = Logger.getLogger(PetitionManager.class.getName());
  43. private Map<Integer, Petition> _pendingPetitions;
  44. private Map<Integer, Petition> _completedPetitions;
  45. private static enum PetitionState
  46. {
  47. Pending,
  48. Responder_Cancel,
  49. Responder_Missing,
  50. Responder_Reject,
  51. Responder_Complete,
  52. Petitioner_Cancel,
  53. Petitioner_Missing,
  54. In_Process,
  55. Completed
  56. }
  57. private static enum PetitionType
  58. {
  59. Immobility,
  60. Recovery_Related,
  61. Bug_Report,
  62. Quest_Related,
  63. Bad_User,
  64. Suggestions,
  65. Game_Tip,
  66. Operation_Related,
  67. Other
  68. }
  69. public static PetitionManager getInstance()
  70. {
  71. return SingletonHolder._instance;
  72. }
  73. private class Petition
  74. {
  75. private long _submitTime = System.currentTimeMillis();
  76. private int _id;
  77. private PetitionType _type;
  78. private PetitionState _state = PetitionState.Pending;
  79. private String _content;
  80. private List<CreatureSay> _messageLog = new FastList<CreatureSay>();
  81. private L2PcInstance _petitioner;
  82. private L2PcInstance _responder;
  83. public Petition(L2PcInstance petitioner, String petitionText, int petitionType)
  84. {
  85. petitionType--;
  86. _id = IdFactory.getInstance().getNextId();
  87. if (petitionType >= PetitionType.values().length)
  88. {
  89. _log.warning("PetitionManager:Petition : invalid petition type (received type was +1) : " + petitionType);
  90. }
  91. _type = PetitionType.values()[petitionType];
  92. _content = petitionText;
  93. _petitioner = petitioner;
  94. }
  95. protected boolean addLogMessage(CreatureSay cs)
  96. {
  97. return _messageLog.add(cs);
  98. }
  99. protected List<CreatureSay> getLogMessages()
  100. {
  101. return _messageLog;
  102. }
  103. public boolean endPetitionConsultation(PetitionState endState)
  104. {
  105. setState(endState);
  106. if (getResponder() != null && getResponder().isOnline())
  107. {
  108. if (endState == PetitionState.Responder_Reject)
  109. {
  110. getPetitioner().sendMessage("Your petition was rejected. Please try again later.");
  111. }
  112. else
  113. {
  114. // Ending petition consultation with <Player>.
  115. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.PETITION_ENDED_WITH_C1);
  116. sm.addString(getPetitioner().getName());
  117. getResponder().sendPacket(sm);
  118. if (endState == PetitionState.Petitioner_Cancel)
  119. {
  120. // Receipt No. <ID> petition cancelled.
  121. sm = SystemMessage.getSystemMessage(SystemMessageId.RECENT_NO_S1_CANCELED);
  122. sm.addNumber(getId());
  123. getResponder().sendPacket(sm);
  124. }
  125. }
  126. }
  127. // End petition consultation and inform them, if they are still online.
  128. if (getPetitioner() != null && getPetitioner().isOnline())
  129. getPetitioner().sendPacket(SystemMessage.getSystemMessage(SystemMessageId.THIS_END_THE_PETITION_PLEASE_PROVIDE_FEEDBACK));
  130. getCompletedPetitions().put(getId(), this);
  131. return (getPendingPetitions().remove(getId()) != null);
  132. }
  133. public String getContent()
  134. {
  135. return _content;
  136. }
  137. public int getId()
  138. {
  139. return _id;
  140. }
  141. public L2PcInstance getPetitioner()
  142. {
  143. return _petitioner;
  144. }
  145. public L2PcInstance getResponder()
  146. {
  147. return _responder;
  148. }
  149. public long getSubmitTime()
  150. {
  151. return _submitTime;
  152. }
  153. public PetitionState getState()
  154. {
  155. return _state;
  156. }
  157. public String getTypeAsString()
  158. {
  159. return _type.toString().replace("_", " ");
  160. }
  161. public void sendPetitionerPacket(L2GameServerPacket responsePacket)
  162. {
  163. if (getPetitioner() == null || !getPetitioner().isOnline())
  164. {
  165. // Allows petitioners to see the results of their petition when
  166. // they log back into the game.
  167. //endPetitionConsultation(PetitionState.Petitioner_Missing);
  168. return;
  169. }
  170. getPetitioner().sendPacket(responsePacket);
  171. }
  172. public void sendResponderPacket(L2GameServerPacket responsePacket)
  173. {
  174. if (getResponder() == null || !getResponder().isOnline())
  175. {
  176. endPetitionConsultation(PetitionState.Responder_Missing);
  177. return;
  178. }
  179. getResponder().sendPacket(responsePacket);
  180. }
  181. public void setState(PetitionState state)
  182. {
  183. _state = state;
  184. }
  185. public void setResponder(L2PcInstance respondingAdmin)
  186. {
  187. if (getResponder() != null)
  188. return;
  189. _responder = respondingAdmin;
  190. }
  191. }
  192. private PetitionManager()
  193. {
  194. _log.info("Initializing PetitionManager");
  195. _pendingPetitions = new FastMap<Integer, Petition>();
  196. _completedPetitions = new FastMap<Integer, Petition>();
  197. }
  198. public void clearCompletedPetitions()
  199. {
  200. int numPetitions = getPendingPetitionCount();
  201. getCompletedPetitions().clear();
  202. _log.info("PetitionManager: Completed petition data cleared. " + numPetitions + " petition(s) removed.");
  203. }
  204. public void clearPendingPetitions()
  205. {
  206. int numPetitions = getPendingPetitionCount();
  207. getPendingPetitions().clear();
  208. _log.info("PetitionManager: Pending petition queue cleared. " + numPetitions + " petition(s) removed.");
  209. }
  210. public boolean acceptPetition(L2PcInstance respondingAdmin, int petitionId)
  211. {
  212. if (!isValidPetition(petitionId))
  213. return false;
  214. Petition currPetition = getPendingPetitions().get(petitionId);
  215. if (currPetition.getResponder() != null)
  216. return false;
  217. currPetition.setResponder(respondingAdmin);
  218. currPetition.setState(PetitionState.In_Process);
  219. // Petition application accepted. (Send to Petitioner)
  220. currPetition.sendPetitionerPacket(SystemMessage.getSystemMessage(SystemMessageId.PETITION_APP_ACCEPTED));
  221. // Petition application accepted. Reciept No. is <ID>
  222. SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.PETITION_ACCEPTED_RECENT_NO_S1);
  223. sm.addNumber(currPetition.getId());
  224. currPetition.sendResponderPacket(sm);
  225. // Petition consultation with <Player> underway.
  226. sm = SystemMessage.getSystemMessage(SystemMessageId.STARTING_PETITION_WITH_C1);
  227. sm.addString(currPetition.getPetitioner().getName());
  228. currPetition.sendResponderPacket(sm);
  229. return true;
  230. }
  231. public boolean cancelActivePetition(L2PcInstance player)
  232. {
  233. for (Petition currPetition : getPendingPetitions().values())
  234. {
  235. if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
  236. return (currPetition.endPetitionConsultation(PetitionState.Petitioner_Cancel));
  237. if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
  238. return (currPetition.endPetitionConsultation(PetitionState.Responder_Cancel));
  239. }
  240. return false;
  241. }
  242. public void checkPetitionMessages(L2PcInstance petitioner)
  243. {
  244. if (petitioner != null)
  245. for (Petition currPetition : getPendingPetitions().values())
  246. {
  247. if (currPetition == null)
  248. continue;
  249. if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == petitioner.getObjectId())
  250. {
  251. for (CreatureSay logMessage : currPetition.getLogMessages())
  252. petitioner.sendPacket(logMessage);
  253. return;
  254. }
  255. }
  256. }
  257. public boolean endActivePetition(L2PcInstance player)
  258. {
  259. if (!player.isGM())
  260. return false;
  261. for (Petition currPetition : getPendingPetitions().values())
  262. {
  263. if (currPetition == null)
  264. continue;
  265. if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
  266. return (currPetition.endPetitionConsultation(PetitionState.Completed));
  267. }
  268. return false;
  269. }
  270. protected Map<Integer, Petition> getCompletedPetitions()
  271. {
  272. return _completedPetitions;
  273. }
  274. protected Map<Integer, Petition> getPendingPetitions()
  275. {
  276. return _pendingPetitions;
  277. }
  278. public int getPendingPetitionCount()
  279. {
  280. return getPendingPetitions().size();
  281. }
  282. public int getPlayerTotalPetitionCount(L2PcInstance player)
  283. {
  284. if (player == null)
  285. return 0;
  286. int petitionCount = 0;
  287. for (Petition currPetition : getPendingPetitions().values())
  288. {
  289. if (currPetition == null)
  290. continue;
  291. if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
  292. petitionCount++;
  293. }
  294. for (Petition currPetition : getCompletedPetitions().values())
  295. {
  296. if (currPetition == null)
  297. continue;
  298. if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
  299. petitionCount++;
  300. }
  301. return petitionCount;
  302. }
  303. public boolean isPetitionInProcess()
  304. {
  305. for (Petition currPetition : getPendingPetitions().values())
  306. {
  307. if (currPetition == null)
  308. continue;
  309. if (currPetition.getState() == PetitionState.In_Process)
  310. return true;
  311. }
  312. return false;
  313. }
  314. public boolean isPetitionInProcess(int petitionId)
  315. {
  316. if (!isValidPetition(petitionId))
  317. return false;
  318. Petition currPetition = getPendingPetitions().get(petitionId);
  319. return (currPetition.getState() == PetitionState.In_Process);
  320. }
  321. public boolean isPlayerInConsultation(L2PcInstance player)
  322. {
  323. if (player != null)
  324. for (Petition currPetition : getPendingPetitions().values())
  325. {
  326. if (currPetition == null)
  327. continue;
  328. if (currPetition.getState() != PetitionState.In_Process)
  329. continue;
  330. if ((currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
  331. || (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId()))
  332. return true;
  333. }
  334. return false;
  335. }
  336. public boolean isPetitioningAllowed()
  337. {
  338. return Config.PETITIONING_ALLOWED;
  339. }
  340. public boolean isPlayerPetitionPending(L2PcInstance petitioner)
  341. {
  342. if (petitioner != null)
  343. for (Petition currPetition : getPendingPetitions().values())
  344. {
  345. if (currPetition == null)
  346. continue;
  347. if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == petitioner.getObjectId())
  348. return true;
  349. }
  350. return false;
  351. }
  352. private boolean isValidPetition(int petitionId)
  353. {
  354. return getPendingPetitions().containsKey(petitionId);
  355. }
  356. public boolean rejectPetition(L2PcInstance respondingAdmin, int petitionId)
  357. {
  358. if (!isValidPetition(petitionId))
  359. return false;
  360. Petition currPetition = getPendingPetitions().get(petitionId);
  361. if (currPetition.getResponder() != null)
  362. return false;
  363. currPetition.setResponder(respondingAdmin);
  364. return (currPetition.endPetitionConsultation(PetitionState.Responder_Reject));
  365. }
  366. public boolean sendActivePetitionMessage(L2PcInstance player, String messageText)
  367. {
  368. //if (!isPlayerInConsultation(player))
  369. //return false;
  370. CreatureSay cs;
  371. for (Petition currPetition : getPendingPetitions().values())
  372. {
  373. if (currPetition == null)
  374. continue;
  375. if (currPetition.getPetitioner() != null && currPetition.getPetitioner().getObjectId() == player.getObjectId())
  376. {
  377. cs = new CreatureSay(player.getObjectId(), Say2.PETITION_PLAYER, player.getName(), messageText);
  378. currPetition.addLogMessage(cs);
  379. currPetition.sendResponderPacket(cs);
  380. currPetition.sendPetitionerPacket(cs);
  381. return true;
  382. }
  383. if (currPetition.getResponder() != null && currPetition.getResponder().getObjectId() == player.getObjectId())
  384. {
  385. cs = new CreatureSay(player.getObjectId(), Say2.PETITION_GM, player.getName(), messageText);
  386. currPetition.addLogMessage(cs);
  387. currPetition.sendResponderPacket(cs);
  388. currPetition.sendPetitionerPacket(cs);
  389. return true;
  390. }
  391. }
  392. return false;
  393. }
  394. public void sendPendingPetitionList(L2PcInstance activeChar)
  395. {
  396. final StringBuilder htmlContent = StringUtil.startAppend(600 + getPendingPetitionCount() * 300, "<html><body><center><table width=270><tr>"
  397. + "<td width=45><button value=\"Main\" action=\"bypass -h admin_admin\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>"
  398. + "<td width=180><center>Petition Menu</center></td>"
  399. + "<td width=45><button value=\"Back\" action=\"bypass -h admin_admin7\" width=45 height=21 back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br>"
  400. + "<table width=\"270\">"
  401. + "<tr><td><table width=\"270\"><tr><td><button value=\"Reset\" action=\"bypass -h admin_reset_petitions\" width=\"80\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>"
  402. + "<td align=right><button value=\"Refresh\" action=\"bypass -h admin_view_petitions\" width=\"80\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table><br></td></tr>");
  403. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
  404. if (getPendingPetitionCount() == 0)
  405. htmlContent.append("<tr><td>There are no currently pending petitions.</td></tr>");
  406. else
  407. htmlContent.append("<tr><td><font color=\"LEVEL\">Current Petitions:</font><br></td></tr>");
  408. boolean color = true;
  409. int petcount = 0;
  410. for (Petition currPetition : getPendingPetitions().values())
  411. {
  412. if (currPetition == null)
  413. continue;
  414. StringUtil.append(htmlContent,"<tr><td width=\"270\"><table width=\"270\" cellpadding=\"2\" bgcolor=",(color ? "131210" : "444444" ),"><tr><td width=\"130\">",dateFormat.format(new Date(currPetition.getSubmitTime())));
  415. StringUtil.append(htmlContent,"</td><td width=\"140\" align=right><font color=\"",(currPetition.getPetitioner().isOnline() ? "00FF00" : "999999"),"\">",currPetition.getPetitioner().getName(),"</font></td></tr>");
  416. StringUtil.append(htmlContent,"<tr><td width=\"130\">");
  417. if (currPetition.getState() != PetitionState.In_Process)
  418. {
  419. StringUtil.append(htmlContent, "<table width=\"130\" cellpadding=\"2\"><tr>"
  420. + "<td><button value=\"View\" action=\"bypass -h admin_view_petition ", String.valueOf(currPetition.getId()), "\" width=\"50\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td>"
  421. + "<td><button value=\"Reject\" action=\"bypass -h admin_reject_petition ", String.valueOf(currPetition.getId()), "\" width=\"50\" height=\"21\" back=\"L2UI_ct1.button_df\" fore=\"L2UI_ct1.button_df\"></td></tr></table>");
  422. }
  423. else
  424. htmlContent.append("<font color=\""+(currPetition.getResponder().isOnline() ? "00FF00" : "999999")+"\">"+currPetition.getResponder().getName()+"</font>");
  425. StringUtil.append(htmlContent,"</td>",currPetition.getTypeAsString(),"<td width=\"140\" align=right>",currPetition.getTypeAsString(),"</td></tr></table></td></tr>");
  426. color = !color;
  427. petcount++;
  428. if(petcount > 10)
  429. {
  430. htmlContent.append("<tr><td><font color=\"LEVEL\">There is more pending petition...</font><br></td></tr>");
  431. break;
  432. }
  433. }
  434. htmlContent.append("</table></center></body></html>");
  435. NpcHtmlMessage htmlMsg = new NpcHtmlMessage(0);
  436. htmlMsg.setHtml(htmlContent.toString());
  437. activeChar.sendPacket(htmlMsg);
  438. }
  439. public int submitPetition(L2PcInstance petitioner, String petitionText, int petitionType)
  440. {
  441. // Create a new petition instance and add it to the list of pending petitions.
  442. Petition newPetition = new Petition(petitioner, petitionText, petitionType);
  443. int newPetitionId = newPetition.getId();
  444. getPendingPetitions().put(newPetitionId, newPetition);
  445. // Notify all GMs that a new petition has been submitted.
  446. String msgContent = petitioner.getName() + " has submitted a new petition."; //(ID: " + newPetitionId + ").";
  447. GmListTable.broadcastToGMs(new CreatureSay(petitioner.getObjectId(), Say2.HERO_VOICE, "Petition System", msgContent));
  448. return newPetitionId;
  449. }
  450. public void viewPetition(L2PcInstance activeChar, int petitionId)
  451. {
  452. if (!activeChar.isGM())
  453. return;
  454. if (!isValidPetition(petitionId))
  455. return;
  456. Petition currPetition = getPendingPetitions().get(petitionId);
  457. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
  458. NpcHtmlMessage html = new NpcHtmlMessage(0);
  459. html.setFile(activeChar.getHtmlPrefix(), "data/html/admin/petition.htm");
  460. html.replace("%petition%", String.valueOf(currPetition.getId()));
  461. html.replace("%time%", dateFormat.format(new Date(currPetition.getSubmitTime())));
  462. html.replace("%type%", currPetition.getTypeAsString());
  463. html.replace("%petitioner%", currPetition.getPetitioner().getName());
  464. html.replace("%online%", (currPetition.getPetitioner().isOnline() ? "00FF00" : "999999"));
  465. html.replace("%text%", currPetition.getContent());
  466. activeChar.sendPacket(html);
  467. }
  468. @SuppressWarnings("synthetic-access")
  469. private static class SingletonHolder
  470. {
  471. protected static final PetitionManager _instance = new PetitionManager();
  472. }
  473. }