Added /SoftMute
This commit is contained in:
parent
5865dc354b
commit
9c1094b95b
10
plugin.yml
10
plugin.yml
|
|
@ -129,6 +129,10 @@ commands:
|
|||
claimexplosions:
|
||||
description: Toggles whether explosives may be used in a specific land claim.
|
||||
usage: /ClaimExplosions
|
||||
softmute:
|
||||
description: Toggles whether a player's messages will only reach other soft-muted players.
|
||||
usage: /SoftMute <player>
|
||||
permission: griefprevention.softmute
|
||||
permissions:
|
||||
griefprevention.createclaims:
|
||||
description: Grants permission to create claims.
|
||||
|
|
@ -146,6 +150,7 @@ permissions:
|
|||
griefprevention.lava: true
|
||||
griefprevention.eavesdrop: true
|
||||
griefprevention.deathblow: true
|
||||
griefprevention.softmute: true
|
||||
griefprevention.restorenature:
|
||||
description: Grants permission to use /RestoreNature.
|
||||
default: op
|
||||
|
|
@ -168,7 +173,7 @@ permissions:
|
|||
description: Grants permission to place lava near the surface and outside of claims.
|
||||
default: op
|
||||
griefprevention.eavesdrop:
|
||||
description: Allows a player to see whispered chat messages (/tell).
|
||||
description: Allows a player to see whispered chat messages (/tell) and softmuted messages.
|
||||
default: op
|
||||
griefprevention.restorenatureaggressive:
|
||||
description: Grants access to /RestoreNatureAggressive and /RestoreNatureFill.
|
||||
|
|
@ -176,6 +181,9 @@ permissions:
|
|||
griefprevention.deathblow:
|
||||
description: Grants access to /DeathBlow.
|
||||
default: op
|
||||
griefprevention.softmute:
|
||||
description: Grants access to /SoftMute.
|
||||
default: op
|
||||
griefprevention.claims:
|
||||
description: Grants access to claim-related slash commands.
|
||||
default: true
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public abstract class DataStore
|
|||
protected final static String dataLayerFolderPath = "plugins" + File.separator + "GriefPreventionData";
|
||||
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";
|
||||
|
||||
//the latest version of the data schema implemented here
|
||||
protected static final int latestSchemaVersion = 1;
|
||||
|
|
@ -71,6 +72,9 @@ public abstract class DataStore
|
|||
static final String CREATIVE_VIDEO_URL = "http://bit.ly/mcgpcrea";
|
||||
static final String SUBDIVISION_VIDEO_URL = "http://bit.ly/mcgpsub";
|
||||
|
||||
//list of UUIDs which are soft-muted
|
||||
ConcurrentHashMap<UUID, Boolean> softMuteMap = new ConcurrentHashMap<UUID, Boolean>();
|
||||
|
||||
protected int getSchemaVersion()
|
||||
{
|
||||
if(this.currentSchemaVersion >= 0)
|
||||
|
|
@ -118,11 +122,124 @@ public abstract class DataStore
|
|||
GriefPrevention.AddLogEntry("Update finished.");
|
||||
}
|
||||
|
||||
//make a note of the data store schema version
|
||||
//load list of soft mutes
|
||||
this.loadSoftMutes();
|
||||
|
||||
//make a note of the data store schema version
|
||||
this.setSchemaVersion(latestSchemaVersion);
|
||||
}
|
||||
|
||||
//removes cached player data from memory
|
||||
private void loadSoftMutes()
|
||||
{
|
||||
File softMuteFile = new File(softMuteFilePath);
|
||||
if(softMuteFile.exists())
|
||||
{
|
||||
BufferedReader inStream = null;
|
||||
try
|
||||
{
|
||||
//open the file
|
||||
inStream = new BufferedReader(new FileReader(softMuteFile.getAbsolutePath()));
|
||||
|
||||
//while there are lines left
|
||||
String nextID = inStream.readLine();
|
||||
while(nextID != null)
|
||||
{
|
||||
//parse line into a UUID
|
||||
UUID playerID;
|
||||
try
|
||||
{
|
||||
playerID = UUID.fromString(nextID);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
playerID = null;
|
||||
GriefPrevention.AddLogEntry("Failed to parse soft mute entry as a UUID: " + nextID);
|
||||
}
|
||||
|
||||
//push it into the map
|
||||
if(playerID != null)
|
||||
{
|
||||
this.softMuteMap.put(playerID, true);
|
||||
}
|
||||
|
||||
//move to the next
|
||||
nextID = inStream.readLine();
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("Failed to read from the soft mute data file: " + e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(inStream != null) inStream.close();
|
||||
}
|
||||
catch(IOException exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
//updates soft mute map and data file
|
||||
boolean toggleSoftMute(UUID playerID)
|
||||
{
|
||||
boolean newValue = !this.isSoftMuted(playerID);
|
||||
|
||||
this.softMuteMap.put(playerID, newValue);
|
||||
this.saveSoftMutes();
|
||||
|
||||
return newValue;
|
||||
}
|
||||
|
||||
boolean isSoftMuted(UUID playerID)
|
||||
{
|
||||
Boolean mapEntry = this.softMuteMap.get(playerID);
|
||||
if(mapEntry == null || mapEntry == Boolean.FALSE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveSoftMutes()
|
||||
{
|
||||
BufferedWriter outStream = null;
|
||||
|
||||
try
|
||||
{
|
||||
//open the file and write the new value
|
||||
File softMuteFile = new File(softMuteFilePath);
|
||||
softMuteFile.createNewFile();
|
||||
outStream = new BufferedWriter(new FileWriter(softMuteFile));
|
||||
|
||||
for(Map.Entry<UUID, Boolean> entry : softMuteMap.entrySet())
|
||||
{
|
||||
if(entry.getValue().booleanValue())
|
||||
{
|
||||
outStream.write(entry.getKey().toString());
|
||||
outStream.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if any problem, log it
|
||||
catch(Exception e)
|
||||
{
|
||||
GriefPrevention.AddLogEntry("Unexpected exception saving soft mute data: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//close the file
|
||||
try
|
||||
{
|
||||
if(outStream != null) outStream.close();
|
||||
}
|
||||
catch(IOException exception) {}
|
||||
}
|
||||
|
||||
//removes cached player data from memory
|
||||
synchronized void clearCachedPlayerData(UUID playerID)
|
||||
{
|
||||
this.playerNameToPlayerDataMap.remove(playerID);
|
||||
|
|
@ -557,13 +674,15 @@ public abstract class DataStore
|
|||
//saves changes to player data to secondary storage. MUST be called after you're done making changes, otherwise a reload will lose them
|
||||
public void savePlayerDataSync(UUID playerID, PlayerData playerData)
|
||||
{
|
||||
//ensure player data is already read from file before trying to save
|
||||
playerData.getAccruedClaimBlocks();
|
||||
playerData.getClaims();
|
||||
this.asyncSavePlayerData(playerID, playerData);
|
||||
}
|
||||
|
||||
//saves changes to player data to secondary storage. MUST be called after you're done making changes, otherwise a reload will lose them
|
||||
public void savePlayerData(UUID playerID, PlayerData playerData)
|
||||
{
|
||||
//thread won't have access to read from files (silent failure - all readlines() return null)
|
||||
//ensure player data is already read from file before trying to save
|
||||
playerData.getAccruedClaimBlocks();
|
||||
playerData.getClaims();
|
||||
|
|
@ -1048,6 +1167,8 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.ClaimExplosivesAdvertisement, "To allow explosives to destroy blocks in this land claim, use /ClaimExplosions.", null);
|
||||
this.addDefault(defaults, Messages.PlayerInPvPSafeZone, "That player is in a PvP safe zone.", null);
|
||||
this.addDefault(defaults, Messages.NoPistonsOutsideClaims, "Warning: Pistons won't move blocks outside land claims.", null);
|
||||
this.addDefault(defaults, Messages.SoftMuted, "Soft-muted {0}.", "The changed player's name.");
|
||||
this.addDefault(defaults, Messages.UnSoftMuted, "Un-soft-muted {0}.", "The changed player's name.");
|
||||
|
||||
//load the config file
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
|
||||
|
|
|
|||
|
|
@ -1910,6 +1910,32 @@ public class GriefPrevention extends JavaPlugin
|
|||
GriefPrevention.sendMessage(defender, TextMode.Warn, Messages.SiegeAlert, attacker.getName());
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.SiegeConfirmed, defender.getName());
|
||||
}
|
||||
else if(cmd.getName().equalsIgnoreCase("softmute"))
|
||||
{
|
||||
//requires one parameter
|
||||
if(args.length != 1) return false;
|
||||
|
||||
//find the specified player
|
||||
OfflinePlayer targetPlayer = this.resolvePlayerByName(args[0], true);
|
||||
if(targetPlayer == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound);
|
||||
return true;
|
||||
}
|
||||
|
||||
//toggle mute for player
|
||||
boolean isMuted = this.dataStore.toggleSoftMute(targetPlayer.getUniqueId());
|
||||
if(isMuted)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.SoftMuted, targetPlayer.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.UnSoftMuted, targetPlayer.getName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ package me.ryanhamshire.GriefPrevention;
|
|||
|
||||
public enum Messages
|
||||
{
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionVideo, 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, CreativeBasicsVideo, SurvivalBasicsVideo, 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
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionVideo, 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, CreativeBasicsVideo, SurvivalBasicsVideo, 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.Calendar;
|
|||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
|
|
@ -92,7 +93,34 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
String message = event.getMessage();
|
||||
|
||||
event.setCancelled(this.handlePlayerChat(player, message, event));
|
||||
boolean muted = this.handlePlayerChat(player, message, event);
|
||||
Set<Player> recipients = event.getRecipients();
|
||||
|
||||
//muted messages go out to only the sender
|
||||
if(muted)
|
||||
{
|
||||
recipients.clear();
|
||||
recipients.add(player);
|
||||
}
|
||||
|
||||
//soft muted messages go out to all soft muted players
|
||||
else if(this.dataStore.isSoftMuted(player.getUniqueId()))
|
||||
{
|
||||
Set<Player> recipientsToKeep = new HashSet<Player>();
|
||||
for(Player recipient : recipients)
|
||||
{
|
||||
if(this.dataStore.isSoftMuted(recipient.getUniqueId()))
|
||||
{
|
||||
recipientsToKeep.add(recipient);
|
||||
}
|
||||
else if(recipient.hasPermission("griefprevention.eavesdrop"))
|
||||
{
|
||||
recipient.sendMessage("(Muted)" + player.getName() + ": " + message);
|
||||
}
|
||||
}
|
||||
recipients.clear();
|
||||
recipients.addAll(recipientsToKeep);
|
||||
}
|
||||
}
|
||||
|
||||
//last chat message shown, regardless of who sent it
|
||||
|
|
@ -292,10 +320,6 @@ class PlayerEventHandler implements Listener
|
|||
//make a log entry
|
||||
GriefPrevention.AddLogEntry("Muted spam from " + player.getName() + ": " + message);
|
||||
|
||||
//send a fake message so the player doesn't realize he's muted
|
||||
//less information for spammers = less effective spam filter dodging
|
||||
player.sendMessage("<" + player.getName() + "> " + message);
|
||||
|
||||
//cancelling the event guarantees other players don't receive the message
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user