Merge pull request #304 from BentoBoxWorld/why

Why admin command
This commit is contained in:
Florian CUNY 2018-10-14 07:35:14 +02:00 committed by GitHub
commit 711db68448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 151 additions and 12 deletions

View File

@ -0,0 +1,72 @@
package world.bentobox.bentobox.api.commands.admin;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.metadata.FixedMetadataValue;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
public class AdminWhyCommand extends ConfirmableCommand {
public AdminWhyCommand(CompositeCommand parent) {
super(parent, "why");
}
@Override
public void setup() {
setPermission("admin.why");
setParametersHelp("commands.admin.why.parameters");
setDescription("commands.admin.why.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
// If args are not right, show help
if (args.size() != 1) {
showHelp(this, user);
return false;
}
// Get target
UUID targetUUID = getPlayers().getUUID(args.get(0));
if (targetUUID == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false;
}
// Set meta data on player
User target = User.getInstance(targetUUID);
if (!target.isOnline()) {
user.sendMessage("general.errors.offline-player");
return false;
}
// Determine the debug mode and toggle if required
boolean newValue = !target.getPlayer().getMetadata(getWorld().getName() + "_why_debug").stream()
.filter(p -> p.getOwningPlugin().equals(getPlugin())).findFirst().map(p -> p.asBoolean()).orElse(false);
if (newValue) {
user.sendMessage("commands.admin.why.turning-on", TextVariables.NAME, target.getName());
} else {
user.sendMessage("commands.admin.why.turning-off", TextVariables.NAME, target.getName());
}
// Set the debug meta
target.getPlayer().setMetadata(getWorld().getName() + "_why_debug", new FixedMetadataValue(getPlugin(), newValue));
return true;
}
@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
if (args.isEmpty()) {
// Don't show every player on the server. Require at least the first letter
return Optional.empty();
}
List<String> options = new ArrayList<>(Util.getOnlinePlayerList(user));
return Optional.of(Util.tabLimit(options, lastArg));
}
}

View File

