Improve the way commutations, appeals, and clears work.
Specifically, commutations now create a new infraction, and all three set a repeal reason/issuer/type. This makes the system more flexible and makes for a better audit log.master
parent
ea101d5c07
commit
3570b7ddab
32
README.md
32
README.md
|
@ -31,9 +31,9 @@ This plugin provides tools which both help moderators track what rule infraction
|
|||
and help server administrators hold moderators accountable through an audit log.
|
||||
|
||||
This plugin provides these basic commands:
|
||||
* `/ban` and `/unban`
|
||||
* `/ban`
|
||||
* `/kick`
|
||||
* `/mute` and `/unmute`
|
||||
* `/mute`
|
||||
* `/warn`
|
||||
|
||||
All bans, kicks, mutes, and warnings are logged,
|
||||
|
@ -43,21 +43,24 @@ and to help server administrators hold moderators accountable through an audit l
|
|||
It is also possible to set the maximum length of bans or mutes that a moderator can issue
|
||||
in the configuration file.
|
||||
|
||||
You may view the currently active bans and mutes using `/bans` and `/mutes` respectively,
|
||||
or see the history of infractions a player has committed using `/infractions`.
|
||||
You may view the currently active sentences against any player,
|
||||
the infractions that a moderator has issued,
|
||||
or see the history of infractions a player has committed using `/infractions query`.
|
||||
This command does not include infractions that have been cleared from a player's record,
|
||||
or old versions of infractions from before they were commuted.
|
||||
|
||||
You can remove an infraction from a player's account using commands like `/unwarn`.
|
||||
Removing an infraction from a player's account will not remove the infraction from the audit log,
|
||||
and in fact will just add that the infraction was removed to the audit log.
|
||||
You can commute, extend, or update a sentence using `/infractions commute`,
|
||||
remove and clear an infraction from a player's record using `/infractions clear`
|
||||
or remove a sentence without clearing the infraction from the player's record using `/infractions appeal`.
|
||||
These commands do not remove the infraction from the audit log, and in fact create a new entry in the audit log.
|
||||
|
||||
You may view the audit log using `/auditlog`.
|
||||
The audit log includes infractions that have been cleared, appealed, or commuted,
|
||||
the history of those actions.
|
||||
|
||||
For more information on how to use these commands please see the in game `/help` or the `plugin.yml`
|
||||
For more information on how to configure this plugin, please see the default `config.yml`.
|
||||
|
||||
### Infraction histories & audit logs
|
||||
A set of moderator tools which logs all moderator actions,
|
||||
|
||||
### Manuals
|
||||
There are two built-in manuals: `/rules` and `/faq`.
|
||||
These manuals provide both brief overviews and more detail which players may view if they wish.
|
||||
|
@ -66,12 +69,3 @@ It is also possible for moderators to (forcibly) show players portions of the ru
|
|||
as a brief reminder of the rules or to quickly answer a question they were asking.
|
||||
|
||||
Please see the in-game `/help` menu or `plugin.yml` for more information on how to use these commands.
|
||||
|
||||
## Current Features
|
||||
* Tracks how many zombies or husks a player kills.
|
||||
* Supports a ranking system for players based on the U.S. Marines' ranks.
|
||||
|
||||
## Planned Features
|
||||
* Make zombies horde more intelligently.
|
||||
* Special world effects.
|
||||
* A lot of stuff, generally, but it's been a few months so I don't remember it all. I'll add it here when work begins again.
|
||||
|
|
|
@ -4,17 +4,13 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||
|
||||
import me.jamestmartin.wasteland.manual.ManualState;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandBan;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandBans;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandInfractions;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandKick;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandMute;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandMutes;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandUnban;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandUnmute;
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandWarn;
|
||||
import me.jamestmartin.wasteland.modtools.config.ModToolsConfig;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.log.CommandModLog;
|
||||
import me.jamestmartin.wasteland.modtools.log.CommandAuditLog;
|
||||
import me.jamestmartin.wasteland.offlineplayer.CommandLastSeen;
|
||||
import me.jamestmartin.wasteland.offlineplayer.CommandUUID;
|
||||
|
||||
|
@ -22,15 +18,11 @@ class ModToolsState {
|
|||
private final ManualState manualState;
|
||||
|
||||
private final CommandBan commandBan;
|
||||
private final CommandBans commandBans;
|
||||
private final CommandInfractions commandInfractions;
|
||||
private final CommandKick commandKick;
|
||||
private final CommandLastSeen commandLastSeen;
|
||||
private final CommandModLog commandModLog;
|
||||
private final CommandAuditLog commandAuditLog;
|
||||
private final CommandMute commandMute;
|
||||
private final CommandMutes commandMutes;
|
||||
private final CommandUnban commandUnban;
|
||||
private final CommandUnmute commandUnmute;
|
||||
private final CommandUUID commandUUID;
|
||||
private final CommandWarn commandWarn;
|
||||
|
||||
|
@ -41,15 +33,11 @@ class ModToolsState {
|
|||
InfractionStore store = null;
|
||||
|
||||
this.commandBan = new CommandBan(store, config.getDurations().getBansConfig());
|
||||
this.commandBans = new CommandBans();
|
||||
this.commandInfractions = new CommandInfractions();
|
||||
this.commandKick = new CommandKick(store);
|
||||
this.commandLastSeen = new CommandLastSeen();
|
||||
this.commandModLog = new CommandModLog();
|
||||
this.commandAuditLog = new CommandAuditLog();
|
||||
this.commandMute = new CommandMute(store, config.getDurations().getMutesConfig());
|
||||
this.commandMutes = new CommandMutes();
|
||||
this.commandUnban = new CommandUnban();
|
||||
this.commandUnmute = new CommandUnmute();
|
||||
this.commandUUID = new CommandUUID();
|
||||
this.commandWarn = new CommandWarn(store);
|
||||
}
|
||||
|
@ -58,15 +46,11 @@ class ModToolsState {
|
|||
manualState.register(plugin);
|
||||
|
||||
plugin.getCommand("ban").setExecutor(commandBan);
|
||||
plugin.getCommand("bans").setExecutor(commandBans);
|
||||
plugin.getCommand("infractions").setExecutor(commandInfractions);
|
||||
plugin.getCommand("kick").setExecutor(commandKick);
|
||||
plugin.getCommand("lastseen").setExecutor(commandLastSeen);
|
||||
plugin.getCommand("modlog").setExecutor(commandModLog);
|
||||
plugin.getCommand("auditlog").setExecutor(commandAuditLog);
|
||||
plugin.getCommand("mute").setExecutor(commandMute);
|
||||
plugin.getCommand("mutes").setExecutor(commandMutes);
|
||||
plugin.getCommand("unban").setExecutor(commandUnban);
|
||||
plugin.getCommand("unmute").setExecutor(commandUnmute);
|
||||
plugin.getCommand("uuid").setExecutor(commandUUID);
|
||||
plugin.getCommand("warn").setExecutor(commandWarn);
|
||||
}
|
||||
|
@ -79,7 +63,7 @@ class ModToolsState {
|
|||
plugin.getCommand("infractions").setExecutor(null);
|
||||
plugin.getCommand("kick").setExecutor(null);
|
||||
plugin.getCommand("lastseen").setExecutor(null);
|
||||
plugin.getCommand("modlog").setExecutor(null);
|
||||
plugin.getCommand("auditlog").setExecutor(null);
|
||||
plugin.getCommand("mute").setExecutor(null);
|
||||
plugin.getCommand("mutes").setExecutor(null);
|
||||
plugin.getCommand("unban").setExecutor(null);
|
||||
|
|
|
@ -4,9 +4,9 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.config.DurationsConfig;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.NewInfraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.SentenceType;
|
||||
|
||||
public class CommandBan extends CommandIssueInfraction {
|
||||
public CommandBan(InfractionStore store, DurationsConfig durations) {
|
||||
|
@ -14,12 +14,12 @@ public class CommandBan extends CommandIssueInfraction {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.BAN;
|
||||
protected SentenceType getType() {
|
||||
return SentenceType.BAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
protected void applyInfraction(CommandSender sender, NewInfraction infraction) {
|
||||
Player recipient = infraction.getRecipient().getPlayer();
|
||||
if (recipient != null) {
|
||||
recipient.kickPlayer(infraction.getMessage());
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandBans implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,9 +10,9 @@ import org.bukkit.entity.Player;
|
|||
|
||||
import me.jamestmartin.wasteland.modtools.config.DurationsConfig;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Duration;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.NewInfraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.SentenceType;
|
||||
|
||||
abstract class CommandIssueInfraction implements CommandExecutor {
|
||||
protected final InfractionStore store;
|
||||
|
@ -41,13 +41,13 @@ abstract class CommandIssueInfraction implements CommandExecutor {
|
|||
}
|
||||
|
||||
Player issuer = sender instanceof Player ? (Player) sender : null;
|
||||
Optional<Infraction> maybe = parseArgs(getType(), issuer, args);
|
||||
Optional<NewInfraction> maybe = parseArgs(getType(), issuer, args);
|
||||
if (maybe.isEmpty()) {
|
||||
// TOOD: better error messages
|
||||
sender.sendMessage("Invalid syntax.");
|
||||
return false;
|
||||
}
|
||||
Infraction infraction = maybe.get();
|
||||
NewInfraction infraction = maybe.get();
|
||||
|
||||
if (infraction.getDuration().compareTo(maxDuration) == 1) {
|
||||
sender.sendMessage("You are not allowed you issue an infraction of duration " + infraction.getDuration() + ".");
|
||||
|
@ -57,15 +57,15 @@ abstract class CommandIssueInfraction implements CommandExecutor {
|
|||
}
|
||||
|
||||
applyInfraction(sender, infraction);
|
||||
store.addInfraction(infraction);
|
||||
store.issueInfraction(infraction);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract InfractionType getType();
|
||||
protected abstract SentenceType getType();
|
||||
|
||||
protected abstract void applyInfraction(CommandSender sender, Infraction infraction);
|
||||
protected abstract void applyInfraction(CommandSender sender, NewInfraction infraction);
|
||||
|
||||
private static Optional<Infraction> parseArgs(InfractionType type, OfflinePlayer issuer, String[] args) {
|
||||
private static Optional<NewInfraction> parseArgs(SentenceType type, OfflinePlayer issuer, String[] args) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package me.jamestmartin.wasteland.modtools.commands;
|
|||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.NewInfraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.SentenceType;
|
||||
|
||||
public class CommandKick extends CommandIssueInfraction {
|
||||
public CommandKick(InfractionStore store) {
|
||||
|
@ -13,12 +13,12 @@ public class CommandKick extends CommandIssueInfraction {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.KICK;
|
||||
protected SentenceType getType() {
|
||||
return SentenceType.KICK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
protected void applyInfraction(CommandSender sender, NewInfraction infraction) {
|
||||
Player player = infraction.getRecipient().getPlayer();
|
||||
if (player == null) {
|
||||
sender.sendMessage("That player is not online!");
|
||||
|
|
|
@ -4,9 +4,9 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.config.DurationsConfig;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.NewInfraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.SentenceType;
|
||||
|
||||
public class CommandMute extends CommandIssueInfraction {
|
||||
public CommandMute(InfractionStore store, DurationsConfig durations) {
|
||||
|
@ -14,12 +14,12 @@ public class CommandMute extends CommandIssueInfraction {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.MUTE;
|
||||
protected SentenceType getType() {
|
||||
return SentenceType.MUTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
protected void applyInfraction(CommandSender sender, NewInfraction infraction) {
|
||||
Player player = infraction.getRecipient().getPlayer();
|
||||
if (player != null) {
|
||||
player.sendMessage(infraction.getMessage());
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandMutes implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
|
||||
public abstract class CommandRemoveInfraction implements CommandExecutor {
|
||||
protected final InfractionStore store;
|
||||
|
||||
public CommandRemoveInfraction(InfractionStore store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
Player issuer = sender instanceof Player ? (Player) sender : null;
|
||||
Optional<Infraction> maybe = parseArgs(getType(), issuer, args);
|
||||
if (maybe.isEmpty()) {
|
||||
// TOOD: better error messages
|
||||
sender.sendMessage("Invalid syntax.");
|
||||
return false;
|
||||
}
|
||||
Infraction infraction = maybe.get();
|
||||
|
||||
applyInfraction(sender, infraction);
|
||||
store.addInfraction(infraction);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract InfractionType getType();
|
||||
|
||||
protected abstract void applyInfraction(CommandSender sender, Infraction infraction);
|
||||
|
||||
private static Optional<Infraction> parseArgs(InfractionType type, OfflinePlayer issuer, String[] args) {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandUnban implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandUnmute implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,9 +3,9 @@ package me.jamestmartin.wasteland.modtools.commands;
|
|||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.NewInfraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.SentenceType;
|
||||
|
||||
public class CommandWarn extends CommandIssueInfraction {
|
||||
public CommandWarn(InfractionStore store) {
|
||||
|
@ -13,12 +13,12 @@ public class CommandWarn extends CommandIssueInfraction {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.WARN;
|
||||
protected SentenceType getType() {
|
||||
return SentenceType.WARN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
protected void applyInfraction(CommandSender sender, NewInfraction infraction) {
|
||||
Player player = infraction.getRecipient().getPlayer();
|
||||
if (player != null) {
|
||||
player.sendMessage(infraction.getMessage());
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
@ -170,4 +171,15 @@ public class Duration implements Comparable<Duration> {
|
|||
|
||||
return Long.compare(getSeconds().get(), other.getSeconds().get());
|
||||
}
|
||||
|
||||
public static Duration fromDates(Date begin, Date end) {
|
||||
return new Duration(end.getTime() - begin.getTime());
|
||||
}
|
||||
|
||||
public static Duration fromDates(Date begin, Optional<Date> end) {
|
||||
if (end.isEmpty()) {
|
||||
return INFINITY;
|
||||
}
|
||||
return fromDates(begin, end.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,56 +1,139 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class Infraction {
|
||||
private final InfractionType type;
|
||||
private final OfflinePlayer issuer;
|
||||
/** The unique identifier of this infraction. */
|
||||
private final int id;
|
||||
/** The type of sentence the player received: ban, kick, mute, or warning. */
|
||||
private final SentenceType type;
|
||||
/** The moderator who issued the sentence. (Or empty, if it was issued by the console.) */
|
||||
private final Optional<OfflinePlayer> issuer;
|
||||
/** The player who committed the infraction. */
|
||||
private final OfflinePlayer recipient;
|
||||
/** The time that the sentence was issued. */
|
||||
private final Date issued;
|
||||
private final Duration duration;
|
||||
/** The time that the sentence takes effect. */
|
||||
private final Date start;
|
||||
/** The time that the sentence naturally expires, if ever. */
|
||||
private final Optional<Date> expiry;
|
||||
/** The information about this infraction's repeal, if it was repealed. */
|
||||
private final Optional<Repeal> repeal;
|
||||
/** If this sentence was commuted, the identifier for the original infraction. */
|
||||
private final Optional<Integer> original;
|
||||
/** The section identifier for the rule that was violated. */
|
||||
private final String rule;
|
||||
/** The reason that an infraction was issued. */
|
||||
private final String reason;
|
||||
|
||||
public Infraction(InfractionType type, OfflinePlayer issuer, OfflinePlayer recipient, Date issued, Duration duration, String rule, String reason) {
|
||||
public Infraction(
|
||||
int id,
|
||||
SentenceType type,
|
||||
Optional<OfflinePlayer> issuer,
|
||||
OfflinePlayer recipient,
|
||||
Date issued,
|
||||
Date start,
|
||||
Optional<Date> expiry,
|
||||
Optional<Repeal> repeal,
|
||||
Optional<Integer> original,
|
||||
String rule,
|
||||
String reason
|
||||
) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.issuer = issuer;
|
||||
this.recipient = recipient;
|
||||
this.issued = issued;
|
||||
this.duration = duration;
|
||||
this.start = start;
|
||||
this.expiry = expiry;
|
||||
this.repeal = repeal;
|
||||
this.original = original;
|
||||
this.rule = rule;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public InfractionType getType() {
|
||||
/** @return The unique identifier for this infraction. */
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** @return The {@link SentenceType type of sentence} the player received: ban, kick, mute, or warning. */
|
||||
public SentenceType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public OfflinePlayer getIssuer() {
|
||||
/** @return The moderator who issued the sentence. (Or empty, if it was issued by the console.) */
|
||||
public Optional<OfflinePlayer> getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
|
||||
/** @return The player who committed the infraction. */
|
||||
public OfflinePlayer getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
/** @return The time the sentence was issued. */
|
||||
public Date getIssued() {
|
||||
return issued;
|
||||
}
|
||||
|
||||
public Duration getDuration() {
|
||||
return duration;
|
||||
/**
|
||||
* @return
|
||||
* <p>The time that the sentence first takes effect.
|
||||
* <p>
|
||||
* Generally, this will be the same time that it was issued;
|
||||
* however, if a sentence is commuted, the new infraction starts at the same time,
|
||||
* but will actually have a time issued *after* the sentence started!
|
||||
*/
|
||||
public Date getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/** @return The time the infraction naturally expires if not repealed, if ever. */
|
||||
public Optional<Date> getExpiry() {
|
||||
return expiry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The duration that the sentence would last if not repealed.
|
||||
* @see #getActualDuration()
|
||||
*/
|
||||
public Duration getOriginalDuration() {
|
||||
return Duration.fromDates(getStart(), getExpiry());
|
||||
}
|
||||
|
||||
/** @return The information about this infraction's repeal, if it was repealed. */
|
||||
public Optional<Repeal> getRepeal() {
|
||||
return repeal;
|
||||
}
|
||||
|
||||
/** @return If this sentence was commuted, the identifier for the original infraction. */
|
||||
public Optional<Integer> getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The duration the sentence would last if it has been repealed, or otherwise the original duration.
|
||||
* @see #getOriginalDuration()
|
||||
*/
|
||||
public Duration getActualDuration() {
|
||||
return Duration.fromDates(getStart(), getRepeal().map(Repeal::getIssued).or(() -> getExpiry()));
|
||||
}
|
||||
|
||||
/** @return The rule that was violated. */
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
/** @return The reason that the infraction was issued. */
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
/** @return The message that the player will get sent with information about their sentence. */
|
||||
public String getMessage() {
|
||||
// TODO
|
||||
return null;
|
||||
|
|
|
@ -5,21 +5,42 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
|
||||
public interface InfractionProvider {
|
||||
Set<Infraction> getActiveInfractions(Optional<UUID> player, Optional<InfractionType> type);
|
||||
/**
|
||||
* @param player The player who committed the infractions, or any player.
|
||||
* @param type The type of sentence given, or any sentence type.
|
||||
* @return The un-expired, un-repealed sentences matching the provide criteria.
|
||||
*/
|
||||
Set<Infraction> getActiveInfractions(Optional<UUID> player, Optional<SentenceType> type);
|
||||
|
||||
/** @return All un-expired, un-repealed sentences. */
|
||||
default Set<Infraction> getActiveInfractions() {
|
||||
return getActiveInfractions(Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player The player who committed the infractions.
|
||||
* @return The player's un-expired, un-repealed sentences.
|
||||
*/
|
||||
default Set<Infraction> getActiveInfractions(UUID player) {
|
||||
return getActiveInfractions(Optional.of(player), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getActiveInfractions(UUID player, InfractionType type) {
|
||||
/**
|
||||
* @param player The player who committed the infractions.
|
||||
* @param type The type of sentence given.
|
||||
* @return The player's un-expired, un-repealed sentences of the given type.
|
||||
*/
|
||||
default Set<Infraction> getActiveInfractions(UUID player, SentenceType type) {
|
||||
return getActiveInfractions(Optional.of(player), Optional.of(type));
|
||||
}
|
||||
|
||||
default Set<Infraction> getActiveInfractions(InfractionType type) {
|
||||
/**
|
||||
* @param type The type of sentence given.
|
||||
* @return All un-expired, un-repealed sentences of the given type.
|
||||
*/
|
||||
default Set<Infraction> getActiveInfractions(SentenceType type) {
|
||||
return getActiveInfractions(Optional.empty(), Optional.of(type));
|
||||
}
|
||||
|
||||
// TODO: Provide *in*active infractions which were never cleared.
|
||||
}
|
||||
|
|
|
@ -1,8 +1,36 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface InfractionStore extends InfractionProvider {
|
||||
void addInfraction(Infraction infraction);
|
||||
void removeInfractions(OfflinePlayer player, InfractionType type);
|
||||
/**
|
||||
* @param infraction The new infraction to add to the database.
|
||||
* @see NewInfraction#NewInfraction(SentenceType, java.util.Optional, OfflinePlayer, Duration, String, String) Create a new infraction.
|
||||
* @see NewInfraction#NewInfraction(java.util.Optional, Duration, Infraction) Commute an old infraction.
|
||||
* @see NewInfraction#NewInfraction(SentenceType, java.util.Optional, OfflinePlayer, java.util.Optional, Duration, java.util.Optional, String, String) Update an old infraction.
|
||||
*/
|
||||
void issueInfraction(NewInfraction infraction);
|
||||
|
||||
/**
|
||||
* <p>Clear a previously-issued infraction.
|
||||
* <p>This will clear the infraction from the player's record, but not from the audit log.
|
||||
* @param id The identifier of the infraction to clear.
|
||||
* @param issuer The moderator who cleared the infraction.
|
||||
* @see RepealType#CLEARED
|
||||
* @see #appealInfraction(OfflinePlayer, SentenceType)
|
||||
*/
|
||||
void clearInfraction(int id, Optional<Player> issuer);
|
||||
|
||||
/**
|
||||
* <p>Accept an appeal for a previously-issued infraction.
|
||||
* <p>This will remove the sentence from the player, but not remove it from their record.
|
||||
* @param id The identifier of the infraction which was appealed.
|
||||
* @param issuer The moderator who accepted the appeal.
|
||||
* @see RepealType#APPEALED
|
||||
* @see #clearInfraction(int, Optional)
|
||||
*/
|
||||
void appealInfraction(int id, Optional<Player> issuer);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class NewInfraction {
|
||||
/** The type of sentence the player received: ban, kick, mute, or warning. */
|
||||
private final SentenceType type;
|
||||
/** The moderator who issued the sentence. (Or empty, if it was issued by the console.) */
|
||||
private final Optional<OfflinePlayer> issuer;
|
||||
/** The player who committed the infraction. */
|
||||
private final OfflinePlayer recipient;
|
||||
/** The time that the sentence takes effect, or empty if it starts immediately. */
|
||||
private final Optional<Date> start;
|
||||
/** The duration of the sentence. */
|
||||
private final Duration duration;
|
||||
/** If this sentence was commuted, the identifier for the original infraction. */
|
||||
private final Optional<Integer> original;
|
||||
/** The section identifier for the rule that was violated. */
|
||||
private final String rule;
|
||||
/** The reason that an infraction was issued. */
|
||||
private final String reason;
|
||||
|
||||
public NewInfraction(
|
||||
SentenceType type,
|
||||
Optional<OfflinePlayer> issuer,
|
||||
OfflinePlayer recipient,
|
||||
Optional<Date> start,
|
||||
Duration duration,
|
||||
Optional<Integer> original,
|
||||
String rule,
|
||||
String reason
|
||||
) {
|
||||
this.type = type;
|
||||
this.issuer = issuer;
|
||||
this.recipient = recipient;
|
||||
this.start = start;
|
||||
this.duration = duration;
|
||||
this.original = original;
|
||||
this.rule = rule;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public NewInfraction(
|
||||
SentenceType type,
|
||||
Optional<OfflinePlayer> issuer,
|
||||
OfflinePlayer recipient,
|
||||
Duration duration,
|
||||
String rule,
|
||||
String reason
|
||||
) {
|
||||
this.type = type;
|
||||
this.issuer = issuer;
|
||||
this.recipient = recipient;
|
||||
this.start = Optional.empty();
|
||||
this.duration = duration;
|
||||
this.original = Optional.empty();
|
||||
this.rule = rule;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
/** Update an old infraction with a new expiry. */
|
||||
public NewInfraction(
|
||||
Optional<OfflinePlayer> issuer,
|
||||
Duration duration,
|
||||
Infraction original
|
||||
) {
|
||||
this.type = original.getType();
|
||||
this.issuer = issuer;
|
||||
this.recipient = original.getRecipient();
|
||||
this.start = Optional.of(original.getStart());
|
||||
this.duration = duration;
|
||||
this.original = Optional.of(original.getId());
|
||||
this.rule = original.getRule();
|
||||
this.reason = original.getReason();
|
||||
}
|
||||
|
||||
/** Update an old infraction with a new expiry and reason. */
|
||||
public NewInfraction(
|
||||
Optional<OfflinePlayer> issuer,
|
||||
Duration duration,
|
||||
Infraction original,
|
||||
String rule,
|
||||
String reason
|
||||
) {
|
||||
this.type = original.getType();
|
||||
this.issuer = issuer;
|
||||
this.recipient = original.getRecipient();
|
||||
this.start = Optional.of(original.getStart());
|
||||
this.duration = duration;
|
||||
this.original = Optional.of(original.getId());
|
||||
this.rule = rule;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
/** @return The {@link SentenceType type of sentence} the player received: ban, kick, mute, or warning. */
|
||||
public SentenceType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/** @return The moderator who issued the sentence. (Or empty, if it was issued by the console.) */
|
||||
public Optional<OfflinePlayer> getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
/** @return The player who committed the infraction. */
|
||||
public OfflinePlayer getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The time that the sentence first takes effect, or empty if it starts immediately.
|
||||
*/
|
||||
public Optional<Date> getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/** @return The time the infraction naturally expires if not repealed, if ever. */
|
||||
public Duration getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/** @return If this sentence was commuted, the identifier for the original infraction. */
|
||||
public Optional<Integer> getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
/** @return The rule that was violated. */
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
/** @return The reason that the infraction was issued. */
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
/** @return The message that the player will get sent with information about their sentence. */
|
||||
public String getMessage() {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class Repeal {
|
||||
private final RepealType type;
|
||||
private final Optional<OfflinePlayer> issuer;
|
||||
private final Date issued;
|
||||
|
||||
public Repeal(RepealType type, Optional<OfflinePlayer> issuer, Date issued) {
|
||||
this.type = type;
|
||||
this.issuer = issuer;
|
||||
this.issued = issued;
|
||||
}
|
||||
|
||||
/** The way in which the infraction was repealed. */
|
||||
public RepealType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/** The player who issued the repeal. */
|
||||
public Optional<OfflinePlayer> getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
/** The time the repeal was issued. */
|
||||
public Date getIssued() {
|
||||
return issued;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
/** The way in which which an infraction was removed. */
|
||||
public enum RepealType {
|
||||
/** The player was cleared of wrongdoing, and this infraction will be removed from their record. */
|
||||
CLEARED,
|
||||
/** The player's sentence was reduced, and replaced with another infraction. */
|
||||
COMMUTED,
|
||||
/** The player's sentence was removed based on appeal, but the infraction will remain on their record. */
|
||||
APPEALED;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
public enum InfractionType {
|
||||
public enum SentenceType {
|
||||
BAN(true),
|
||||
KICK(false),
|
||||
MUTE(true),
|
||||
|
@ -8,7 +8,7 @@ public enum InfractionType {
|
|||
|
||||
private final boolean hasduration;
|
||||
|
||||
private InfractionType(boolean hasDuration) {
|
||||
private SentenceType(boolean hasDuration) {
|
||||
this.hasduration = hasDuration;
|
||||
}
|
||||
|
|
@ -6,37 +6,60 @@ import java.util.UUID;
|
|||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Duration;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.SentenceType;
|
||||
|
||||
public interface ModLogProvider {
|
||||
public interface AuditLogProvider {
|
||||
/**
|
||||
* @param duration The maximum time ago that an infraction was issued or repealed.
|
||||
* @param issuer The moderator who issued an infraction.
|
||||
* @param recipient The player who committed the infraction.
|
||||
* @param type The type of sentence issued.
|
||||
* @return All infractions that were issued or repealed fitting the provided criteria.
|
||||
*/
|
||||
Set<Infraction> getInfractions(
|
||||
Duration duration,
|
||||
Optional<UUID> issuer,
|
||||
Optional<UUID> recipient,
|
||||
Optional<InfractionType> type
|
||||
Optional<SentenceType> type
|
||||
);
|
||||
|
||||
/** All infractions that have ever been issued. */
|
||||
default Set<Infraction> getInfractions() {
|
||||
return getInfractions(Duration.INFINITY);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractions(InfractionType type) {
|
||||
/**
|
||||
* @param type The type of sentence issued.
|
||||
* @return All sentences of the given type that have ever been issued.
|
||||
*/
|
||||
default Set<Infraction> getInfractions(SentenceType type) {
|
||||
return getInfractions(Duration.INFINITY, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param duration The maximum time ago that an infraction was issued or repealed.
|
||||
* @return All sentences that have ever been issued or repealed within the duration provided.
|
||||
*/
|
||||
default Set<Infraction> getInfractions(Duration duration) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractions(Duration duration, InfractionType type) {
|
||||
/**
|
||||
* @param duration The maximum time ago that an infraction was issued or repealed.
|
||||
* @param type The type of sentence issued.
|
||||
* @return All sentences of the given type that have ever been issued or repealed within the duration provided.
|
||||
*/
|
||||
default Set<Infraction> getInfractions(Duration duration, SentenceType type) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.empty(), Optional.of(type));
|
||||
}
|
||||
|
||||
// TODO: Javadoc for all these variants.
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(UUID player) {
|
||||
return getInfractionsIssuedTo(Duration.INFINITY, player);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(UUID player, InfractionType type) {
|
||||
default Set<Infraction> getInfractionsIssuedTo(UUID player, SentenceType type) {
|
||||
return getInfractionsIssuedTo(Duration.INFINITY, player, type);
|
||||
}
|
||||
|
||||
|
@ -44,7 +67,7 @@ public interface ModLogProvider {
|
|||
return getInfractions(duration, Optional.empty(), Optional.of(player), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(Duration duration, UUID player, InfractionType type) {
|
||||
default Set<Infraction> getInfractionsIssuedTo(Duration duration, UUID player, SentenceType type) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.of(player), Optional.of(type));
|
||||
}
|
||||
|
||||
|
@ -52,7 +75,7 @@ public interface ModLogProvider {
|
|||
return getInfractionsIssuedBy(Duration.INFINITY, player);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedBy(UUID player, InfractionType type) {
|
||||
default Set<Infraction> getInfractionsIssuedBy(UUID player, SentenceType type) {
|
||||
return getInfractionsIssuedBy(Duration.INFINITY, player, type);
|
||||
}
|
||||
|
||||
|
@ -60,8 +83,7 @@ public interface ModLogProvider {
|
|||
return getInfractions(duration, Optional.of(player), Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedBy(Duration duration, UUID player, InfractionType type) {
|
||||
default Set<Infraction> getInfractionsIssuedBy(Duration duration, UUID player, SentenceType type) {
|
||||
return getInfractions(duration, Optional.of(player), Optional.empty(), Optional.of(type));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package me.jamestmartin.wasteland.modtools.log;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionStore;
|
||||
|
||||
public interface ModLogStore extends ModLogProvider {
|
||||
public interface AuditLogStore extends AuditLogProvider, InfractionStore {
|
||||
void addInfraction(Infraction infraction);
|
||||
}
|
|
@ -4,7 +4,7 @@ import org.bukkit.command.Command;
|
|||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandModLog implements CommandExecutor {
|
||||
public class CommandAuditLog implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
@ -5,14 +5,19 @@ version: 0.1.0
|
|||
api-version: 1.16
|
||||
|
||||
commands:
|
||||
modlog:
|
||||
auditlog:
|
||||
description: See the list of recent actions taken by moderators.
|
||||
usage: "Usage: /<command> [<duration>]"
|
||||
permission: wasteland.modtools.log
|
||||
permission-message: You do not have permission to view the moderator log.
|
||||
permission-message: You do not have permission to view the aduit log.
|
||||
infractions:
|
||||
description: See the list of infractions against the rules a player has committed.
|
||||
usage: "Usage: /<infractions> <player> [<duration>]"
|
||||
usage: |
|
||||
Usage:
|
||||
/<command> query <player> [<duration>]
|
||||
/<command> commute <id> <duration> [<rule>] [<reason> ...]
|
||||
/<command> clear <id>
|
||||
/<command> appeal <id>
|
||||
permission: wasteland.modtools.infractions
|
||||
permission-message: You do not have permission to view players' infractions against the rules.
|
||||
|
||||
|
@ -43,16 +48,6 @@ commands:
|
|||
usage: "Usage: /<command> <player> <duration> [<rule>] [<reason> ...]"
|
||||
permission: wasteland.modtools.ban.issue
|
||||
permission-message: You do not have permission to ban players.
|
||||
unban:
|
||||
description: Unban a player, allowing them to join again.
|
||||
usage: "Usage: /<command> <player> [<reason> ...]"
|
||||
permission: wasteland.modtools.ban.pardon
|
||||
permission-message: You do not have permission to unban players.
|
||||
bans:
|
||||
description: See the list of all players currently banned from the server.
|
||||
usage: "Usage: /<command> [<player>]"
|
||||
permission: wasteland.modtools.ban.list
|
||||
permission-message: You do not have permission to list banned players.
|
||||
|
||||
kick:
|
||||
description: Kick a player from the server.
|
||||
|
@ -65,16 +60,6 @@ commands:
|
|||
usage: "Usage: /<command> <player> <duration> [<rule>] [<reason> ...]"
|
||||
permission: wasteland.modtools.mute.issue
|
||||
permission-message: You do not have permission to mute players.
|
||||
unmute:
|
||||
description: Unmute a player, allowing them to talk again.
|
||||
usage: "Usage: /<command> <player> [<reason> ...]"
|
||||
permission: wasteland.modtools.mute.pardon
|
||||
permission-message: You do not have permission to unmute players.
|
||||
mutes:
|
||||
description: See the list of all players currently muted on the server.
|
||||
usage: "Usage: /<command> [<player>]"
|
||||
permission: wasteland.modtools.mutes.list
|
||||
permission-message: You do not have permission to list muted players.
|
||||
|
||||
warn:
|
||||
description: Give a player an official (logged) warning.
|
||||
|
@ -97,12 +82,12 @@ permissions:
|
|||
default: op
|
||||
children:
|
||||
wasteland.modtools.infractions: true
|
||||
wasteland.modtools.ban.list: true
|
||||
wasteland.modtools.mute.list: true
|
||||
wasteland.modtools.warn.list: true
|
||||
wasteland.modtools.infractions:
|
||||
description: Allows you to see the list of infractions against the rules a player has committed.
|
||||
default: op
|
||||
wasteland.modtools.infractions.clear:
|
||||
description: Allows you to clear infractions from players' permanent records.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.uuid:
|
||||
description: Allows you to see the UUIDs of players with a given name on this server.
|
||||
|
@ -151,20 +136,16 @@ permissions:
|
|||
wasteland.manual.faq: true
|
||||
|
||||
wasteland.modtools.ban:
|
||||
description: Allows you to ban or unban a player, or list active bans.
|
||||
description: Allows you to ban or unban a player.
|
||||
default: op
|
||||
children:
|
||||
wasteland.modtools.ban.issue: true
|
||||
wasteland.modtools.ban.list: true
|
||||
wasteland.modtools.ban.pardon: true
|
||||
wasteland.modtools.ban.issue:
|
||||
description: Allows you to issue bans.
|
||||
default: op
|
||||
wasteland.modtools.ban.list:
|
||||
description: Allows you to list all active bans.
|
||||
default: op
|
||||
wasteland.modtools.ban.pardon:
|
||||
description: Allows you to remove bans.
|
||||
wasteland.modtools.ban.commute:
|
||||
description: Allows you to commute bans.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.kick:
|
||||
|
@ -172,20 +153,15 @@ permissions:
|
|||
default: op
|
||||
|
||||
wasteland.modtools.mute:
|
||||
description: Allows you to mute or unmute a player, or list active mutes.
|
||||
default: op
|
||||
description: Allows you to mute or unmute a player.
|
||||
children:
|
||||
wasteland.modtools.mute.issue: true
|
||||
wasteland.modtools.mute.list: true
|
||||
wasteland.modtools.mute.pardon: true
|
||||
wasteland.modtools.mute.issue:
|
||||
description: Allows you to issue mutes.
|
||||
default: op
|
||||
wasteland.modtools.mute.list:
|
||||
description: Allows you to list active mutes.
|
||||
default: op
|
||||
wasteland.modtools.mute.pardon:
|
||||
description: Allows you to remove mutes.
|
||||
wasteland.modtools.mute.commute:
|
||||
description: Allows you to commute mutes.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.warn:
|
||||
|
|
Loading…
Reference in New Issue