PageRenderTime 340ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java

https://github.com/dotblank/Factions
Java | 644 lines | 523 code | 85 blank | 36 comment | 121 complexity | f2e86a9679fc8f8c8bf898d55878f4a0 MD5 | raw file
  1. package com.massivecraft.factions.listeners;
  2. import java.util.logging.Logger;
  3. import java.util.Iterator;
  4. import java.util.UnknownFormatConversionException;
  5. import org.bukkit.ChatColor;
  6. import org.bukkit.Location;
  7. import org.bukkit.Material;
  8. import org.bukkit.block.Block;
  9. import org.bukkit.entity.Player;
  10. import org.bukkit.event.block.Action;
  11. import org.bukkit.event.player.PlayerBucketEmptyEvent;
  12. import org.bukkit.event.player.PlayerBucketFillEvent;
  13. import org.bukkit.event.player.PlayerChatEvent;
  14. import org.bukkit.event.player.PlayerCommandPreprocessEvent;
  15. import org.bukkit.event.player.PlayerInteractEvent;
  16. import org.bukkit.event.player.PlayerJoinEvent;
  17. import org.bukkit.event.player.PlayerKickEvent;
  18. import org.bukkit.event.player.PlayerListener;
  19. import org.bukkit.event.player.PlayerMoveEvent;
  20. import org.bukkit.event.player.PlayerQuitEvent;
  21. import org.bukkit.event.player.PlayerRespawnEvent;
  22. import com.massivecraft.factions.Board;
  23. import com.massivecraft.factions.Conf;
  24. import com.massivecraft.factions.FLocation;
  25. import com.massivecraft.factions.FPlayer;
  26. import com.massivecraft.factions.FPlayers;
  27. import com.massivecraft.factions.Faction;
  28. import com.massivecraft.factions.Factions;
  29. import com.massivecraft.factions.P;
  30. import com.massivecraft.factions.integration.SpoutFeatures;
  31. import com.massivecraft.factions.struct.Permission;
  32. import com.massivecraft.factions.struct.Role;
  33. import com.massivecraft.factions.struct.Relation;
  34. import com.massivecraft.factions.zcore.util.TextUtil;
  35. import java.util.logging.Level;
  36. public class FactionsPlayerListener extends PlayerListener
  37. {
  38. public P p;
  39. public FactionsPlayerListener(P p)
  40. {
  41. this.p = p;
  42. }
  43. @Override
  44. public void onPlayerChat(PlayerChatEvent event)
  45. {
  46. if (event.isCancelled()) return;
  47. Player talkingPlayer = event.getPlayer();
  48. String msg = event.getMessage();
  49. // ... it was not a command. This means that it is a chat message!
  50. FPlayer me = FPlayers.i.get(talkingPlayer);
  51. // Are we to insert the Faction tag into the format?
  52. // If we are not to insert it - we are done.
  53. if ( ! Conf.chatTagEnabled || Conf.chatTagHandledByAnotherPlugin)
  54. {
  55. return;
  56. }
  57. int InsertIndex = 0;
  58. String eventFormat = event.getFormat();
  59. if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString))
  60. {
  61. // we're using the "replace" method of inserting the faction tags
  62. // if they stuck "{FACTION_TITLE}" in there, go ahead and do it too
  63. if (eventFormat.contains("{FACTION_TITLE}"))
  64. {
  65. eventFormat = eventFormat.replace("{FACTION_TITLE}", me.getTitle());
  66. }
  67. InsertIndex = eventFormat.indexOf(Conf.chatTagReplaceString);
  68. eventFormat = eventFormat.replace(Conf.chatTagReplaceString, "");
  69. Conf.chatTagPadAfter = false;
  70. Conf.chatTagPadBefore = false;
  71. }
  72. else if (!Conf.chatTagInsertAfterString.isEmpty() && eventFormat.contains(Conf.chatTagInsertAfterString))
  73. {
  74. // we're using the "insert after string" method
  75. InsertIndex = eventFormat.indexOf(Conf.chatTagInsertAfterString) + Conf.chatTagInsertAfterString.length();
  76. }
  77. else if (!Conf.chatTagInsertBeforeString.isEmpty() && eventFormat.contains(Conf.chatTagInsertBeforeString))
  78. {
  79. // we're using the "insert before string" method
  80. InsertIndex = eventFormat.indexOf(Conf.chatTagInsertBeforeString);
  81. }
  82. else
  83. {
  84. // we'll fall back to using the index place method
  85. InsertIndex = Conf.chatTagInsertIndex;
  86. if (InsertIndex > eventFormat.length())
  87. return;
  88. }
  89. String formatStart = eventFormat.substring(0, InsertIndex) + ((Conf.chatTagPadBefore && !me.getChatTag().isEmpty()) ? " " : "");
  90. String formatEnd = ((Conf.chatTagPadAfter && !me.getChatTag().isEmpty()) ? " " : "") + eventFormat.substring(InsertIndex);
  91. String nonColoredMsgFormat = formatStart + me.getChatTag().trim() + formatEnd;
  92. // Relation Colored?
  93. if (Conf.chatTagRelationColored)
  94. {
  95. // We must choke the standard message and send out individual messages to all players
  96. // Why? Because the relations will differ.
  97. event.setCancelled(true);
  98. for (Player listeningPlayer : event.getRecipients())
  99. {
  100. FPlayer you = FPlayers.i.get(listeningPlayer);
  101. String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd;
  102. try
  103. {
  104. listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg));
  105. }
  106. catch (UnknownFormatConversionException ex)
  107. {
  108. P.p.log(Level.SEVERE, "Critical error in chat message formatting! Complete format string: "+yourFormat);
  109. P.p.log(Level.SEVERE, "First half of event.getFormat() string: "+formatStart);
  110. P.p.log(Level.SEVERE, "Second half of event.getFormat() string: "+formatEnd);
  111. P.p.log(Level.SEVERE, "NOTE: To fix this quickly, running this command should work: f config chatTagInsertIndex 0");
  112. P.p.log(Level.SEVERE, "For a more proper fix, please read the chat configuration notes on the configuration page of the Factions user guide.");
  113. ex.printStackTrace();
  114. return;
  115. }
  116. }
  117. // Write to the log... We will write the non colored message.
  118. String nonColoredMsg = ChatColor.stripColor(String.format(nonColoredMsgFormat, talkingPlayer.getDisplayName(), msg));
  119. Logger.getLogger("Minecraft").info(nonColoredMsg);
  120. }
  121. else
  122. {
  123. // No relation color.
  124. event.setFormat(nonColoredMsgFormat);
  125. }
  126. }
  127. @Override
  128. public void onPlayerJoin(PlayerJoinEvent event)
  129. {
  130. // Make sure that all online players do have a fplayer.
  131. final FPlayer me = FPlayers.i.get(event.getPlayer());
  132. // Update the lastLoginTime for this fplayer
  133. me.setLastLoginTime(System.currentTimeMillis());
  134. // Run the member auto kick routine. Twice to get to the admins...
  135. FPlayers.i.autoLeaveOnInactivityRoutine();
  136. FPlayers.i.autoLeaveOnInactivityRoutine();
  137. }
  138. @Override
  139. public void onPlayerQuit(PlayerQuitEvent event)
  140. {
  141. // Make sure player's power is up to date when they log off.
  142. FPlayer me = FPlayers.i.get(event.getPlayer());
  143. me.getPower();
  144. Faction myFaction = me.getFaction();
  145. if (myFaction != null)
  146. {
  147. myFaction.memberLoggedOff();
  148. }
  149. SpoutFeatures.playerDisconnect(me);
  150. }
  151. @Override
  152. public void onPlayerMove(PlayerMoveEvent event)
  153. {
  154. Player player = event.getPlayer();
  155. FPlayer me = FPlayers.i.get(player);
  156. // Did we change coord?
  157. FLocation from = me.getLastStoodAt();
  158. FLocation to = new FLocation(player.getLocation());
  159. if (from.equals(to))
  160. {
  161. return;
  162. }
  163. // Yes we did change coord (:
  164. me.sendFactionHeaderMessage();
  165. me.setLastStoodAt(to);
  166. if (me.isMapAutoUpdating())
  167. {
  168. me.sendMessage(Board.getMap(me.getFaction(), to, player.getLocation().getYaw()));
  169. }
  170. else
  171. {
  172. // Did we change "host"(faction)?
  173. Faction factionFrom = Board.getFactionAt(from);
  174. Faction factionTo = Board.getFactionAt(to);
  175. Faction myFaction = me.getFaction();
  176. String ownersTo = myFaction.getOwnerListString(to);
  177. boolean spoutClient = SpoutFeatures.availableFor(player);
  178. if (factionFrom != factionTo)
  179. {
  180. me.sendFactionHereMessage();
  181. if
  182. (
  183. Conf.ownedAreasEnabled
  184. &&
  185. Conf.ownedMessageOnBorder
  186. &&
  187. (
  188. !spoutClient
  189. ||
  190. !Conf.spoutTerritoryOwnersShow
  191. )
  192. &&
  193. myFaction == factionTo
  194. &&
  195. !ownersTo.isEmpty()
  196. )
  197. {
  198. me.sendMessage(Conf.ownedLandMessage+ownersTo);
  199. }
  200. }
  201. else if (spoutClient && Conf.spoutTerritoryOwnersShow)
  202. {
  203. SpoutFeatures.updateOwnerList(me);
  204. }
  205. else if
  206. (
  207. Conf.ownedAreasEnabled
  208. &&
  209. Conf.ownedMessageInsideTerritory
  210. &&
  211. factionFrom == factionTo
  212. &&
  213. myFaction == factionTo
  214. )
  215. {
  216. String ownersFrom = myFaction.getOwnerListString(from);
  217. if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo))
  218. {
  219. if (!ownersTo.isEmpty())
  220. me.sendMessage(Conf.ownedLandMessage+ownersTo);
  221. else if (!Conf.publicLandMessage.isEmpty())
  222. me.sendMessage(Conf.publicLandMessage);
  223. }
  224. }
  225. }
  226. if (me.isAutoClaimEnabled())
  227. {
  228. Faction myFaction = me.getFaction();
  229. // TODO: Why is this ("cost") here and unused??? Should it be used somewhere Brettflan? :)
  230. // Olof just commented it out to avoid the error.
  231. // So sayeth Brettflan, answered in a comment since you asked in a comment:
  232. // NOTHING MORE TODO: it was used, but apparently not needed after some changes including this commit: https://github.com/MassiveCraft/Factions/commit/5eaf9c68358c6076bb856baf80fd6496e2ab02ce
  233. //
  234. //Faction otherFaction = Board.getFactionAt(to);
  235. //double cost = Econ.calculateClaimCost(myFaction.getLandRounded(), otherFaction.isNormal());
  236. if (me.getRole().value < Role.MODERATOR.value)
  237. {
  238. me.sendMessage("You must be "+Role.MODERATOR+" to claim land.");
  239. me.setIsAutoClaimEnabled(false);
  240. }
  241. else if (Conf.worldsNoClaiming.contains(to.getWorldName()))
  242. {
  243. me.sendMessage("Sorry, this world has land claiming disabled.");
  244. me.setIsAutoClaimEnabled(false);
  245. }
  246. else if (myFaction.getLandRounded() >= myFaction.getPowerRounded())
  247. {
  248. me.sendMessage("You can't claim more land! You need more power!");
  249. me.setIsAutoClaimEnabled(false);
  250. }
  251. else
  252. me.attemptClaim(false);
  253. }
  254. else if (me.isAutoSafeClaimEnabled())
  255. {
  256. if ( ! Permission.MANAGE_SAFE_ZONE.has(player))
  257. {
  258. me.setIsAutoSafeClaimEnabled(false);
  259. }
  260. else
  261. {
  262. FLocation playerFlocation = new FLocation(me);
  263. if (!Board.getFactionAt(playerFlocation).isSafeZone())
  264. {
  265. Board.setFactionAt(Factions.i.getSafeZone(), playerFlocation);
  266. me.sendMessage("This land is now a safe zone.");
  267. }
  268. }
  269. }
  270. else if (me.isAutoWarClaimEnabled())
  271. {
  272. if ( ! Permission.MANAGE_WAR_ZONE.has(player))
  273. {
  274. me.setIsAutoWarClaimEnabled(false);
  275. }
  276. else
  277. {
  278. FLocation playerFlocation = new FLocation(me);
  279. if (!Board.getFactionAt(playerFlocation).isWarZone())
  280. {
  281. Board.setFactionAt(Factions.i.getWarZone(), playerFlocation);
  282. me.sendMessage("This land is now a war zone.");
  283. }
  284. }
  285. }
  286. }
  287. @Override
  288. public void onPlayerInteract(PlayerInteractEvent event)
  289. {
  290. if (event.isCancelled()) return;
  291. Block block = event.getClickedBlock();
  292. Player player = event.getPlayer();
  293. if (block == null)
  294. {
  295. return; // clicked in air, apparently
  296. }
  297. if ( ! canPlayerUseBlock(player, block, false))
  298. {
  299. event.setCancelled(true);
  300. return;
  301. }
  302. if (event.getAction() != Action.RIGHT_CLICK_BLOCK)
  303. {
  304. return; // only interested on right-clicks for below
  305. }
  306. if ( ! playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false))
  307. {
  308. event.setCancelled(true);
  309. return;
  310. }
  311. }
  312. public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck)
  313. {
  314. FPlayer me = FPlayers.i.get(player);
  315. if (me.isAdminBypassing())
  316. return true;
  317. FLocation loc = new FLocation(location);
  318. Faction otherFaction = Board.getFactionAt(loc);
  319. if (otherFaction.hasPlayersOnline())
  320. {
  321. if ( ! Conf.territoryDenyUseageMaterials.contains(material))
  322. return true; // Item isn't one we're preventing for online factions.
  323. }
  324. else
  325. {
  326. if ( ! Conf.territoryDenyUseageMaterialsWhenOffline.contains(material))
  327. return true; // Item isn't one we're preventing for offline factions.
  328. }
  329. if (otherFaction.isNone())
  330. {
  331. if (!Conf.wildernessDenyUseage || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName()))
  332. return true; // This is not faction territory. Use whatever you like here.
  333. if (!justCheck)
  334. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the wilderness.");
  335. return false;
  336. }
  337. else if (otherFaction.isSafeZone())
  338. {
  339. if (!Conf.safeZoneDenyUseage || Permission.MANAGE_SAFE_ZONE.has(player))
  340. return true;
  341. if (!justCheck)
  342. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a safe zone.");
  343. return false;
  344. }
  345. else if (otherFaction.isWarZone())
  346. {
  347. if (!Conf.warZoneDenyUseage || Permission.MANAGE_WAR_ZONE.has(player))
  348. return true;
  349. if (!justCheck)
  350. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a war zone.");
  351. return false;
  352. }
  353. Faction myFaction = me.getFaction();
  354. Relation rel = myFaction.getRelationTo(otherFaction);
  355. // Cancel if we are not in our own territory
  356. if (rel.confDenyUseage())
  357. {
  358. if (!justCheck)
  359. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction));
  360. return false;
  361. }
  362. // Also cancel if player doesn't have ownership rights for this claim
  363. if (Conf.ownedAreasEnabled && Conf.ownedAreaDenyUseage && !otherFaction.playerHasOwnershipRights(me, loc))
  364. {
  365. if (!justCheck)
  366. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+otherFaction.getOwnerListString(loc));
  367. return false;
  368. }
  369. return true;
  370. }
  371. public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck)
  372. {
  373. FPlayer me = FPlayers.i.get(player);
  374. if (me.isAdminBypassing())
  375. return true;
  376. Material material = block.getType();
  377. FLocation loc = new FLocation(block);
  378. Faction otherFaction = Board.getFactionAt(loc);
  379. // no door/chest/whatever protection in wilderness, war zones, or safe zones
  380. if (!otherFaction.isNormal())
  381. return true;
  382. // We only care about some material types.
  383. if (otherFaction.hasPlayersOnline())
  384. {
  385. if ( ! Conf.territoryProtectedMaterials.contains(material))
  386. return true;
  387. }
  388. else
  389. {
  390. if ( ! Conf.territoryProtectedMaterialsWhenOffline.contains(material))
  391. return true;
  392. }
  393. Faction myFaction = me.getFaction();
  394. Relation rel = myFaction.getRelationTo(otherFaction);
  395. // You may use any block unless it is another faction's territory...
  396. if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials))
  397. {
  398. if (!justCheck)
  399. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction));
  400. return false;
  401. }
  402. // Also cancel if player doesn't have ownership rights for this claim
  403. if (Conf.ownedAreasEnabled && Conf.ownedAreaProtectMaterials && !otherFaction.playerHasOwnershipRights(me, loc))
  404. {
  405. if (!justCheck)
  406. me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+otherFaction.getOwnerListString(loc));
  407. return false;
  408. }
  409. return true;
  410. }
  411. @Override
  412. public void onPlayerRespawn(PlayerRespawnEvent event)
  413. {
  414. FPlayer me = FPlayers.i.get(event.getPlayer());
  415. Location home = me.getFaction().getHome();
  416. if
  417. (
  418. Conf.homesEnabled
  419. &&
  420. Conf.homesTeleportToOnDeath
  421. &&
  422. home != null
  423. &&
  424. (
  425. Conf.homesRespawnFromNoPowerLossWorlds
  426. ||
  427. ! Conf.worldsNoPowerLoss.contains(event.getPlayer().getWorld().getName())
  428. )
  429. )
  430. {
  431. event.setRespawnLocation(home);
  432. }
  433. }
  434. // For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected),
  435. // but these separate bucket events below always fire without fail
  436. @Override
  437. public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event)
  438. {
  439. if (event.isCancelled()) return;
  440. Block block = event.getBlockClicked();
  441. Player player = event.getPlayer();
  442. if ( ! playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false))
  443. {
  444. event.setCancelled(true);
  445. return;
  446. }
  447. }
  448. @Override
  449. public void onPlayerBucketFill(PlayerBucketFillEvent event)
  450. {
  451. if (event.isCancelled()) return;
  452. Block block = event.getBlockClicked();
  453. Player player = event.getPlayer();
  454. if ( ! playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false))
  455. {
  456. event.setCancelled(true);
  457. return;
  458. }
  459. }
  460. @Override
  461. public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
  462. {
  463. if (event.isCancelled()) return;
  464. if (preventCommand(event.getMessage().toLowerCase(), event.getPlayer()))
  465. {
  466. event.setCancelled(true);
  467. }
  468. }
  469. public static boolean preventCommand(String fullCmd, Player player)
  470. {
  471. if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty()))
  472. {
  473. return false;
  474. }
  475. FPlayer me = FPlayers.i.get(player);
  476. if (!me.isInOthersTerritory())
  477. {
  478. return false;
  479. }
  480. Relation rel = me.getRelationToLocation();
  481. if (rel.isAtLeast(Relation.ALLY))
  482. {
  483. return false;
  484. }
  485. String shortCmd = fullCmd.substring(1); // Get rid of the slash at the beginning
  486. if
  487. (
  488. rel.isNeutral()
  489. &&
  490. ! Conf.territoryNeutralDenyCommands.isEmpty()
  491. &&
  492. ! me.isAdminBypassing()
  493. )
  494. {
  495. Iterator<String> iter = Conf.territoryNeutralDenyCommands.iterator();
  496. String cmdCheck;
  497. while (iter.hasNext())
  498. {
  499. cmdCheck = iter.next();
  500. if (cmdCheck == null)
  501. {
  502. iter.remove();
  503. continue;
  504. }
  505. cmdCheck = cmdCheck.toLowerCase();
  506. if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck))
  507. {
  508. me.sendMessage("You can't use the command \""+fullCmd+"\" in neutral territory.");
  509. return true;
  510. }
  511. }
  512. }
  513. else if
  514. (
  515. rel.isEnemy()
  516. &&
  517. ! Conf.territoryEnemyDenyCommands.isEmpty()
  518. &&
  519. ! me.isAdminBypassing()
  520. )
  521. {
  522. Iterator<String> iter = Conf.territoryEnemyDenyCommands.iterator();
  523. String cmdCheck;
  524. while (iter.hasNext())
  525. {
  526. cmdCheck = iter.next();
  527. if (cmdCheck == null)
  528. {
  529. iter.remove();
  530. continue;
  531. }
  532. cmdCheck = cmdCheck.toLowerCase();
  533. if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck))
  534. {
  535. me.sendMessage("You can't use the command \""+fullCmd+"\" in enemy territory.");
  536. return true;
  537. }
  538. }
  539. }
  540. return false;
  541. }
  542. @Override
  543. public void onPlayerKick(PlayerKickEvent event)
  544. {
  545. if (event.isCancelled()) return;
  546. FPlayer badGuy = FPlayers.i.get(event.getPlayer());
  547. if (badGuy == null)
  548. {
  549. return;
  550. }
  551. SpoutFeatures.playerDisconnect(badGuy);
  552. // if player was banned (not just kicked), get rid of their stored info
  553. if (event.getReason().equals("Banned by admin."))
  554. {
  555. badGuy.leave(false);
  556. badGuy.markForDeletion(true);
  557. }
  558. }
  559. }