Committing incomplete work on the WIP WastelandModTools.
parent
e4ec1995da
commit
f7f37a18f8
|
@ -0,0 +1,25 @@
|
|||
plugins {
|
||||
id 'java-library'
|
||||
}
|
||||
|
||||
group 'me.jamestmartin'
|
||||
version '0.1.0'
|
||||
|
||||
sourceCompatibility = 8
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' }
|
||||
maven {
|
||||
url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
|
||||
|
||||
content {
|
||||
includeGroup 'org.bukkit'
|
||||
includeGroup 'org.spigotmc'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
|
||||
}
|
|
@ -6,6 +6,8 @@ import org.bukkit.command.Command;
|
|||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import me.jamestmartin.wasteland.manual.config.ManualSection;
|
||||
|
||||
public class CommandManual implements CommandExecutor {
|
||||
private final String manualName;
|
||||
private final ManualSection manual;
|
|
@ -2,9 +2,9 @@ package me.jamestmartin.wasteland.manual;
|
|||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import me.jamestmartin.wasteland.Substate;
|
||||
import me.jamestmartin.wasteland.manual.config.ManualConfig;
|
||||
|
||||
public class ManualState implements Substate {
|
||||
public class ManualState {
|
||||
private final CommandManual commandRules;
|
||||
private final CommandManual commandFaq;
|
||||
|
||||
|
@ -13,13 +13,11 @@ public class ManualState implements Substate {
|
|||
this.commandFaq = new CommandManual("faq", config.getFaq());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(JavaPlugin plugin) {
|
||||
plugin.getCommand("rules").setExecutor(commandRules);
|
||||
plugin.getCommand("faq").setExecutor(commandFaq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(JavaPlugin plugin) {
|
||||
plugin.getCommand("rules").setExecutor(null);
|
||||
plugin.getCommand("faq").setExecutor(null);
|
|
@ -1,4 +1,4 @@
|
|||
package me.jamestmartin.wasteland.manual;
|
||||
package me.jamestmartin.wasteland.manual.config;
|
||||
|
||||
public class ManualConfig {
|
||||
private final ManualSection rules;
|
|
@ -0,0 +1,49 @@
|
|||
package me.jamestmartin.wasteland.manual.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
public class ManualConfigParser {
|
||||
public static ManualConfig parse(ConfigurationSection c) {
|
||||
ManualSection rules = new ManualSection(
|
||||
"The Server Rules",
|
||||
parseManualSectionList(castToSectionList(c.getMapList("rules"))));
|
||||
ManualSection faq = new ManualSection(
|
||||
"Frequently Asked Questions",
|
||||
parseManualSectionList(castToSectionList(c.getMapList("faq"))));
|
||||
return new ManualConfig(rules, faq);
|
||||
}
|
||||
|
||||
private static ManualSection parseManualSection(Map<?, ?> c) {
|
||||
String summary = (String) c.get("summary");
|
||||
Optional<String> details = Optional.ofNullable((String) c.get("details"));
|
||||
List<ManualSection> subsections = parseManualSectionList(castToSectionList(c.get("sections")));
|
||||
|
||||
return new ManualSection(summary, details, subsections);
|
||||
}
|
||||
|
||||
private static List<Map<?, ?>> castToSectionList(Object x) {
|
||||
if (x == null) {
|
||||
return null;
|
||||
}
|
||||
return ((List<?>) x).stream().map(xx -> (Map<?, ?>) xx).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
|
||||
public static List<ManualSection> parseManualSectionList(List<Map<?, ?>> list) {
|
||||
List<ManualSection> sections = new ArrayList<>();
|
||||
if (list == null) {
|
||||
return sections;
|
||||
}
|
||||
|
||||
for (Map<?, ?> section : list) {
|
||||
sections.add(parseManualSection(section));
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package me.jamestmartin.wasteland.manual;
|
||||
package me.jamestmartin.wasteland.manual.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
|
@ -0,0 +1,96 @@
|
|||
package me.jamestmartin.wasteland.modtools;
|
||||
|
||||
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.offlineplayer.CommandLastSeen;
|
||||
import me.jamestmartin.wasteland.offlineplayer.CommandUUID;
|
||||
|
||||
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 CommandMute commandMute;
|
||||
private final CommandMutes commandMutes;
|
||||
private final CommandUnban commandUnban;
|
||||
private final CommandUnmute commandUnmute;
|
||||
private final CommandUUID commandUUID;
|
||||
private final CommandWarn commandWarn;
|
||||
|
||||
public ModToolsState(ModToolsConfig config) {
|
||||
this.manualState = new ManualState(config.getManuals());
|
||||
|
||||
// TODO
|
||||
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.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);
|
||||
}
|
||||
|
||||
public void register(JavaPlugin plugin) {
|
||||
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("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);
|
||||
}
|
||||
|
||||
public void unregister(JavaPlugin plugin) {
|
||||
manualState.unregister(plugin);
|
||||
|
||||
plugin.getCommand("ban").setExecutor(null);
|
||||
plugin.getCommand("bans").setExecutor(null);
|
||||
plugin.getCommand("infractions").setExecutor(null);
|
||||
plugin.getCommand("kick").setExecutor(null);
|
||||
plugin.getCommand("lastseen").setExecutor(null);
|
||||
plugin.getCommand("modlog").setExecutor(null);
|
||||
plugin.getCommand("mute").setExecutor(null);
|
||||
plugin.getCommand("mutes").setExecutor(null);
|
||||
plugin.getCommand("unban").setExecutor(null);
|
||||
plugin.getCommand("unmute").setExecutor(null);
|
||||
plugin.getCommand("uuid").setExecutor(null);
|
||||
plugin.getCommand("warn").setExecutor(null);
|
||||
|
||||
disable(plugin);
|
||||
}
|
||||
|
||||
public void disable(JavaPlugin plugin) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package me.jamestmartin.wasteland.modtools;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.commands.CommandWMT;
|
||||
import me.jamestmartin.wasteland.modtools.config.ConfigParser;
|
||||
|
||||
public class WastelandModTools extends JavaPlugin {
|
||||
private static WastelandModTools instance;
|
||||
|
||||
private ModToolsState state;
|
||||
|
||||
public static WastelandModTools getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
saveDefaultConfig();
|
||||
load();
|
||||
|
||||
// This command doesn't depend on any config,
|
||||
// so we don't need to register/unregister it when we reload.
|
||||
getCommand("wmt").setExecutor(new CommandWMT(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
state.disable(this);
|
||||
instance = null;
|
||||
}
|
||||
|
||||
private void load() {
|
||||
state = new ModToolsState(ConfigParser.parse(getConfig()));
|
||||
state.register(this);
|
||||
}
|
||||
|
||||
private void unload() {
|
||||
state.unregister(this);
|
||||
state = null;
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
getLogger().info("Reloading...");
|
||||
saveDefaultConfig();
|
||||
reloadConfig();
|
||||
unload();
|
||||
load();
|
||||
getLogger().info("Done.");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
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;
|
||||
|
||||
public class CommandBan extends CommandIssueInfraction {
|
||||
public CommandBan(InfractionStore store, DurationsConfig durations) {
|
||||
super(store, durations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.BAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
Player recipient = infraction.getRecipient().getPlayer();
|
||||
if (recipient != null) {
|
||||
recipient.kickPlayer(infraction.getMessage());
|
||||
}
|
||||
sender.sendMessage(infraction.getRecipient().getName() + " has been banned for " + infraction.getDuration().toStringLong() + ".");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandInfractions implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
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.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;
|
||||
|
||||
abstract class CommandIssueInfraction implements CommandExecutor {
|
||||
protected final InfractionStore store;
|
||||
protected final DurationsConfig durations;
|
||||
|
||||
public CommandIssueInfraction(InfractionStore store, DurationsConfig durations) {
|
||||
this.store = store;
|
||||
this.durations = durations;
|
||||
}
|
||||
|
||||
public CommandIssueInfraction(InfractionStore store) {
|
||||
if (getType().hasDuration()) {
|
||||
throw new IllegalArgumentException("Must pass durations for infraction type which has duration");
|
||||
}
|
||||
this.store = store;
|
||||
this.durations = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
Duration maxDuration = durations != null ? durations.getMaximumBanDuration(sender) : Duration.INFINITY;
|
||||
if (maxDuration.getSeconds().map(x -> x == 0).orElse(false)) {
|
||||
sender.sendMessage("You have permission to issue infractions, but can only issue infractions of duration 0!");
|
||||
sender.sendMessage("No infraction will be issued.");
|
||||
return true;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (infraction.getDuration().compareTo(maxDuration) == 1) {
|
||||
sender.sendMessage("You are not allowed you issue an infraction of duration " + infraction.getDuration() + ".");
|
||||
sender.sendMessage("The maximum infraction duration you can issue is " + maxDuration + ".");
|
||||
sender.sendMessage("No infraction will be issued.");
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
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.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
|
||||
public class CommandKick extends CommandIssueInfraction {
|
||||
public CommandKick(InfractionStore store) {
|
||||
super(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.KICK;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
Player player = infraction.getRecipient().getPlayer();
|
||||
if (player == null) {
|
||||
sender.sendMessage("That player is not online!");
|
||||
sender.sendMessage("Infraction logged anyway.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.kickPlayer(infraction.getMessage());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
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;
|
||||
|
||||
public class CommandMute extends CommandIssueInfraction {
|
||||
public CommandMute(InfractionStore store, DurationsConfig durations) {
|
||||
super(store, durations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.MUTE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
Player player = infraction.getRecipient().getPlayer();
|
||||
if (player != null) {
|
||||
player.sendMessage(infraction.getMessage());
|
||||
}
|
||||
|
||||
sender.sendMessage(infraction.getRecipient().getName() + " has been muted for " + infraction.getDuration().toStringLong() + ".");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package me.jamestmartin.wasteland.modtools.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.WastelandModTools;
|
||||
|
||||
public class CommandWMT implements CommandExecutor {
|
||||
private final WastelandModTools instance;
|
||||
|
||||
public CommandWMT(WastelandModTools instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length < 1) {
|
||||
sender.sendMessage("Not enough arguments.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length > 1) {
|
||||
sender.sendMessage("Too many arguments.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[0].equals("reload")) {
|
||||
sender.sendMessage("Unknown subcommand: " + args[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("wasteland.modtools.reload")) {
|
||||
sender.sendMessage("You do not have permission to reload Wasteland ModTools.");
|
||||
}
|
||||
|
||||
sender.sendMessage("Reloading...");
|
||||
instance.reload();
|
||||
sender.sendMessage("Done.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
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.InfractionStore;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.InfractionType;
|
||||
|
||||
public class CommandWarn extends CommandIssueInfraction {
|
||||
public CommandWarn(InfractionStore store) {
|
||||
super(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InfractionType getType() {
|
||||
return InfractionType.WARN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyInfraction(CommandSender sender, Infraction infraction) {
|
||||
Player player = infraction.getRecipient().getPlayer();
|
||||
if (player != null) {
|
||||
player.sendMessage(infraction.getMessage());
|
||||
}
|
||||
|
||||
sender.sendMessage(infraction.getRecipient().getName() + " has been warned.");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package me.jamestmartin.wasteland.modtools.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import me.jamestmartin.wasteland.manual.config.ManualConfig;
|
||||
import me.jamestmartin.wasteland.manual.config.ManualConfigParser;
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Duration;
|
||||
|
||||
public class ConfigParser {
|
||||
public static ModToolsConfig parse(ConfigurationSection c) {
|
||||
ManualConfig manualConfig = ManualConfigParser.parse(c.getConfigurationSection("manuals"));
|
||||
DurationsConfigs durationsConfig = parseDurationsConfig(c.getConfigurationSection("permissions"));
|
||||
|
||||
return new ModToolsConfig(manualConfig, durationsConfig);
|
||||
}
|
||||
|
||||
private static DurationsConfigs parseDurationsConfig(ConfigurationSection c) {
|
||||
Map<String, Duration> maximumBans = new HashMap<>();
|
||||
Map<String, Duration> maximumMutes = new HashMap<>();
|
||||
|
||||
if (c.isString("ban")) {
|
||||
maximumBans.put("", Duration.parse(c.getString("ban")).get());
|
||||
}
|
||||
if (c.isString("mute")) {
|
||||
maximumMutes.put("", Duration.parse(c.getString("mute")).get());
|
||||
}
|
||||
|
||||
for (String key : c.getKeys(false)) {
|
||||
if (c.isString(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DurationsConfigs sub = parseDurationsConfig(c.getConfigurationSection(key));
|
||||
for (Entry<String, Duration> ban : sub.getBansConfig().getMaximumDurations().entrySet()) {
|
||||
maximumBans.put(key + "." + ban.getKey(), ban.getValue());
|
||||
}
|
||||
for (Entry<String, Duration> mute : sub.getMutesConfig().getMaximumDurations().entrySet()) {
|
||||
maximumMutes.put(key + "." + mute.getKey(), mute.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return new DurationsConfigs(new DurationsConfig(maximumBans), new DurationsConfig(maximumMutes));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package me.jamestmartin.wasteland.modtools.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Duration;
|
||||
|
||||
public class DurationsConfig {
|
||||
private final Map<String, Duration> maxima;
|
||||
|
||||
public DurationsConfig(Map<String, Duration> maxima) {
|
||||
this.maxima = maxima;
|
||||
}
|
||||
|
||||
public Map<String, Duration> getMaximumDurations() {
|
||||
return maxima;
|
||||
}
|
||||
|
||||
public Duration getMaximumBanDuration(CommandSender moderator) {
|
||||
Duration duration = maxima.getOrDefault("default", Duration.ZERO);
|
||||
for (String perm : maxima.keySet()) {
|
||||
if (moderator.hasPermission(perm)) {
|
||||
duration = duration.max(maxima.get(perm));
|
||||
}
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package me.jamestmartin.wasteland.modtools.config;
|
||||
|
||||
public class DurationsConfigs {
|
||||
private final DurationsConfig bansConfig;
|
||||
private final DurationsConfig mutesConfig;
|
||||
|
||||
public DurationsConfigs(DurationsConfig bansConfig, DurationsConfig mutesConfig) {
|
||||
this.bansConfig = bansConfig;
|
||||
this.mutesConfig = mutesConfig;
|
||||
}
|
||||
|
||||
public DurationsConfig getBansConfig() {
|
||||
return bansConfig;
|
||||
}
|
||||
|
||||
public DurationsConfig getMutesConfig() {
|
||||
return mutesConfig;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package me.jamestmartin.wasteland.modtools.config;
|
||||
|
||||
import me.jamestmartin.wasteland.manual.config.ManualConfig;
|
||||
|
||||
public class ModToolsConfig {
|
||||
private final ManualConfig manuals;
|
||||
private final DurationsConfigs durations;
|
||||
|
||||
public ModToolsConfig(ManualConfig manuals, DurationsConfigs durations) {
|
||||
this.manuals = manuals;
|
||||
this.durations = durations;
|
||||
}
|
||||
|
||||
public ManualConfig getManuals() {
|
||||
return manuals;
|
||||
}
|
||||
|
||||
public DurationsConfigs getDurations() {
|
||||
return durations;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Duration implements Comparable<Duration> {
|
||||
public static final Duration ZERO = new Duration(0);
|
||||
public static final Duration INFINITY = new Duration();
|
||||
|
||||
/** Durations of "none" are infinite. */
|
||||
private final Optional<Long> seconds;
|
||||
|
||||
private Duration() {
|
||||
this.seconds = Optional.empty();
|
||||
}
|
||||
|
||||
private Duration(Optional<Long> seconds) {
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
public Duration(long seconds) {
|
||||
this.seconds = Optional.of(seconds);
|
||||
}
|
||||
|
||||
public Optional<Long> getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public Duration max(Duration other) {
|
||||
return new Duration(this.seconds.flatMap(x -> other.seconds.map(y -> Math.max(x, y))));
|
||||
}
|
||||
|
||||
public static Optional<Duration> parse(String str) {
|
||||
if (str.equals("0")) {
|
||||
return Optional.of(ZERO);
|
||||
}
|
||||
if (str.equals("forever")) {
|
||||
return Optional.of(INFINITY);
|
||||
}
|
||||
return DurationParts.parse(str).map(DurationParts::toDuration);
|
||||
}
|
||||
|
||||
private Optional<DurationParts> toParts() {
|
||||
if (seconds.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
long secs = seconds.get();
|
||||
|
||||
// Find the greatest prefix that gives an exact value.
|
||||
List<DurationSuffix> suffixes = List.of(DurationSuffix.values());
|
||||
Collections.reverse(suffixes);
|
||||
DurationSuffix s = null;
|
||||
for (DurationSuffix suffix : suffixes) {
|
||||
if (secs % suffix.getSeconds() == 0) {
|
||||
s = suffix;
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.of(new DurationParts(secs / s.getSeconds(), s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toParts().map(DurationParts::toString).orElse("forever");
|
||||
}
|
||||
|
||||
public String toStringLong() {
|
||||
return toParts().map(DurationParts::toStringLong).orElse("forever");
|
||||
}
|
||||
|
||||
private static class DurationParts {
|
||||
public final long value;
|
||||
public final DurationSuffix suffix;
|
||||
|
||||
public DurationParts(long value, DurationSuffix suffix) {
|
||||
this.value = value;
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
public Duration toDuration() {
|
||||
return new Duration(value * suffix.getSeconds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value + suffix.toString();
|
||||
}
|
||||
|
||||
public String toStringLong() {
|
||||
return value + " " + suffix.toStingLong();
|
||||
}
|
||||
|
||||
public static Optional<DurationParts> parse(String str) {
|
||||
if (str.length() < 2) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Optional<DurationSuffix> suffix = DurationSuffix.fromChar(str.charAt(str.length() - 1));
|
||||
if (suffix.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String valueStr = str.substring(0, str.length() - 1);
|
||||
if (!valueStr.matches("\\d+")) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(new DurationParts(Long.parseLong(valueStr), suffix.get()));
|
||||
}
|
||||
}
|
||||
|
||||
private static enum DurationSuffix {
|
||||
SECONDS('s', "seconds", 1),
|
||||
MINUTES('m', "minutes", 60),
|
||||
HOURS('h', "hours", 3600),
|
||||
DAYS('d', "days", 86400),
|
||||
WEEKS('w', "weeks", 604800),
|
||||
MONTHS('M', "months", 2628000),
|
||||
YEARS('y', "years", 31540000);
|
||||
|
||||
private final char character;
|
||||
private final String longName;
|
||||
private final long seconds;
|
||||
|
||||
private DurationSuffix(char character, String longName, long seconds) {
|
||||
this.character = character;
|
||||
this.longName = longName;
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
public long getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public char toChar() {
|
||||
return character;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(toChar());
|
||||
}
|
||||
|
||||
public String toStingLong() {
|
||||
return longName;
|
||||
}
|
||||
|
||||
public static Optional<DurationSuffix> fromChar(char c) {
|
||||
for (DurationSuffix suffix : DurationSuffix.values()) {
|
||||
if (suffix.character == c) {
|
||||
return Optional.of(suffix);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Duration other) {
|
||||
if (getSeconds().isEmpty() && other.getSeconds().isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
if (getSeconds().isEmpty()) {
|
||||
return 1;
|
||||
}
|
||||
if (other.getSeconds().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return Long.compare(getSeconds().get(), other.getSeconds().get());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public class Infraction {
|
||||
private final InfractionType type;
|
||||
private final OfflinePlayer issuer;
|
||||
private final OfflinePlayer recipient;
|
||||
private final Date issued;
|
||||
private final Duration duration;
|
||||
private final String rule;
|
||||
private final String reason;
|
||||
|
||||
public Infraction(InfractionType type, OfflinePlayer issuer, OfflinePlayer recipient, Date issued, Duration duration, String rule, String reason) {
|
||||
this.type = type;
|
||||
this.issuer = issuer;
|
||||
this.recipient = recipient;
|
||||
this.issued = issued;
|
||||
this.duration = duration;
|
||||
this.rule = rule;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public InfractionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public OfflinePlayer getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
public OfflinePlayer getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public Date getIssued() {
|
||||
return issued;
|
||||
}
|
||||
|
||||
public Duration getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public String getRule() {
|
||||
return rule;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface InfractionProvider {
|
||||
Set<Infraction> getActiveInfractions(Optional<UUID> player, Optional<InfractionType> type);
|
||||
|
||||
default Set<Infraction> getActiveInfractions() {
|
||||
return getActiveInfractions(Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getActiveInfractions(UUID player) {
|
||||
return getActiveInfractions(Optional.of(player), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getActiveInfractions(UUID player, InfractionType type) {
|
||||
return getActiveInfractions(Optional.of(player), Optional.of(type));
|
||||
}
|
||||
|
||||
default Set<Infraction> getActiveInfractions(InfractionType type) {
|
||||
return getActiveInfractions(Optional.empty(), Optional.of(type));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
public interface InfractionStore extends InfractionProvider {
|
||||
void addInfraction(Infraction infraction);
|
||||
void removeInfractions(OfflinePlayer player, InfractionType type);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package me.jamestmartin.wasteland.modtools.infraction;
|
||||
|
||||
public enum InfractionType {
|
||||
BAN(true),
|
||||
KICK(false),
|
||||
MUTE(true),
|
||||
WARN(false);
|
||||
|
||||
private final boolean hasduration;
|
||||
|
||||
private InfractionType(boolean hasDuration) {
|
||||
this.hasduration = hasDuration;
|
||||
}
|
||||
|
||||
public boolean hasDuration() {
|
||||
return hasduration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package me.jamestmartin.wasteland.modtools.log;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandModLog implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package me.jamestmartin.wasteland.modtools.log;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
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;
|
||||
|
||||
public interface ModLogProvider {
|
||||
Set<Infraction> getInfractions(
|
||||
Duration duration,
|
||||
Optional<UUID> issuer,
|
||||
Optional<UUID> recipient,
|
||||
Optional<InfractionType> type
|
||||
);
|
||||
|
||||
default Set<Infraction> getInfractions() {
|
||||
return getInfractions(Duration.INFINITY);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractions(InfractionType type) {
|
||||
return getInfractions(Duration.INFINITY, type);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractions(Duration duration) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractions(Duration duration, InfractionType type) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.empty(), Optional.of(type));
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(UUID player) {
|
||||
return getInfractionsIssuedTo(Duration.INFINITY, player);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(UUID player, InfractionType type) {
|
||||
return getInfractionsIssuedTo(Duration.INFINITY, player, type);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(Duration duration, UUID player) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.of(player), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedTo(Duration duration, UUID player, InfractionType type) {
|
||||
return getInfractions(duration, Optional.empty(), Optional.of(player), Optional.of(type));
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedBy(UUID player) {
|
||||
return getInfractionsIssuedBy(Duration.INFINITY, player);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedBy(UUID player, InfractionType type) {
|
||||
return getInfractionsIssuedBy(Duration.INFINITY, player, type);
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedBy(Duration duration, UUID player) {
|
||||
return getInfractions(duration, Optional.of(player), Optional.empty(), Optional.empty());
|
||||
}
|
||||
|
||||
default Set<Infraction> getInfractionsIssuedBy(Duration duration, UUID player, InfractionType type) {
|
||||
return getInfractions(duration, Optional.of(player), Optional.empty(), Optional.of(type));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package me.jamestmartin.wasteland.modtools.log;
|
||||
|
||||
import me.jamestmartin.wasteland.modtools.infraction.Infraction;
|
||||
|
||||
public interface ModLogStore extends ModLogProvider {
|
||||
void addInfraction(Infraction infraction);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package me.jamestmartin.wasteland.offlineplayer;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandLastSeen implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package me.jamestmartin.wasteland.offlineplayer;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class CommandUUID implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package me.jamestmartin.wasteland.offlineplayer;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface OfflinePlayerProvider {
|
||||
Map<UUID, Date> getNameUUIDs(String playerName);
|
||||
Date getFirstSeen(UUID player);
|
||||
Date getLastSeen(UUID player);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package me.jamestmartin.wasteland.offlineplayer;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface OfflinePlayerStore extends OfflinePlayerProvider {
|
||||
void logPlayer(Player player);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
manuals:
|
||||
rules:
|
||||
- summary: Be civil and respectful.
|
||||
sections:
|
||||
- summary: If you start getting angry or frustrated, take a break!
|
||||
- summary: Do not harass other players.
|
||||
- summary: Do not use slurs.
|
||||
- summary: Do not advertise.
|
||||
- summary: Do not spam.
|
||||
- summary: Avoid excessive swearing.
|
||||
details: 'What is "excessive" is determined by moderator discretion.'
|
||||
- summary: Be independent and mature.
|
||||
sections:
|
||||
- summary: This is a server intended for adults.
|
||||
details: You will not be banned for being <16 per se, but acting like a child will get you banned no matter how old you are.
|
||||
- summary: RTFM (Read The Field Manual).
|
||||
details: Try to answer questions for yourself (e.g. with `/faq`) before asking them.
|
||||
- summary: Do not whine or beg.
|
||||
- summary: Do not ask moderators to cheat.
|
||||
details: They don't have the ability to, anyway.
|
||||
- summary: Play fairly.
|
||||
sections:
|
||||
- summary: Do not use hacks.
|
||||
details: Hacks are the use of a client or mod designed for cheating.
|
||||
- summary: Do not use exploits.
|
||||
details: Exploits are the use of bugs to gain an unfair advantage (e.g. item duplication) or e.g. bypass protection plugins.
|
||||
- summary: Do not use cheats.
|
||||
details: Do not use x-ray resource packs or any other form of cheating.
|
||||
- summary: Use your power appropriately.
|
||||
details: Use moderator tools and ranks strictly for their intended purpose.
|
||||
- summary: Only use authorized mods.
|
||||
details: Refer to the authorized mods list to see which mods are permitted. If you'd like to use a mod not on that list, you **must ask the administrator(s)** before using it.
|
||||
- summary: Stick to the game.
|
||||
sections:
|
||||
- summary: Keep the chat SFW.
|
||||
- summary: Avoid discussing politics, religion, and the news.
|
||||
details: This is not strictly forbidden, but these discussions may be shut down by moderator discretion.
|
||||
- summary: Do not ask for personal information.
|
||||
details: This includes real name, age, and location.
|
||||
- summary: Do not share anyone else's personal information.
|
||||
details: This includes their real name, age, and location.
|
||||
- summary: Avoid sharing your own personal information.
|
||||
details: You may share your own real name, age, or location, but not e.g. your address or phone number.
|
||||
|
||||
faq:
|
||||
- summary: Nothing to see here.
|
||||
details: The server administrator has not set an FAQ.
|
||||
|
||||
# Set the maximum durations for which moderators are allowed to mute or ban,
|
||||
# based on their permission nodes.
|
||||
permissions:
|
||||
# The default durations for people with permission to mute/ban, but with no specific duration permission set.
|
||||
# Set this to 0 if you want to require a more specific permission be to set to allow mutes and bans.
|
||||
wasteland.modtools.ban.issue:
|
||||
ban: forever
|
||||
wasteland.modtools.mute.issue:
|
||||
mute: forever
|
||||
# You will not want to leave this section here if you will not be using Wasteland's rank system,
|
||||
# or don't intend to use the officer rank system for staff ranks.
|
||||
wasteland.rank:
|
||||
ltcol:
|
||||
mute: 3h
|
||||
ban: 3h
|
||||
col:
|
||||
mute: 3d
|
||||
ban: 3d
|
||||
bgen:
|
||||
mute: forever
|
||||
ban: forever
|
|
@ -0,0 +1,193 @@
|
|||
name: WastelandModTools
|
||||
author: HuskFodder
|
||||
main: me.jamestmartin.wasteland.modtools.WastelandModTools
|
||||
version: 0.1.0
|
||||
api-version: 1.16
|
||||
|
||||
commands:
|
||||
modlog:
|
||||
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.
|
||||
infractions:
|
||||
description: See the list of infractions against the rules a player has committed.
|
||||
usage: "Usage: /<infractions> <player> [<duration>]"
|
||||
permission: wasteland.modtools.infractions
|
||||
permission-message: You do not have permission to view players' infractions against the rules.
|
||||
|
||||
uuid:
|
||||
description: Get the UUID(s) of players who have had a name on this server.
|
||||
usage: "Usage: /<command> <player name>"
|
||||
permission: wasteland.modtools.uuid
|
||||
permission-message: You do not have permission to view player UUIDs.
|
||||
lastseen:
|
||||
description: Get the last time the player with that name or UUID was seen.
|
||||
usage: "Usage: /<command> <player name or UUID>"
|
||||
permission: wasteland.modtools.lastseen
|
||||
permission-message: You do not have permission to view when a player was last seen.
|
||||
|
||||
rules:
|
||||
description: "Read the server rules. You can view more information about a specific rule using `/rules #`."
|
||||
usage: "Usage: /<command> [<section>] [<player>]"
|
||||
permission: wasteland.manual.rules
|
||||
permission-message: You do not have permission to read the server rules.
|
||||
faq:
|
||||
description: "Read the server FAQ. You can view more information about a specific topic using `/faq #`."
|
||||
usage: "Usage: /<command> [<section>] [<player>]"
|
||||
permission: wasteland.manual.faq
|
||||
permission-message: You do not have permission to read the server FAQ.
|
||||
|
||||
ban:
|
||||
description: Ban a player from the server, preventing them from joining again.
|
||||
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.
|
||||
usage: "Usage: /<command> <player> [<rule>] [<reason> ...]"
|
||||
permission: wasteland.modtools.kick
|
||||
permission-message: You do not have permission to kick players.
|
||||
|
||||
mute:
|
||||
description: Mute a player, preventing them from talking.
|
||||
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.
|
||||
usage: "Usage: /<command> <player> [<rule>] [<reason> ...]"
|
||||
permission: wasteland.modtools.warn
|
||||
permission-message: You do not have permission to issue warnings to players.
|
||||
|
||||
permissions:
|
||||
wasteland.modtools:
|
||||
description: Allows you full access to the moderator tools.
|
||||
default: op
|
||||
children:
|
||||
wasteland.modtools.uuid: true
|
||||
wasteland.modtools.lastseen: true
|
||||
wasteland.modtools.log: true
|
||||
wasteland.modtools.actions: true
|
||||
|
||||
wasteland.modtools.log:
|
||||
description: Allows you to view the log of moderator actions.
|
||||
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.uuid:
|
||||
description: Allows you to see the UUIDs of players with a given name on this server.
|
||||
default: op
|
||||
wasteland.modtools.lastseen:
|
||||
description: Allows you to see the first and last time a player was seen on this server.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.actions:
|
||||
description: Allows you to perform any moderator action.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.show-other: true
|
||||
wasteland.modtools.ban: true
|
||||
wasteland.modtools.kick: true
|
||||
wasteland.modtools.mute: true
|
||||
wasteland.modtools.warn: true
|
||||
|
||||
wasteland.manual:
|
||||
description: Allows you to read any manual.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.rules: true
|
||||
wasteland.manual.faq: true
|
||||
wasteland.manual.show-other:
|
||||
description: Allows you to forcibly show any manual to someone else.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.rules.show-other: true
|
||||
wasteland.manual.faq.show-other: true
|
||||
wasteland.manual.rules:
|
||||
description: Allows you to read the server rules.
|
||||
default: true
|
||||
wasteland.manual.rules.show-other:
|
||||
description: Allows you to forcibly show the server rules to someone else.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.rules: true
|
||||
wasteland.manual.faq:
|
||||
description: Allows you to read the FAQ.
|
||||
default: true
|
||||
wasteland.manual.faq.show-other:
|
||||
description: Allows you to forcibly show the FAQ to someone else.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.faq: true
|
||||
|
||||
wasteland.modtools.ban:
|
||||
description: Allows you to ban or unban a player, or list active bans.
|
||||
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.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.kick:
|
||||
desription: Allows you to kick players.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.mute:
|
||||
description: Allows you to mute or unmute a player, or list active mutes.
|
||||
default: op
|
||||
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.
|
||||
default: op
|
||||
|
||||
wasteland.modtools.warn:
|
||||
description: Allows you to issue a warning against a player.
|
||||
default: op
|
|
@ -22,6 +22,10 @@ class CommandWP implements CommandExecutor {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("wasteland.permissions.reload")) {
|
||||
sender.sendMessage("You do not have permission to reload Wasteland Permissions' config.");
|
||||
}
|
||||
|
||||
WastelandPermissions.getInstance().reload();
|
||||
sender.sendMessage("Reloaded Wasteland Permissions' configuration.");
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ public class ConfigParser {
|
|||
}
|
||||
|
||||
private static Map<String, Group> parseGroups(ConfigurationSection c) {
|
||||
if (c == null) {
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
Map<String, GroupConfig> groupConfigs = new HashMap<>();
|
||||
for (String group : c.getKeys(false)) {
|
||||
groupConfigs.put(group, parseGroup(group, c.getConfigurationSection(group)));
|
||||
|
@ -88,6 +92,10 @@ public class ConfigParser {
|
|||
|
||||
private static Map<UUID, PlayerGroup> parsePlayers(Map<String, Group> groups, ConfigurationSection c) {
|
||||
Map<UUID, PlayerGroup> players = new HashMap<>();
|
||||
if (c == null) {
|
||||
return players;
|
||||
}
|
||||
|
||||
for (String uuidStr : c.getKeys(false)) {
|
||||
UUID uuid = UUID.fromString(uuidStr);
|
||||
players.put(uuid, parsePlayer(groups, uuidStr, c.getConfigurationSection(uuidStr)));
|
||||
|
@ -103,11 +111,18 @@ public class ConfigParser {
|
|||
}
|
||||
|
||||
private static PseudoGroupConfig parsePseudoGroup(List<String> inherits, ConfigurationSection permissions) {
|
||||
if (inherits == null) {
|
||||
inherits = List.of();
|
||||
}
|
||||
return new PseudoGroupConfig(inherits, parsePermissions(permissions));
|
||||
}
|
||||
|
||||
private static Map<String, Boolean> parsePermissions(ConfigurationSection c) {
|
||||
Map<String, Boolean> permissions = new HashMap<>();
|
||||
if (c == null) {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
for (String node : c.getKeys(false)) {
|
||||
if (c.isBoolean(node)) {
|
||||
permissions.put(node, c.getBoolean(node));
|
||||
|
|
|
@ -9,7 +9,7 @@ commands:
|
|||
description: Manage the Wasteland Permissions plugin.
|
||||
usage: "Usage: /<command> [reload]"
|
||||
permission: wasteland.permissions
|
||||
permission-message: You do not have permission to reload Wasteland Permission' config.
|
||||
permission-message: You do not have permission to manage Wasteland Permissions.
|
||||
|
||||
permissions:
|
||||
wasteland.permissions:
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
rootProject.name = 'wasteland-all'
|
||||
include 'wasteland', 'permissions'
|
||||
include 'wasteland', 'permissions', 'modtools'
|
|
@ -3,7 +3,6 @@ package me.jamestmartin.wasteland;
|
|||
import me.jamestmartin.wasteland.chat.ChatConfig;
|
||||
import me.jamestmartin.wasteland.kills.KillsConfig;
|
||||
import me.jamestmartin.wasteland.kit.KitConfig;
|
||||
import me.jamestmartin.wasteland.manual.ManualConfig;
|
||||
import me.jamestmartin.wasteland.ranks.AllRanks;
|
||||
import me.jamestmartin.wasteland.spawns.SpawnsConfig;
|
||||
|
||||
|
@ -14,7 +13,6 @@ public class WastelandConfig {
|
|||
private final AllRanks ranks;
|
||||
private final SpawnsConfig spawnsConfig;
|
||||
private final KitConfig kitConfig;
|
||||
private final ManualConfig manualConfig;
|
||||
|
||||
public WastelandConfig(
|
||||
String databaseFilename,
|
||||
|
@ -22,15 +20,13 @@ public class WastelandConfig {
|
|||
KillsConfig killsConfig,
|
||||
AllRanks ranks,
|
||||
SpawnsConfig spawnsConfig,
|
||||
KitConfig kitConfig,
|
||||
ManualConfig manualConfig) {
|
||||
KitConfig kitConfig) {
|
||||
this.databaseFilename = databaseFilename;
|
||||
this.chatConfig = chatConfig;
|
||||
this.killsConfig = killsConfig;
|
||||
this.ranks = ranks;
|
||||
this.spawnsConfig = spawnsConfig;
|
||||
this.kitConfig = kitConfig;
|
||||
this.manualConfig = manualConfig;
|
||||
}
|
||||
|
||||
public String getDatabaseFilename() {
|
||||
|
@ -56,8 +52,4 @@ public class WastelandConfig {
|
|||
public KitConfig getKitConfig() {
|
||||
return kitConfig;
|
||||
}
|
||||
|
||||
public ManualConfig getManualConfig() {
|
||||
return manualConfig;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||
import me.jamestmartin.wasteland.chat.ChatState;
|
||||
import me.jamestmartin.wasteland.kills.KillsState;
|
||||
import me.jamestmartin.wasteland.kit.KitState;
|
||||
import me.jamestmartin.wasteland.manual.ManualState;
|
||||
import me.jamestmartin.wasteland.ranks.PermissionsPlayerRankProvider;
|
||||
import me.jamestmartin.wasteland.ranks.PlayerRankProvider;
|
||||
import me.jamestmartin.wasteland.ranks.RanksState;
|
||||
|
@ -25,7 +24,6 @@ public class WastelandState implements Substate {
|
|||
private final RanksState ranksState;
|
||||
private final SpawnsState spawnsState;
|
||||
private final KitState kitState;
|
||||
private final ManualState manualState;
|
||||
|
||||
public WastelandState(WastelandConfig config) throws IOException, ClassNotFoundException, SQLException {
|
||||
this.commandWasteland = new CommandWasteland();
|
||||
|
@ -37,7 +35,6 @@ public class WastelandState implements Substate {
|
|||
this.killsState = new KillsState(config.getKillsConfig(), ranksState.getPlayerKillsStore(), rankProvider);
|
||||
this.spawnsState = new SpawnsState(config.getSpawnsConfig());
|
||||
this.kitState = new KitState(config.getKitConfig(), storeState.getKitStore());
|
||||
this.manualState = new ManualState(config.getManualConfig());
|
||||
}
|
||||
|
||||
private Substate[] getSubstates() {
|
||||
|
@ -48,7 +45,6 @@ public class WastelandState implements Substate {
|
|||
ranksState,
|
||||
spawnsState,
|
||||
kitState,
|
||||
manualState,
|
||||
};
|
||||
return substates;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
@ -26,8 +24,6 @@ import me.jamestmartin.wasteland.WastelandConfig;
|
|||
import me.jamestmartin.wasteland.chat.ChatConfig;
|
||||
import me.jamestmartin.wasteland.kills.KillsConfig;
|
||||
import me.jamestmartin.wasteland.kit.KitConfig;
|
||||
import me.jamestmartin.wasteland.manual.ManualConfig;
|
||||
import me.jamestmartin.wasteland.manual.ManualSection;
|
||||
import me.jamestmartin.wasteland.ranks.AllRanks;
|
||||
import me.jamestmartin.wasteland.ranks.EnlistedRank;
|
||||
import me.jamestmartin.wasteland.ranks.EnlistedRanks;
|
||||
|
@ -51,22 +47,13 @@ public class ConfigParser {
|
|||
ConfigurationSection officerSection = c.getConfigurationSection("officer");
|
||||
AllRanks ranks = parseRanks(enlistedSection, officerSection);
|
||||
|
||||
ManualSection rules = new ManualSection(
|
||||
"The Server Rules",
|
||||
parseManualSectionList(castToSectionList(c.getMapList("rules"))));
|
||||
ManualSection faq = new ManualSection(
|
||||
"Frequently Asked Questions",
|
||||
parseManualSectionList(castToSectionList(c.getMapList("faq"))));
|
||||
ManualConfig manualConfig = new ManualConfig(rules, faq);
|
||||
|
||||
return new WastelandConfig(
|
||||
databaseFilename,
|
||||
chatConfig,
|
||||
killsConfig,
|
||||
ranks,
|
||||
spawnsConfig,
|
||||
kitConfig,
|
||||
manualConfig);
|
||||
kitConfig);
|
||||
}
|
||||
|
||||
private static ChatConfig parseChatConfig(ConfigurationSection c) {
|
||||
|
@ -321,34 +308,6 @@ public class ConfigParser {
|
|||
return new KitConfig(kitPeriod, kitTools, kitItems);
|
||||
}
|
||||
|
||||
public static ManualSection parseManualSection(Map<?, ?> c) {
|
||||
String summary = (String) c.get("summary");
|
||||
Optional<String> details = Optional.ofNullable((String) c.get("details"));
|
||||
List<ManualSection> subsections = parseManualSectionList(castToSectionList(c.get("sections")));
|
||||
|
||||
return new ManualSection(summary, details, subsections);
|
||||
}
|
||||
|
||||
private static List<Map<?, ?>> castToSectionList(Object x) {
|
||||
if (x == null) {
|
||||
return null;
|
||||
}
|
||||
return ((List<?>) x).stream().map(xx -> (Map<?, ?>) xx).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
|
||||
public static List<ManualSection> parseManualSectionList(List<Map<?, ?>> list) {
|
||||
List<ManualSection> sections = new ArrayList<>();
|
||||
if (list == null) {
|
||||
return sections;
|
||||
}
|
||||
|
||||
for (Map<?, ?> section : list) {
|
||||
sections.add(parseManualSection(section));
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
/** Orphaned method. */
|
||||
private static Optional<ChatColor> readColor(ConfigurationSection c, String path) {
|
||||
return (Optional<ChatColor>) Optional.ofNullable(c.getString(path)).map(ChatColor::valueOf);
|
||||
|
|
|
@ -365,51 +365,4 @@ kit:
|
|||
# A random quantity will be chosen depending on how many kits the player has received.
|
||||
# The item type will not be dropped if the quantity chosen is less than one eighth of the maximum.
|
||||
items:
|
||||
ROTTEN_FLESH: 32
|
||||
|
||||
rules:
|
||||
- summary: Be civil and respectful.
|
||||
sections:
|
||||
- summary: If you start getting angry or frustrated, take a break!
|
||||
- summary: Do not harass other players.
|
||||
- summary: Do not use slurs.
|
||||
- summary: Do not advertise.
|
||||
- summary: Do not spam.
|
||||
- summary: Avoid excessive swearing.
|
||||
details: 'What is "excessive" is determined by moderator discretion.'
|
||||
- summary: Be independent and mature.
|
||||
sections:
|
||||
- summary: This is a server intended for adults.
|
||||
details: You will not be banned for being <16 per se, but acting like a child will get you banned no matter how old you are.
|
||||
- summary: RTFM (Read The Field Manual).
|
||||
details: Try to answer questions for yourself (e.g. with `/faq`) before asking them.
|
||||
- summary: Do not whine or beg.
|
||||
- summary: Do not ask moderators to cheat.
|
||||
details: They don't have the ability to, anyway.
|
||||
- summary: Play fairly.
|
||||
sections:
|
||||
- summary: Do not use hacks.
|
||||
details: Hacks are the use of a client or mod designed for cheating.
|
||||
- summary: Do not use exploits.
|
||||
details: Exploits are the use of bugs to gain an unfair advantage (e.g. item duplication) or e.g. bypass protection plugins.
|
||||
- summary: Do not use cheats.
|
||||
details: Do not use x-ray resource packs or any other form of cheating.
|
||||
- summary: Use your power appropriately.
|
||||
details: Use moderator tools and ranks strictly for their intended purpose.
|
||||
- summary: Only use authorized mods.
|
||||
details: Refer to the authorized mods list to see which mods are permitted. If you'd like to use a mod not on that list, you **must ask the administrator(s)** before using it.
|
||||
- summary: Stick to the game.
|
||||
sections:
|
||||
- summary: Keep the chat SFW.
|
||||
- summary: Avoid discussing politics, religion, and the news.
|
||||
details: This is not strictly forbidden, but these discussions may be shut down by moderator discretion.
|
||||
- summary: Do not ask for personal information.
|
||||
details: This includes real name, age, and location.
|
||||
- summary: Do not share anyone else's personal information.
|
||||
details: This includes their real name, age, and location.
|
||||
- summary: Avoid sharing your own personal information.
|
||||
details: You may share your own real name, age, or location, but not e.g. your address or phone number.
|
||||
|
||||
faq:
|
||||
- summary: Nothing to see here.
|
||||
details: The server administrator has not set an FAQ.
|
||||
ROTTEN_FLESH: 32
|
|
@ -56,17 +56,6 @@ commands:
|
|||
usage: "Usage: /<command>"
|
||||
permission: wasteland.kit
|
||||
permission-message: You do not have permission to receive a starter kit.
|
||||
|
||||
rules:
|
||||
description: "Read the server rules. You can view more information about a specific rule using `/rules #`."
|
||||
usage: "Usage: /<command> [<section>] [<player>]"
|
||||
permission: wasteland.manual.rules
|
||||
permission-message: You do not have permission to read the server rules.
|
||||
faq:
|
||||
description: "Read the server FAQ. You can view more information about a specific topic using `/faq #`."
|
||||
usage: "Usage: /<command> [<section>] [<player>]"
|
||||
permission: wasteland.manual.faq
|
||||
permission-message: You do not have permission to read the server FAQ.
|
||||
|
||||
permissions:
|
||||
wasteland.reload:
|
||||
|
@ -128,32 +117,3 @@ permissions:
|
|||
wasteland.kit:
|
||||
description: Allows you to receive a starter kit.
|
||||
default: true
|
||||
|
||||
wasteland.manual:
|
||||
description: Allows you to read any manual.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.rules: true
|
||||
wasteland.manual.faq: true
|
||||
wasteland.manual.show-other:
|
||||
description: Allows you to forcibly show any manual to someone else.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.rules.show-other: true
|
||||
wasteland.manual.faq.show-other: true
|
||||
wasteland.manual.rules:
|
||||
description: Allows you to read the server rules.
|
||||
default: true
|
||||
wasteland.manual.rules.show-other:
|
||||
description: Allows you to forcibly show the server rules to someone else.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.rules: true
|
||||
wasteland.manual.faq:
|
||||
description: Allows you to read the FAQ.
|
||||
default: true
|
||||
wasteland.manual.faq.show-other:
|
||||
description: Allows you to forcibly show the FAQ to someone else.
|
||||
default: op
|
||||
children:
|
||||
wasteland.manual.faq: true
|
||||
|
|
Loading…
Reference in New Issue