@ -15,6 +15,7 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.util.Util;
/** /**
* Abstract class for flag listeners. Provides common code. * Abstract class for flag listeners. Provides common code.
@ -23,8 +24,33 @@ import world.bentobox.bentobox.managers.IslandsManager;
*/ */
public abstract class AbstractFlagListener implements Listener { public abstract class AbstractFlagListener implements Listener {
/**
* Reason for why flag was allowed or disallowed
* Used by admins for debugging player actions
*
*/
enum Why {
UNPROTECTED_WORLD,
OP,
BYPASS_EVERYWHERE,
BYPASS_ISLAND,
RANK_ALLOWED,
ALLOWED_IN_WORLD,
ALLOWED_ON_ISLAND,
NOT_ALLOWED_ON_ISLAND,
NOT_ALLOWED_IN_WORLD,
ERROR_NO_ASSOCIATED_USER,
NOT_SET,
SETTING_ALLOWED_ON_ISLAND,
SETTING_NOT_ALLOWED_ON_ISLAND,
SETTING_ALLOWED_IN_WORLD,
SETTING_NOT_ALLOWED_IN_WORLD
}
private BentoBox plugin = BentoBox.getInstance(); private BentoBox plugin = BentoBox.getInstance();
private User user = null; private User user = null;
private Why why;
/** /**
* @return the plugin * @return the plugin
@ -127,6 +153,7 @@ public abstract class AbstractFlagListener implements Listener {
|| (plugin.getIWM().isNether(loc.getWorld()) && !plugin.getIWM().isNetherIslands(loc.getWorld())) || (plugin.getIWM().isNether(loc.getWorld()) && !plugin.getIWM().isNetherIslands(loc.getWorld()))
|| (plugin.getIWM().isEnd(loc.getWorld()) && !plugin.getIWM().isEndIslands(loc.getWorld())) || (plugin.getIWM().isEnd(loc.getWorld()) && !plugin.getIWM().isEndIslands(loc.getWorld()))
) { ) {
report(user, e, loc, flag, Why.UNPROTECTED_WORLD);
return true; return true;
} }
// Get the island and if present // Get the island and if present
@ -134,6 +161,11 @@ public abstract class AbstractFlagListener implements Listener {
// Handle Settings Flag // Handle Settings Flag
if (flag.getType().equals(Flag.Type.SETTING)) { if (flag.getType().equals(Flag.Type.SETTING)) {
// If the island exists, return the setting, otherwise return the default setting for this flag // If the island exists, return the setting, otherwise return the default setting for this flag
if (island.isPresent()) {
report(user, e, loc, flag, island.map(x -> x.isAllowed(flag)).orElse(false) ? Why.SETTING_ALLOWED_ON_ISLAND : Why.SETTING_NOT_ALLOWED_ON_ISLAND);
} else {
report(user, e, loc, flag, flag.isSetForWorld(loc.getWorld()) ? Why.SETTING_ALLOWED_IN_WORLD : Why.SETTING_NOT_ALLOWED_IN_WORLD);
}
return island.map(x -> x.isAllowed(flag)).orElse(flag.isSetForWorld(loc.getWorld())); return island.map(x -> x.isAllowed(flag)).orElse(flag.isSetForWorld(loc.getWorld()));
} }
@ -144,11 +176,17 @@ public abstract class AbstractFlagListener implements Listener {
// TODO: is this the correct handling here? // TODO: is this the correct handling here?
if (user == null && !createEventUser(e)) { if (user == null && !createEventUser(e)) {
plugin.logError("Check island had no associated user! " + e.getEventName()); plugin.logError("Check island had no associated user! " + e.getEventName());
report(user, e, loc, flag, Why.ERROR_NO_ASSOCIATED_USER);
return false; return false;
} }
// Ops or "bypass everywhere" moderators can do anything // Ops or "bypass everywhere" moderators can do anything
if (user.isOp() || user.hasPermission(getIWM().getPermissionPrefix(loc.getWorld()) + ".mod.bypass." + flag.getID() + ".everywhere")) { if (user.isOp() || user.hasPermission(getIWM().getPermissionPrefix(loc.getWorld()) + ".mod.bypass." + flag.getID() + ".everywhere")) {
if (user.isOp()) {
report(user, e, loc, flag, Why.OP);
} else {
report(user, e, loc, flag, Why.BYPASS_EVERYWHERE);
}
user = null; user = null;
return true; return true;
} }
@ -158,27 +196,43 @@ public abstract class AbstractFlagListener implements Listener {
if (island.isPresent()) { if (island.isPresent()) {
// If it is not allowed on the island, "bypass island" moderators can do anything // If it is not allowed on the island, "bypass island" moderators can do anything
if (!island.get().isAllowed(user, flag) && !user.hasPermission(getIWM().getPermissionPrefix(loc.getWorld()) + ".mod.bypass." + flag.getID() + ".island")) { if (island.get().isAllowed(user, flag)) {
report(user, e, loc, flag, Why.RANK_ALLOWED);
user = null;
return true;
} else if (user.hasPermission(getIWM().getPermissionPrefix(loc.getWorld()) + ".mod.bypass." + flag.getID() + ".island")) {
report(user, e, loc, flag, Why.BYPASS_ISLAND);
user = null;
return true;
}
report(user, e, loc, flag, Why.NOT_ALLOWED_ON_ISLAND);
noGo(e, flag, silent); noGo(e, flag, silent);
// Clear the user for the next time // Clear the user for the next time
user = null; user = null;
return false; return false;
} else {
user = null;
return true;
}
} }
// The player is in the world, but not on an island, so general world settings apply // The player is in the world, but not on an island, so general world settings apply
if (!flag.isSetForWorld(loc.getWorld())) { if (flag.isSetForWorld(loc.getWorld())) {
report(user, e, loc, flag, Why.ALLOWED_IN_WORLD);
user = null;
return true;
} else {
report(user, e, loc, flag, Why.NOT_ALLOWED_IN_WORLD);
noGo(e, flag, silent); noGo(e, flag, silent);
user = null; user = null;
return false; return false;
} else {
user = null;
return true;
} }
} }
private void report(User user, Event e, Location loc, Flag flag, Why why) {
if (user != null && user.getPlayer().getMetadata(loc.getWorld().getName() + "_why_debug").stream()
.filter(p -> p.getOwningPlugin().equals(getPlugin())).findFirst().map(p -> p.asBoolean()).orElse(false)) {
plugin.log("Why: " + e.getEventName() + " in world " + loc.getWorld().getName() + " at " + Util.xyz(loc.toVector()));
plugin.log("Why: " + (user == null ? "Unknown" : user.getName()) + " " + flag.getID() + " - " + why.name());
}
}
/** /**
* Get the flag for this ID * Get the flag for this ID
* @param id - the flag ID * @param id - the flag ID
@ -203,4 +257,12 @@ public abstract class AbstractFlagListener implements Listener {
protected IslandWorldManager getIWM() { protected IslandWorldManager getIWM() {
return plugin.getIWM(); return plugin.getIWM();
} }
/**
* Get why the flag was allowed or not allowed
* @return the why - reason
*/
public Why getWhy() {
return why;
}
} }

View File

@ -192,6 +192,11 @@ commands:
description: "deletes a player's island" description: "deletes a player's island"
cannot-delete-team-leader: "&cAll island members have to be kicked from the island before deleting it." cannot-delete-team-leader: "&cAll island members have to be kicked from the island before deleting it."
deleted-island: "&aIsland at &e[xyz] &ahas been successfully deleted." deleted-island: "&aIsland at &e[xyz] &ahas been successfully deleted."
why:
parameters: "<player>"
description: "Toggle console protection debug reporting"
turning-on: "Turning on console debug for [name]"
turning-off: "Turning off console debug for [name]"
bentobox: bentobox:
description: "BentoBox admin command" description: "BentoBox admin command"
about: about: