Saber-Factions/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java

652 lines
18 KiB
Java
Raw Normal View History

2011-07-18 22:06:02 +02:00
package com.massivecraft.factions.listeners;
2011-02-06 13:36:11 +01:00
import java.util.logging.Logger;
import java.util.Iterator;
import java.util.UnknownFormatConversionException;
2011-02-06 13:36:11 +01:00
import org.bukkit.ChatColor;
2011-03-23 17:39:56 +01:00
import org.bukkit.Location;
2011-03-23 12:00:38 +01:00
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
2011-02-06 13:36:11 +01:00
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
2011-02-06 13:36:11 +01:00
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
2011-03-23 17:39:56 +01:00
import org.bukkit.event.player.PlayerRespawnEvent;
2011-07-18 22:06:02 +02:00
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.FPlayers;
2011-07-18 22:06:02 +02:00
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.P;
import com.massivecraft.factions.integration.SpoutFeatures;
2011-10-08 23:22:02 +02:00
import com.massivecraft.factions.struct.Permission;
2011-07-18 22:06:02 +02:00
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.zcore.util.TextUtil;
2011-02-06 13:36:11 +01:00
import java.util.logging.Level;
2011-02-06 13:36:11 +01:00
public class FactionsPlayerListener extends PlayerListener
{
public P p;
public FactionsPlayerListener(P p)
{
this.p = p;
}
2011-02-06 13:36:11 +01:00
@Override
public void onPlayerChat(PlayerChatEvent event)
{
if (event.isCancelled()) return;
Player talkingPlayer = event.getPlayer();
2011-02-06 13:36:11 +01:00
String msg = event.getMessage();
// ... it was not a command. This means that it is a chat message!
FPlayer me = FPlayers.i.get(talkingPlayer);
// Are we to insert the Faction tag into the format?
// If we are not to insert it - we are done.
if ( ! Conf.chatTagEnabled || Conf.chatTagHandledByAnotherPlugin)
{
return;
}
int InsertIndex = 0;
String eventFormat = event.getFormat();
if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString))
{
// we're using the "replace" method of inserting the faction tags
// if they stuck "{FACTION_TITLE}" in there, go ahead and do it too
if (eventFormat.contains("{FACTION_TITLE}"))
{
eventFormat = eventFormat.replace("{FACTION_TITLE}", me.getTitle());
}
InsertIndex = eventFormat.indexOf(Conf.chatTagReplaceString);
eventFormat = eventFormat.replace(Conf.chatTagReplaceString, "");
Conf.chatTagPadAfter = false;
Conf.chatTagPadBefore = false;
}
else if (!Conf.chatTagInsertAfterString.isEmpty() && eventFormat.contains(Conf.chatTagInsertAfterString))
{
// we're using the "insert after string" method
InsertIndex = eventFormat.indexOf(Conf.chatTagInsertAfterString) + Conf.chatTagInsertAfterString.length();
}
else if (!Conf.chatTagInsertBeforeString.isEmpty() && eventFormat.contains(Conf.chatTagInsertBeforeString))
{
// we're using the "insert before string" method
InsertIndex = eventFormat.indexOf(Conf.chatTagInsertBeforeString);
}
else
{
// we'll fall back to using the index place method
InsertIndex = Conf.chatTagInsertIndex;
if (InsertIndex > eventFormat.length())
return;
}
String formatStart = eventFormat.substring(0, InsertIndex) + ((Conf.chatTagPadBefore && !me.getChatTag().isEmpty()) ? " " : "");
String formatEnd = ((Conf.chatTagPadAfter && !me.getChatTag().isEmpty()) ? " " : "") + eventFormat.substring(InsertIndex);
String nonColoredMsgFormat = formatStart + me.getChatTag().trim() + formatEnd;
// Relation Colored?
if (Conf.chatTagRelationColored)
{
// We must choke the standard message and send out individual messages to all players
// Why? Because the relations will differ.
event.setCancelled(true);
for (Player listeningPlayer : event.getRecipients())
{
FPlayer you = FPlayers.i.get(listeningPlayer);
String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd;
try
{
listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg));
}
catch (UnknownFormatConversionException ex)
{
P.p.log(Level.SEVERE, "Critical error in chat message formatting! Complete format string: "+yourFormat);
P.p.log(Level.SEVERE, "First half of event.getFormat() string: "+formatStart);
P.p.log(Level.SEVERE, "Second half of event.getFormat() string: "+formatEnd);
P.p.log(Level.SEVERE, "NOTE: To fix this quickly, running this command should work: f config chatTagInsertIndex 0");
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.");
ex.printStackTrace();
return;
}
2011-02-06 13:36:11 +01:00
}
// Write to the log... We will write the non colored message.
String nonColoredMsg = ChatColor.stripColor(String.format(nonColoredMsgFormat, talkingPlayer.getDisplayName(), msg));
Logger.getLogger("Minecraft").info(nonColoredMsg);
}
else
{
// No relation color.
event.setFormat(nonColoredMsgFormat);
2011-02-06 13:36:11 +01:00
}
}
@Override
public void onPlayerJoin(PlayerJoinEvent event)
{
// Make sure that all online players do have a fplayer.
final FPlayer me = FPlayers.i.get(event.getPlayer());
2011-03-22 20:36:33 +01:00
// Update the lastLoginTime for this fplayer
me.setLastLoginTime(System.currentTimeMillis());
2011-03-23 12:00:38 +01:00
// Run the member auto kick routine. Twice to get to the admins...
FPlayers.i.autoLeaveOnInactivityRoutine();
FPlayers.i.autoLeaveOnInactivityRoutine();
SpoutFeatures.updateTerritoryDisplay(me);
// Appearance updates which are run when a player joins don't apply properly for other clients, so they need to be delayed slightly
P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, new Runnable() {
public void run() {
SpoutFeatures.updateAppearances(me.getPlayer());
SpoutFeatures.updateTerritoryDisplay(me);
}
}, 20);
2011-02-06 13:36:11 +01:00
}
@Override
public void onPlayerQuit(PlayerQuitEvent event)
{
// Make sure player's power is up to date when they log off.
FPlayer me = FPlayers.i.get(event.getPlayer());
me.getPower();
2011-07-31 03:17:00 +02:00
Faction myFaction = me.getFaction();
if (myFaction != null)
{
2011-07-31 03:17:00 +02:00
myFaction.memberLoggedOff();
}
SpoutFeatures.playerDisconnect(me);
}
2011-02-06 13:36:11 +01:00
@Override
public void onPlayerMove(PlayerMoveEvent event)
{
2011-07-31 03:17:00 +02:00
Player player = event.getPlayer();
FPlayer me = FPlayers.i.get(player);
2011-02-13 17:04:06 +01:00
2011-02-06 13:36:11 +01:00
// Did we change coord?
FLocation from = me.getLastStoodAt();
2011-07-31 03:17:00 +02:00
FLocation to = new FLocation(player.getLocation());
if (from.equals(to))
{
2011-02-06 13:36:11 +01:00
return;
}
// Yes we did change coord (:
me.setLastStoodAt(to);
2011-02-13 11:18:08 +01:00
if (me.isMapAutoUpdating())
{
2011-07-31 03:17:00 +02:00
me.sendMessage(Board.getMap(me.getFaction(), to, player.getLocation().getYaw()));
}
else
{
2011-02-06 13:36:11 +01:00
// Did we change "host"(faction)?
Faction factionFrom = Board.getFactionAt(from);
Faction factionTo = Board.getFactionAt(to);
Faction myFaction = me.getFaction();
String ownersTo = myFaction.getOwnerListString(to);
if (factionFrom != factionTo)
{
2011-02-06 13:36:11 +01:00
me.sendFactionHereMessage();
if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty())
{
me.sendMessage(Conf.ownedLandMessage+ownersTo);
}
}
else if (Conf.ownedAreasEnabled && Conf.ownedMessageInsideTerritory && factionFrom == factionTo && myFaction == factionTo)
{
String ownersFrom = myFaction.getOwnerListString(from);
if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo))
{
if (!ownersTo.isEmpty())
{
me.sendMessage(Conf.ownedLandMessage+ownersTo);
}
else if (!Conf.publicLandMessage.isEmpty())
{
me.sendMessage(Conf.publicLandMessage);
}
}
2011-02-06 13:36:11 +01:00
}
}
if (me.isAutoClaimEnabled())
{
Faction myFaction = me.getFaction();
// TODO: Why is this ("cost") here and unused??? Should it be used somewhere Brettflan? :)
// Olof just commented it out to avoid the error.
//Faction otherFaction = Board.getFactionAt(to);
//double cost = Econ.calculateClaimCost(myFaction.getLandRounded(), otherFaction.isNormal());
if (me.getRole().value < Role.MODERATOR.value)
{
me.sendMessage("You must be "+Role.MODERATOR+" to claim land.");
me.setIsAutoClaimEnabled(false);
}
else if (Conf.worldsNoClaiming.contains(to.getWorldName()))
{
me.sendMessage("Sorry, this world has land claiming disabled.");
me.setIsAutoClaimEnabled(false);
}
else if (myFaction.getLandRounded() >= myFaction.getPowerRounded())
{
me.sendMessage("You can't claim more land! You need more power!");
me.setIsAutoClaimEnabled(false);
}
else
me.attemptClaim(false);
}
else if (me.isAutoSafeClaimEnabled())
{
2011-10-08 23:22:02 +02:00
if ( ! Permission.MANAGE_SAFE_ZONE.has(player))
{
me.setIsAutoSafeClaimEnabled(false);
}
else
{
FLocation playerFlocation = new FLocation(me);
if (!Board.getFactionAt(playerFlocation).isSafeZone())
{
Board.setFactionAt(Factions.i.getSafeZone(), playerFlocation);
me.sendMessage("This land is now a safe zone.");
}
}
}
else if (me.isAutoWarClaimEnabled())
{
2011-10-08 23:22:02 +02:00
if ( ! Permission.MANAGE_WAR_ZONE.has(player))
{
me.setIsAutoWarClaimEnabled(false);
}
else
{
FLocation playerFlocation = new FLocation(me);
if (!Board.getFactionAt(playerFlocation).isWarZone())
{
Board.setFactionAt(Factions.i.getWarZone(), playerFlocation);
me.sendMessage("This land is now a war zone.");
}
}
}
2011-02-06 13:36:11 +01:00
}
@Override
public void onPlayerInteract(PlayerInteractEvent event)
{
if (event.isCancelled()) return;
Block block = event.getClickedBlock();
Player player = event.getPlayer();
if (block == null)
{
return; // clicked in air, apparently
}
if ( ! canPlayerUseBlock(player, block, false))
{
event.setCancelled(true);
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK)
{
return; // only interested on right-clicks for below
}
if ( ! playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false))
{
event.setCancelled(true);
return;
}
}
public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck)
{
if (Conf.adminBypassPlayers.contains(player.getName()))
{
return true;
}
FLocation loc = new FLocation(location);
2011-07-31 03:17:00 +02:00
Faction otherFaction = Board.getFactionAt(loc);
if (otherFaction.hasPlayersOnline()){
if ( ! Conf.territoryDenyUseageMaterials.contains(material))
{
return true; // Item isn't one we're preventing for online factions.
}
}
else
{
if ( ! Conf.territoryDenyUseageMaterialsWhenOffline.contains(material))
{
return true; // Item isn't one we're preventing for offline factions.
}
}
FPlayer me = FPlayers.i.get(player);
if (otherFaction.isNone())
{
2011-10-08 23:22:02 +02:00
if (!Conf.wildernessDenyUseage || Permission.ADMIN_BYPASS.has(player) || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName()))
{
return true; // This is not faction territory. Use whatever you like here.
}
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the wilderness.");
}
return false;
}
else if (otherFaction.isSafeZone())
{
2011-10-08 23:22:02 +02:00
if (!Conf.safeZoneDenyUseage || Permission.MANAGE_SAFE_ZONE.has(player))
{
return true;
}
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a safe zone.");
}
return false;
}
else if (otherFaction.isWarZone())
{
2011-10-08 23:22:02 +02:00
if (!Conf.warZoneDenyUseage || Permission.MANAGE_WAR_ZONE.has(player))
{
return true;
}
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a war zone.");
}
return false;
}
Faction myFaction = me.getFaction();
Relation rel = myFaction.getRelation(otherFaction);
boolean ownershipFail = Conf.ownedAreasEnabled && Conf.ownedAreaDenyUseage && !otherFaction.playerHasOwnershipRights(me, loc);
// Cancel if we are not in our own territory
if (!rel.isMember() && rel.confDenyUseage())
{
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction));
}
return false;
2011-07-31 03:17:00 +02:00
}
// Also cancel if player doesn't have ownership rights for this claim
2011-10-08 23:22:02 +02:00
else if (rel.isMember() && ownershipFail && ! Permission.OWNERSHIP_BYPASS.has(player))
{
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc));
}
return false;
}
return true;
}
public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck)
{
if (Conf.adminBypassPlayers.contains(player.getName()))
{
return true;
}
Material material = block.getType();
2011-07-31 03:17:00 +02:00
FLocation loc = new FLocation(block);
Faction otherFaction = Board.getFactionAt(loc);
// no door/chest/whatever protection in wilderness, war zones, or safe zones
if (!otherFaction.isNormal())
{
return true;
}
// We only care about some material types.
if (otherFaction.hasPlayersOnline())
{
if ( ! Conf.territoryProtectedMaterials.contains(material))
{
return true;
}
}
else
{
if ( ! Conf.territoryProtectedMaterialsWhenOffline.contains(material))
{
return true;
}
}
FPlayer me = FPlayers.i.get(player);
Faction myFaction = me.getFaction();
Relation rel = myFaction.getRelation(otherFaction);
boolean ownershipFail = Conf.ownedAreasEnabled && Conf.ownedAreaProtectMaterials && !otherFaction.playerHasOwnershipRights(me, loc);
// You may use any block unless it is another faction's territory...
if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials))
{
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction));
}
return false;
}
2011-07-31 03:17:00 +02:00
// Also cancel if player doesn't have ownership rights for this claim
2011-10-08 23:22:02 +02:00
else if (rel.isMember() && ownershipFail && ! Permission.OWNERSHIP_BYPASS.has(player))
{
if (!justCheck)
{
me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc));
}
2011-07-31 03:17:00 +02:00
return false;
}
return true;
}
2011-03-23 17:39:56 +01:00
@Override
public void onPlayerRespawn(PlayerRespawnEvent event)
{
FPlayer me = FPlayers.i.get(event.getPlayer());
2011-03-23 17:39:56 +01:00
Location home = me.getFaction().getHome();
if
(
Conf.homesEnabled
&&
Conf.homesTeleportToOnDeath
&&
home != null
&&
(
Conf.homesRespawnFromNoPowerLossWorlds
||
! Conf.worldsNoPowerLoss.contains(event.getPlayer().getWorld().getName())
)
)
{
2011-03-23 17:39:56 +01:00
event.setRespawnLocation(home);
}
}
// For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected),
// but these separate bucket events below always fire without fail
@Override
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event)
{
if (event.isCancelled()) return;
Block block = event.getBlockClicked();
Player player = event.getPlayer();
if ( ! playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false))
{
event.setCancelled(true);
return;
}
}
@Override
public void onPlayerBucketFill(PlayerBucketFillEvent event)
{
if (event.isCancelled()) return;
Block block = event.getBlockClicked();
Player player = event.getPlayer();
if ( ! playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false))
{
event.setCancelled(true);
return;
}
}
@Override
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
{
if (event.isCancelled()) return;
if (preventCommand(event.getMessage().toLowerCase(), event.getPlayer()))
{
event.setCancelled(true);
}
}
public static boolean preventCommand(String fullCmd, Player player)
{
if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty()))
{
return false;
}
FPlayer me = FPlayers.i.get(player);
if (!me.isInOthersTerritory())
{
return false;
}
Relation rel = me.getRelationToLocation();
if (rel.isAtLeast(Relation.ALLY))
{
return false;
}
String shortCmd = fullCmd.substring(1); // Get rid of the slash at the beginning
if
(
rel.isNeutral()
&&
! Conf.territoryNeutralDenyCommands.isEmpty()
&&
! Conf.adminBypassPlayers.contains(me.getName())
)
{
Iterator<String> iter = Conf.territoryNeutralDenyCommands.iterator();
String cmdCheck;
while (iter.hasNext())
{
cmdCheck = iter.next();
if (cmdCheck == null)
{
iter.remove();
continue;
}
cmdCheck = cmdCheck.toLowerCase();
if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck))
{
me.sendMessage("You can't use the command \""+fullCmd+"\" in neutral territory.");
return true;
}
}
}
else if
(
rel.isEnemy()
&&
! Conf.territoryEnemyDenyCommands.isEmpty()
&&
! Conf.adminBypassPlayers.contains(me.getName())
)
{
Iterator<String> iter = Conf.territoryEnemyDenyCommands.iterator();
String cmdCheck;
while (iter.hasNext())
{
cmdCheck = iter.next();
if (cmdCheck == null)
{
iter.remove();
continue;
}
cmdCheck = cmdCheck.toLowerCase();
if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck))
{
me.sendMessage("You can't use the command \""+fullCmd+"\" in enemy territory.");
return true;
}
}
}
return false;
}
@Override
public void onPlayerKick(PlayerKickEvent event)
{
if (event.isCancelled()) return;
FPlayer badGuy = FPlayers.i.get(event.getPlayer());
if (badGuy == null)
{
return;
}
SpoutFeatures.playerDisconnect(badGuy);
// if player was banned (not just kicked), get rid of their stored info
if (event.getReason().equals("Banned by admin."))
{
badGuy.leave(false);
badGuy.markForDeletion(true);
}
}
2011-02-06 13:36:11 +01:00
}