Added /ignore and /separate.
Also companion commands like /unseparate, /unignore, and /ignorelist.
This commit is contained in:
parent
02dee1f21e
commit
14717bd4c7
24
plugin.yml
24
plugin.yml
|
|
@ -152,6 +152,26 @@ commands:
|
|||
description: Allows an administrator to get technical information about blocks in the world and items in hand.
|
||||
usage: /GPBlockInfo
|
||||
permission: griefprevention.gpblockinfo
|
||||
ignoreplayer:
|
||||
description: Ignores another player's chat messages.
|
||||
usage: /IgnorePlayer <player name>
|
||||
aliases: [ignore]
|
||||
unignoreplayer:
|
||||
description: Unignores another player's chat messages.
|
||||
usage: /UnIgnorePlayer <player name>
|
||||
aliases: [unignore]
|
||||
ignoredplayerlist:
|
||||
description: Lists the players you're ignoring in chat.
|
||||
usage: /IgnoredPlayerList
|
||||
aliases: [ignores, ignored, ignorelist, ignoredlist, listignores, listignored, ignoring]
|
||||
separate:
|
||||
description: Forces two players to ignore each other in chat.
|
||||
usage: /Separate
|
||||
permission: griefprevention.separate
|
||||
unseparate:
|
||||
description: Reverses /separate.
|
||||
usage: /UnSeparate
|
||||
permission: griefprevention.separate
|
||||
permissions:
|
||||
griefprevention.createclaims:
|
||||
description: Grants permission to create claims.
|
||||
|
|
@ -176,6 +196,7 @@ permissions:
|
|||
griefprevention.transferclaim: true
|
||||
griefprevention.claimslistother: true
|
||||
griefprevention.siegeimmune: true
|
||||
griefprevention.separate: true
|
||||
griefprevention.siegeimmune:
|
||||
description: Makes a player immune to /Siege.
|
||||
default: op
|
||||
|
|
@ -239,3 +260,6 @@ permissions:
|
|||
griefprevention.overrideclaimcountlimit:
|
||||
description: Allows players to create more claims than the limit specified by the config.
|
||||
default: op
|
||||
griefprevention.separate:
|
||||
description: Grants access to /Separate and /UnSeparate.
|
||||
default: op
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
|
@ -31,6 +34,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
//singleton class which manages all GriefPrevention data (except for config options)
|
||||
public abstract class DataStore
|
||||
{
|
||||
|
|
@ -55,7 +60,8 @@ public abstract class DataStore
|
|||
|
||||
//path information, for where stuff stored on disk is well... stored
|
||||
protected final static String dataLayerFolderPath = "plugins" + File.separator + "GriefPreventionData";
|
||||
final static String configFilePath = dataLayerFolderPath + File.separator + "config.yml";
|
||||
final static String playerDataFolderPath = dataLayerFolderPath + File.separator + "PlayerData";
|
||||
final static String configFilePath = dataLayerFolderPath + File.separator + "config.yml";
|
||||
final static String messagesFilePath = dataLayerFolderPath + File.separator + "messages.yml";
|
||||
final static String softMuteFilePath = dataLayerFolderPath + File.separator + "softMute.txt";
|
||||
|
||||
|
|
@ -104,6 +110,13 @@ public abstract class DataStore
|
|||
{
|
||||
GriefPrevention.AddLogEntry(this.claims.size() + " total claims loaded.");
|
||||
|
||||
//ensure data folders exist
|
||||
File playerDataFolder = new File(playerDataFolderPath);
|
||||
if(!playerDataFolder.exists())
|
||||
{
|
||||
playerDataFolder.mkdirs();
|
||||
}
|
||||
|
||||
//load up all the messages from messages.yml
|
||||
this.loadMessages();
|
||||
GriefPrevention.AddLogEntry("Customizable messages loaded.");
|
||||
|
|
@ -756,7 +769,47 @@ public abstract class DataStore
|
|||
new SavePlayerDataThread(playerID, playerData).start();
|
||||
}
|
||||
|
||||
public abstract void asyncSavePlayerData(UUID playerID, PlayerData playerData);
|
||||
public void asyncSavePlayerData(UUID playerID, PlayerData playerData)
|
||||
{
|
||||
//save everything except the ignore list
|
||||
this.overrideSavePlayerData(playerID, playerData);
|
||||
|
||||
//save the ignore list
|
||||
if(playerData.ignoreListChanged)
|
||||
{
|
||||
StringBuilder fileContent = new StringBuilder();
|
||||
try
|
||||
{
|
||||
for(UUID uuidKey : playerData.ignoredPlayers.keySet())
|
||||
{
|
||||
Boolean value = playerData.ignoredPlayers.get(uuidKey);
|
||||
if(value == null) continue;
|
||||
|
||||
//admin-enforced ignores begin with an asterisk
|
||||
if(value)
|
||||
{
|
||||
fileContent.append("*");
|
||||
}
|
||||
|
||||
fileContent.append(uuidKey);
|
||||
fileContent.append("\n");
|
||||
}
|
||||
|
||||
//write data to file
|
||||
File playerDataFile = new File(playerDataFolderPath + File.separator + playerID + ".ignore");
|
||||
Files.write(fileContent.toString().trim().getBytes("UTF-8"), playerDataFile);
|
||||
}
|
||||
|
||||
//if any problem, log it
|
||||
catch(Exception e)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("GriefPrevention: Unexpected exception saving data for player \"" + playerID.toString() + "\": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract void overrideSavePlayerData(UUID playerID, PlayerData playerData);
|
||||
|
||||
//extends a claim to a new depth
|
||||
//respects the max depth config variable
|
||||
|
|
@ -1275,6 +1328,12 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.NoChatUntilMove, "Sorry, but you have to move a little more before you can chat. We get lots of spam bots here. :)", null);
|
||||
this.addDefault(defaults, Messages.SiegeImmune, "That player is immune to /siege.", null);
|
||||
this.addDefault(defaults, Messages.SetClaimBlocksSuccess, "Updated accrued claim blocks.", null);
|
||||
this.addDefault(defaults, Messages.IgnoreConfirmation, "You're now ignoring chat messages from that player.", null);
|
||||
this.addDefault(defaults, Messages.UnIgnoreConfirmation, "You're no longer ignoring chat messages from that player.", null);
|
||||
this.addDefault(defaults, Messages.NotIgnoringPlayer, "You're not ignoring that player.", null);
|
||||
this.addDefault(defaults, Messages.SeparateConfirmation, "Those players will now ignore each other in chat.", null);
|
||||
this.addDefault(defaults, Messages.UnSeparateConfirmation, "Those players will no longer ignore each other in chat.", null);
|
||||
this.addDefault(defaults, Messages.NotIgnoringAnyone, "You're not ignoring anyone.", null);
|
||||
|
||||
//load the config file
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
|
||||
|
|
|
|||
|
|
@ -524,7 +524,7 @@ public class DatabaseDataStore extends DataStore
|
|||
|
||||
//saves changes to player data. MUST be called after you're done making changes, otherwise a reload will lose them
|
||||
@Override
|
||||
public void asyncSavePlayerData(UUID playerID, PlayerData playerData)
|
||||
public void overrideSavePlayerData(UUID playerID, PlayerData playerData)
|
||||
{
|
||||
//never save data for the "administrative" account. an empty string for player name indicates administrative account
|
||||
if(playerID == null) return;
|
||||
|
|
|
|||
|
|
@ -32,17 +32,15 @@ import com.google.common.io.Files;
|
|||
//manages data stored in the file system
|
||||
public class FlatFileDataStore extends DataStore
|
||||
{
|
||||
private final static String playerDataFolderPath = dataLayerFolderPath + File.separator + "PlayerData";
|
||||
private final static String claimDataFolderPath = dataLayerFolderPath + File.separator + "ClaimData";
|
||||
private final static String nextClaimIdFilePath = claimDataFolderPath + File.separator + "_nextClaimID";
|
||||
private final static String schemaVersionFilePath = dataLayerFolderPath + File.separator + "_schemaVersion";
|
||||
|
||||
static boolean hasData()
|
||||
{
|
||||
File playerDataFolder = new File(playerDataFolderPath);
|
||||
File claimsDataFolder = new File(claimDataFolderPath);
|
||||
|
||||
return playerDataFolder.exists() || claimsDataFolder.exists();
|
||||
return claimsDataFolder.exists();
|
||||
}
|
||||
|
||||
//initialization!
|
||||
|
|
@ -554,7 +552,7 @@ public class FlatFileDataStore extends DataStore
|
|||
|
||||
//saves changes to player data. MUST be called after you're done making changes, otherwise a reload will lose them
|
||||
@Override
|
||||
public void asyncSavePlayerData(UUID playerID, PlayerData playerData)
|
||||
public void overrideSavePlayerData(UUID playerID, PlayerData playerData)
|
||||
{
|
||||
//never save data for the "administrative" account. null for claim owner ID indicates administrative account
|
||||
if(playerID == null) return;
|
||||
|
|
@ -596,6 +594,7 @@ public class FlatFileDataStore extends DataStore
|
|||
catch(Exception e)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("GriefPrevention: Unexpected exception saving data for player \"" + playerID.toString() + "\": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
@ -281,7 +282,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
String dataMode = (this.dataStore instanceof FlatFileDataStore)?"(File Mode)":"(Database Mode)";
|
||||
AddLogEntry("Finished loading data " + dataMode + ".");
|
||||
|
||||
//unless claim block accrual is disabled, start the recurring per 5 minute event to give claim blocks to online players
|
||||
//unless claim block accrual is disabled, start the recurring per 10 minute event to give claim blocks to online players
|
||||
//20L ~ 1 second
|
||||
if(this.config_claims_blocksAccruedPerHour > 0)
|
||||
{
|
||||
|
|
@ -354,6 +355,13 @@ public class GriefPrevention extends JavaPlugin
|
|||
namesThread.setPriority(Thread.MIN_PRIORITY);
|
||||
namesThread.start();
|
||||
|
||||
//load ignore lists for any already-online players
|
||||
Collection<Player> players = (Collection<Player>)GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
for(Player player : players)
|
||||
{
|
||||
new IgnoreLoaderThread(player.getUniqueId(), this.dataStore.getPlayerData(player.getUniqueId()).ignoredPlayers).start();
|
||||
}
|
||||
|
||||
AddLogEntry("Boot finished.");
|
||||
}
|
||||
|
||||
|
|
@ -2049,9 +2057,169 @@ public class GriefPrevention extends JavaPlugin
|
|||
return true;
|
||||
}
|
||||
|
||||
//ignoreplayer
|
||||
else if(cmd.getName().equalsIgnoreCase("ignoreplayer") && player != null)
|
||||
{
|
||||
//requires target player name
|
||||
if(args.length < 1) return false;
|
||||
|
||||
//validate target player
|
||||
OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]);
|
||||
if(targetPlayer == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.setIgnoreStatus(player, targetPlayer, IgnoreMode.StandardIgnore);
|
||||
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.IgnoreConfirmation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//unignoreplayer
|
||||
else if(cmd.getName().equalsIgnoreCase("unignoreplayer") && player != null)
|
||||
{
|
||||
//requires target player name
|
||||
if(args.length < 1) return false;
|
||||
|
||||
//validate target player
|
||||
OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]);
|
||||
if(targetPlayer == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
Boolean ignoreStatus = playerData.ignoredPlayers.get(targetPlayer.getUniqueId());
|
||||
if(ignoreStatus == null || ignoreStatus == true)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NotIgnoringPlayer);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.setIgnoreStatus(player, targetPlayer, IgnoreMode.None);
|
||||
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.UnIgnoreConfirmation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//ignoredplayerlist
|
||||
else if(cmd.getName().equalsIgnoreCase("ignoredplayerlist") && player != null)
|
||||
{
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(Entry<UUID, Boolean> entry : playerData.ignoredPlayers.entrySet())
|
||||
{
|
||||
if(entry.getValue() != null)
|
||||
{
|
||||
//if not an admin ignore, add it to the list
|
||||
if(!entry.getValue())
|
||||
{
|
||||
builder.append(GriefPrevention.lookupPlayerName(entry.getKey()));
|
||||
builder.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String list = builder.toString().trim();
|
||||
if(list.isEmpty())
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.NotIgnoringAnyone);
|
||||
}
|
||||
else
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, list);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//separateplayers
|
||||
else if(cmd.getName().equalsIgnoreCase("separate") && player != null)
|
||||
{
|
||||
//requires two player names
|
||||
if(args.length < 2) return false;
|
||||
|
||||
//validate target players
|
||||
OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]);
|
||||
if(targetPlayer == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflinePlayer targetPlayer2 = this.resolvePlayerByName(args[1]);
|
||||
if(targetPlayer2 == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.setIgnoreStatus(targetPlayer, targetPlayer2, IgnoreMode.AdminIgnore);
|
||||
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.SeparateConfirmation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//unseparateplayers
|
||||
else if(cmd.getName().equalsIgnoreCase("unseparate") && player != null)
|
||||
{
|
||||
//requires two player names
|
||||
if(args.length < 2) return false;
|
||||
|
||||
//validate target players
|
||||
OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0]);
|
||||
if(targetPlayer == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflinePlayer targetPlayer2 = this.resolvePlayerByName(args[1]);
|
||||
if(targetPlayer2 == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound2);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.setIgnoreStatus(targetPlayer, targetPlayer2, IgnoreMode.None);
|
||||
this.setIgnoreStatus(targetPlayer2, targetPlayer, IgnoreMode.None);
|
||||
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.UnSeparateConfirmation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setIgnoreStatus(OfflinePlayer ignorer, OfflinePlayer ignoree, IgnoreMode mode)
|
||||
{
|
||||
PlayerData playerData = this.dataStore.getPlayerData(ignorer.getUniqueId());
|
||||
if(mode == IgnoreMode.None)
|
||||
{
|
||||
playerData.ignoredPlayers.remove(ignoree.getUniqueId());
|
||||
}
|
||||
else
|
||||
{
|
||||
playerData.ignoredPlayers.put(ignoree.getUniqueId(), mode == IgnoreMode.StandardIgnore ? false : true);
|
||||
}
|
||||
|
||||
playerData.ignoreListChanged = true;
|
||||
if(!ignorer.isOnline())
|
||||
{
|
||||
this.dataStore.savePlayerData(ignorer.getUniqueId(), playerData);
|
||||
this.dataStore.clearCachedPlayerData(ignorer.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
enum IgnoreMode {None, StandardIgnore, AdminIgnore}
|
||||
|
||||
private String trustEntryToPlayerName(String entry)
|
||||
{
|
||||
if(entry.startsWith("[") || entry.equals("public"))
|
||||
|
|
|
|||
85
src/me/ryanhamshire/GriefPrevention/IgnoreLoaderThread.java
Normal file
85
src/me/ryanhamshire/GriefPrevention/IgnoreLoaderThread.java
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
//loads ignore data from file into a hash map
|
||||
class IgnoreLoaderThread extends Thread
|
||||
{
|
||||
private UUID playerToLoad;
|
||||
private ConcurrentHashMap<UUID, Boolean> destinationMap;
|
||||
|
||||
IgnoreLoaderThread(UUID playerToLoad, ConcurrentHashMap<UUID, Boolean> destinationMap)
|
||||
{
|
||||
this.playerToLoad = playerToLoad;
|
||||
this.destinationMap = destinationMap;
|
||||
this.setPriority(MIN_PRIORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
File ignoreFile = new File(DataStore.playerDataFolderPath + File.separator + this.playerToLoad + ".ignore");
|
||||
|
||||
//if the file doesn't exist, there's nothing to do here
|
||||
if(!ignoreFile.exists()) return;
|
||||
|
||||
boolean needRetry = false;
|
||||
int retriesRemaining = 5;
|
||||
Exception latestException = null;
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
needRetry = false;
|
||||
|
||||
//read the file content and immediately close it
|
||||
List<String> lines = Files.readLines(ignoreFile, Charset.forName("UTF-8"));
|
||||
|
||||
//each line is one ignore. asterisks indicate administrative ignores
|
||||
for(String line : lines)
|
||||
{
|
||||
boolean adminIgnore = false;
|
||||
if(line.startsWith("*"))
|
||||
{
|
||||
adminIgnore = true;
|
||||
line = line.substring(1);
|
||||
}
|
||||
try
|
||||
{
|
||||
UUID ignoredUUID = UUID.fromString(line);
|
||||
this.destinationMap.put(ignoredUUID, adminIgnore);
|
||||
}
|
||||
catch(IllegalArgumentException e){} //if a bad UUID, ignore the line
|
||||
}
|
||||
}
|
||||
|
||||
//if there's any problem with the file's content, retry up to 5 times with 5 milliseconds between
|
||||
catch(Exception e)
|
||||
{
|
||||
latestException = e;
|
||||
needRetry = true;
|
||||
retriesRemaining--;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(needRetry) Thread.sleep(5);
|
||||
}
|
||||
catch(InterruptedException exception) {}
|
||||
|
||||
}while(needRetry && retriesRemaining >= 0);
|
||||
|
||||
//if last attempt failed, log information about the problem
|
||||
if(needRetry)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("Retry attempts exhausted. Unable to load ignore data for player \"" + playerToLoad.toString() + "\": " + latestException.toString());
|
||||
latestException.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,5 +20,5 @@ package me.ryanhamshire.GriefPrevention;
|
|||
|
||||
public enum Messages
|
||||
{
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound2, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionVideo2, DeleteClaimMissing, DeletionSubdivisionWarning, DeleteSuccess, CantDeleteAdminClaim, DeleteAllSuccess, NoDeletePermission, AllAdminDeleted, AdjustBlocksSuccess, NotTrappedHere, RescuePending, NonSiegeWorld, AlreadySieging, NotSiegableThere, SiegeTooFarAway, NoSiegeDefenseless, AlreadyUnderSiegePlayer, AlreadyUnderSiegeArea, NoSiegeAdminClaim, SiegeOnCooldown, SiegeAlert, SiegeConfirmed, AbandonClaimMissing, NotYourClaim, DeleteTopLevelClaim, AbandonSuccess, CantGrantThatPermission, GrantPermissionNoClaim, GrantPermissionConfirmation, ManageUniversalPermissionsInstruction, ManageOneClaimPermissionsInstruction, CollectivePublic, BuildPermission, ContainersPermission, AccessPermission, PermissionsPermission, LocationCurrentClaim, LocationAllClaims, PvPImmunityStart, SiegeNoDrop, DonateItemsInstruction, ChestFull, DonationSuccess, PlayerTooCloseForFire, TooDeepToClaim, ChestClaimConfirmation, AutomaticClaimNotification, UnprotectedChestWarning, ThatPlayerPvPImmune, CantFightWhileImmune, NoDamageClaimedEntity, ShovelBasicClaimMode, RemainingBlocks, CreativeBasicsVideo2, SurvivalBasicsVideo2, TrappedChatKeyword, TrappedInstructions, PvPNoDrop, SiegeNoTeleport, BesiegedNoTeleport, SiegeNoContainers, PvPNoContainers, PvPImmunityEnd, NoBedPermission, NoWildernessBuckets, NoLavaNearOtherPlayer, TooFarAway, BlockNotClaimed, BlockClaimed, SiegeNoShovel, RestoreNaturePlayerInChunk, NoCreateClaimPermission, ResizeClaimTooSmall, ResizeNeedMoreBlocks, NoCreativeUnClaim, ClaimResizeSuccess, ResizeFailOverlap, ResizeStart, ResizeFailOverlapSubdivision, SubdivisionStart, CreateSubdivisionOverlap, SubdivisionSuccess, CreateClaimFailOverlap, CreateClaimFailOverlapOtherPlayer, ClaimsDisabledWorld, ClaimStart, NewClaimTooSmall, CreateClaimInsufficientBlocks, AbandonClaimAdvertisement, CreateClaimFailOverlapShort, CreateClaimSuccess, SiegeWinDoorsOpen, RescueAbortedMoved, SiegeDoorsLockedEjection, NoModifyDuringSiege, OnlyOwnersModifyClaims, NoBuildUnderSiege, NoBuildPvP, NoBuildPermission, NonSiegeMaterial, NoOwnerBuildUnderSiege, NoAccessPermission, NoContainersSiege, NoContainersPermission, OwnerNameForAdminClaims, ClaimTooSmallForEntities, TooManyEntitiesInClaim, YouHaveNoClaims, ConfirmFluidRemoval, AutoBanNotify, AdjustGroupBlocksSuccess, InvalidPermissionID, UntrustOwnerOnly, HowToClaimRegex, NoBuildOutsideClaims, PlayerOfflineTime, BuildingOutsideClaims, TrappedWontWorkHere, CommandBannedInPvP, UnclaimCleanupWarning, BuySellNotConfigured, NoTeleportPvPCombat, NoTNTDamageAboveSeaLevel, NoTNTDamageClaims, IgnoreClaimsAdvertisement, NoPermissionForCommand, ClaimsListNoPermission, ExplosivesDisabled, ExplosivesEnabled, ClaimExplosivesAdvertisement, PlayerInPvPSafeZone, NoPistonsOutsideClaims, SoftMuted, UnSoftMuted, DropUnlockAdvertisement, PickupBlockedExplanation, DropUnlockConfirmation, AdvertiseACandACB, AdvertiseAdminClaims, AdvertiseACB, NotYourPet, PetGiveawayConfirmation, PetTransferCancellation, ReadyToTransferPet, AvoidGriefClaimLand, BecomeMayor, ClaimCreationFailedOverClaimCountLimit, CreateClaimFailOverlapRegion, ResizeFailOverlapRegion, NoBuildPortalPermission, ShowNearbyClaims, NoChatUntilMove, SiegeImmune, SetClaimBlocksSuccess
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound2, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionVideo2, DeleteClaimMissing, DeletionSubdivisionWarning, DeleteSuccess, CantDeleteAdminClaim, DeleteAllSuccess, NoDeletePermission, AllAdminDeleted, AdjustBlocksSuccess, NotTrappedHere, RescuePending, NonSiegeWorld, AlreadySieging, NotSiegableThere, SiegeTooFarAway, NoSiegeDefenseless, AlreadyUnderSiegePlayer, AlreadyUnderSiegeArea, NoSiegeAdminClaim, SiegeOnCooldown, SiegeAlert, SiegeConfirmed, AbandonClaimMissing, NotYourClaim, DeleteTopLevelClaim, AbandonSuccess, CantGrantThatPermission, GrantPermissionNoClaim, GrantPermissionConfirmation, ManageUniversalPermissionsInstruction, ManageOneClaimPermissionsInstruction, CollectivePublic, BuildPermission, ContainersPermission, AccessPermission, PermissionsPermission, LocationCurrentClaim, LocationAllClaims, PvPImmunityStart, SiegeNoDrop, DonateItemsInstruction, ChestFull, DonationSuccess, PlayerTooCloseForFire, TooDeepToClaim, ChestClaimConfirmation, AutomaticClaimNotification, UnprotectedChestWarning, ThatPlayerPvPImmune, CantFightWhileImmune, NoDamageClaimedEntity, ShovelBasicClaimMode, RemainingBlocks, CreativeBasicsVideo2, SurvivalBasicsVideo2, TrappedChatKeyword, TrappedInstructions, PvPNoDrop, SiegeNoTeleport, BesiegedNoTeleport, SiegeNoContainers, PvPNoContainers, PvPImmunityEnd, NoBedPermission, NoWildernessBuckets, NoLavaNearOtherPlayer, TooFarAway, BlockNotClaimed, BlockClaimed, SiegeNoShovel, RestoreNaturePlayerInChunk, NoCreateClaimPermission, ResizeClaimTooSmall, ResizeNeedMoreBlocks, NoCreativeUnClaim, ClaimResizeSuccess, ResizeFailOverlap, ResizeStart, ResizeFailOverlapSubdivision, SubdivisionStart, CreateSubdivisionOverlap, SubdivisionSuccess, CreateClaimFailOverlap, CreateClaimFailOverlapOtherPlayer, ClaimsDisabledWorld, ClaimStart, NewClaimTooSmall, CreateClaimInsufficientBlocks, AbandonClaimAdvertisement, CreateClaimFailOverlapShort, CreateClaimSuccess, SiegeWinDoorsOpen, RescueAbortedMoved, SiegeDoorsLockedEjection, NoModifyDuringSiege, OnlyOwnersModifyClaims, NoBuildUnderSiege, NoBuildPvP, NoBuildPermission, NonSiegeMaterial, NoOwnerBuildUnderSiege, NoAccessPermission, NoContainersSiege, NoContainersPermission, OwnerNameForAdminClaims, ClaimTooSmallForEntities, TooManyEntitiesInClaim, YouHaveNoClaims, ConfirmFluidRemoval, AutoBanNotify, AdjustGroupBlocksSuccess, InvalidPermissionID, UntrustOwnerOnly, HowToClaimRegex, NoBuildOutsideClaims, PlayerOfflineTime, BuildingOutsideClaims, TrappedWontWorkHere, CommandBannedInPvP, UnclaimCleanupWarning, BuySellNotConfigured, NoTeleportPvPCombat, NoTNTDamageAboveSeaLevel, NoTNTDamageClaims, IgnoreClaimsAdvertisement, NoPermissionForCommand, ClaimsListNoPermission, ExplosivesDisabled, ExplosivesEnabled, ClaimExplosivesAdvertisement, PlayerInPvPSafeZone, NoPistonsOutsideClaims, SoftMuted, UnSoftMuted, DropUnlockAdvertisement, PickupBlockedExplanation, DropUnlockConfirmation, AdvertiseACandACB, AdvertiseAdminClaims, AdvertiseACB, NotYourPet, PetGiveawayConfirmation, PetTransferCancellation, ReadyToTransferPet, AvoidGriefClaimLand, BecomeMayor, ClaimCreationFailedOverClaimCountLimit, CreateClaimFailOverlapRegion, ResizeFailOverlapRegion, NoBuildPortalPermission, ShowNearbyClaims, NoChatUntilMove, SiegeImmune, SetClaimBlocksSuccess, IgnoreConfirmation, NotIgnoringPlayer, UnIgnoreConfirmation, SeparateConfirmation, UnSeparateConfirmation, NotIgnoringAnyone
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import me.ryanhamshire.GriefPrevention.Claim;
|
||||
import me.ryanhamshire.GriefPrevention.GriefPrevention;
|
||||
|
|
@ -136,6 +139,11 @@ public class PlayerData
|
|||
//this is an anti-bot strategy.
|
||||
Location noChatLocation = null;
|
||||
|
||||
//ignore list
|
||||
//true means invisible (admin-forced ignore), false means player-created ignore
|
||||
ConcurrentHashMap<UUID, Boolean> ignoredPlayers = new ConcurrentHashMap<UUID, Boolean>();
|
||||
boolean ignoreListChanged = false;
|
||||
|
||||
//whether or not this player is "in" pvp combat
|
||||
public boolean inPvpCombat()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import java.util.UUID;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
import org.bukkit.Achievement;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
|
|
@ -134,10 +135,32 @@ class PlayerEventHandler implements Listener
|
|||
GriefPrevention.AddLogEntry(notificationMessage, CustomLogEntryTypes.Debug, true);
|
||||
}
|
||||
|
||||
//unfiltered messages go to the abridged chat logs
|
||||
//remaining messages
|
||||
else
|
||||
{
|
||||
//enter in abridged chat logs
|
||||
this.makeSocialLogEntry(player.getName(), message);
|
||||
|
||||
//based on ignore lists, remove some of the audience
|
||||
Set<Player> recipientsToRemove = new HashSet<Player>();
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
for(Player recipient : recipients)
|
||||
{
|
||||
if(playerData.ignoredPlayers.containsKey(recipient.getUniqueId()))
|
||||
{
|
||||
recipientsToRemove.add(recipient);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerData targetPlayerData = this.dataStore.getPlayerData(recipient.getUniqueId());
|
||||
if(targetPlayerData.ignoredPlayers.containsKey(player.getUniqueId()))
|
||||
{
|
||||
recipientsToRemove.add(recipient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recipients.removeAll(recipientsToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -419,32 +442,61 @@ class PlayerEventHandler implements Listener
|
|||
{
|
||||
String [] args = event.getMessage().split(" ");
|
||||
|
||||
//if eavesdrop enabled, eavesdrop
|
||||
String command = args[0].toLowerCase();
|
||||
if(GriefPrevention.instance.config_whisperNotifications && GriefPrevention.instance.config_eavesdrop_whisperCommands.contains(command) && !event.getPlayer().hasPermission("griefprevention.eavesdrop") && args.length > 1)
|
||||
|
||||
Player player = event.getPlayer();
|
||||
PlayerData playerData = null;
|
||||
|
||||
//if a whisper
|
||||
if(GriefPrevention.instance.config_eavesdrop_whisperCommands.contains(command) && args.length > 1)
|
||||
{
|
||||
StringBuilder logMessageBuilder = new StringBuilder();
|
||||
logMessageBuilder.append("[[").append(event.getPlayer().getName()).append("]] ");
|
||||
//if eavesdrop enabled, eavesdrop
|
||||
if(GriefPrevention.instance.config_whisperNotifications && !event.getPlayer().hasPermission("griefprevention.eavesdrop"))
|
||||
{
|
||||
StringBuilder logMessageBuilder = new StringBuilder();
|
||||
logMessageBuilder.append("[[").append(event.getPlayer().getName()).append("]] ");
|
||||
|
||||
for(int i = 1; i < args.length; i++)
|
||||
{
|
||||
logMessageBuilder.append(args[i]).append(" ");
|
||||
}
|
||||
for(int i = 1; i < args.length; i++)
|
||||
{
|
||||
logMessageBuilder.append(args[i]).append(" ");
|
||||
}
|
||||
|
||||
String logMessage = logMessageBuilder.toString();
|
||||
String logMessage = logMessageBuilder.toString();
|
||||
|
||||
Collection<Player> players = (Collection<Player>)GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
for(Player player : players)
|
||||
{
|
||||
if(player.hasPermission("griefprevention.eavesdrop") && !player.getName().equalsIgnoreCase(args[1]))
|
||||
{
|
||||
player.sendMessage(ChatColor.GRAY + logMessage);
|
||||
}
|
||||
}
|
||||
Collection<Player> players = (Collection<Player>)GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
for(Player onlinePlayer : players)
|
||||
{
|
||||
if(onlinePlayer.hasPermission("griefprevention.eavesdrop") && !onlinePlayer.getName().equalsIgnoreCase(args[1]))
|
||||
{
|
||||
onlinePlayer.sendMessage(ChatColor.GRAY + logMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//determine target player
|
||||
Player targetPlayer = GriefPrevention.instance.getServer().getPlayer(args[1]);
|
||||
if(targetPlayer != null && targetPlayer.isOnline())
|
||||
{
|
||||
//if either is ignoring the other, cancel this command
|
||||
playerData = this.dataStore.getPlayerData(player.getUniqueId());
|
||||
if(playerData.ignoredPlayers.containsKey(targetPlayer.getUniqueId()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerData targetPlayerData = this.dataStore.getPlayerData(targetPlayer.getUniqueId());
|
||||
if(targetPlayerData.ignoredPlayers.containsKey(player.getUniqueId()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if in pvp, block any pvp-banned slash commands
|
||||
PlayerData playerData = this.dataStore.getPlayerData(event.getPlayer().getUniqueId());
|
||||
if(playerData == null) playerData = this.dataStore.getPlayerData(event.getPlayer().getUniqueId());
|
||||
|
||||
if((playerData.inPvpCombat() || playerData.siegeData != null) && GriefPrevention.instance.config_pvp_blockedCommands.contains(command))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
|
|
@ -497,7 +549,6 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
if(isMonitoredCommand)
|
||||
{
|
||||
Player player = event.getPlayer();
|
||||
Claim claim = this.dataStore.getClaimAt(player.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
|
|
@ -713,6 +764,9 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create a thread to load ignore information
|
||||
new IgnoreLoaderThread(playerID, playerData.ignoredPlayers).start();
|
||||
}
|
||||
|
||||
//when a player spawns, conditionally apply temporary pvp protection
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user