Use the standard Bukkit command handling system.

Doing so will remove the possiblility for dynamic command alias assignment but makes factions compatible with all other
plugins doing stuff like blocking commands from being used (AntiGuest, NoCheatPlus, War etc) and plugins that log command
useage (Hawkeye etc).
This commit is contained in:
Olof Larsson 2013-01-03 08:23:46 +01:00
parent 31faf605dc
commit 16c69d67cd
10 changed files with 49 additions and 253 deletions

View File

@ -1,11 +1,11 @@
name: Factions name: Factions
version: 1.8.0 version: 1.8.1
main: com.massivecraft.factions.P main: com.massivecraft.factions.P
authors: [Olof Larsson, Brett Flannigan] authors: [Olof Larsson, Brett Flannigan]
softdepend: [PermissionsEx, Permissions, Essentials, EssentialsChat, HeroChat, iChat, LocalAreaChat, LWC, nChat, ChatManager, CAPI, AuthMe, Vault, Spout, WorldEdit, WorldGuard, AuthDB, CaptureThePoints, CombatTag] softdepend: [PermissionsEx, Permissions, Essentials, EssentialsChat, HeroChat, iChat, LocalAreaChat, LWC, nChat, ChatManager, CAPI, AuthMe, Vault, Spout, WorldEdit, WorldGuard, AuthDB, CaptureThePoints, CombatTag]
commands: commands:
factions: factions:
description: Reference command for Factions. description: The Factions base command
aliases: [f] aliases: [f]
permissions: permissions:
factions.kit.admin: factions.kit.admin:

View File

@ -11,8 +11,7 @@ import com.massivecraft.factions.struct.Rel;
public class Conf public class Conf
{ {
public static List<String> baseCommandAliases = new ArrayList<String>(); public final static transient List<String> baseCommandAliases = new ArrayList<String>();
public static boolean allowNoSlashCommand = true;
// Colors // Colors
public static ChatColor colorMember = ChatColor.GREEN; public static ChatColor colorMember = ChatColor.GREEN;

View File

@ -1,14 +1,13 @@
package com.massivecraft.factions; package com.massivecraft.factions;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.Set; import java.util.Set;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.Location; import org.bukkit.Location;
@ -40,8 +39,9 @@ import com.massivecraft.factions.struct.TerritoryAccess;
import com.massivecraft.factions.util.AutoLeaveTask; import com.massivecraft.factions.util.AutoLeaveTask;
import com.massivecraft.factions.util.LazyLocation; import com.massivecraft.factions.util.LazyLocation;
import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.MPlugin;
import com.massivecraft.factions.zcore.util.TextUtil;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.libs.com.google.gson.GsonBuilder; import org.bukkit.craftbukkit.libs.com.google.gson.GsonBuilder;
@ -81,7 +81,6 @@ public class P extends MPlugin
this.appearanceListener = new FactionsAppearanceListener(this); this.appearanceListener = new FactionsAppearanceListener(this);
} }
@Override @Override
public void onEnable() public void onEnable()
{ {
@ -109,7 +108,6 @@ public class P extends MPlugin
// Add Base Commands // Add Base Commands
this.cmdAutoHelp = new CmdAutoHelp(); this.cmdAutoHelp = new CmdAutoHelp();
this.cmdBase = new FCmdRoot(); this.cmdBase = new FCmdRoot();
this.getBaseCommands().add(cmdBase);
EssentialsFeatures.setup(); EssentialsFeatures.setup();
SpoutFeatures.setup(); SpoutFeatures.setup();
@ -135,9 +133,6 @@ public class P extends MPlugin
getServer().getPluginManager().registerEvents(this.serverListener, this); getServer().getPluginManager().registerEvents(this.serverListener, this);
getServer().getPluginManager().registerEvents(this.appearanceListener, this); getServer().getPluginManager().registerEvents(this.appearanceListener, this);
// since some other plugins execute commands directly through this command interface, provide it
this.getCommand(this.refCommand).setExecutor(this);
postEnable(); postEnable();
this.loadSuccessful = true; this.loadSuccessful = true;
} }
@ -196,33 +191,13 @@ public class P extends MPlugin
Conf.save(); Conf.save();
} }
@Override
public boolean logPlayerCommands()
{
return Conf.logPlayerCommands;
}
@Override
public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly)
{
if (sender instanceof Player && FactionsPlayerListener.preventCommand(commandString, (Player)sender)) return true;
return super.handleCommand(sender, commandString, testOnly);
}
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] split) public boolean onCommand(CommandSender sender, Command command, String label, String[] split)
{ {
// if bare command at this point, it has already been handled by MPlugin's command listeners this.cmdBase.execute(sender, new ArrayList<String>(Arrays.asList(split)));
if (split == null || split.length == 0) return true; return true;
// otherwise, needs to be handled; presumably another plugin directly ran the command
String cmd = Conf.baseCommandAliases.isEmpty() ? "/f" : "/" + Conf.baseCommandAliases.get(0);
return handleCommand(sender, cmd + " " + TextUtil.implode(Arrays.asList(split), " "), false);
} }
// -------------------------------------------- // // -------------------------------------------- //
// Functions for other plugins to hook into // Functions for other plugins to hook into
// -------------------------------------------- // // -------------------------------------------- //
@ -260,10 +235,12 @@ public class P extends MPlugin
} }
// Is this chat message actually a Factions command, and thus should be left alone by other plugins? // Is this chat message actually a Factions command, and thus should be left alone by other plugins?
/**
* @deprecated As of release 1.8.1 the normal Bukkit command-handling is used.
*/
public boolean isFactionsCommand(String check) public boolean isFactionsCommand(String check)
{ {
if (check == null || check.isEmpty()) return false; return false;
return this.handleCommand(null, check, true);
} }
// Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat // Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat

View File

@ -53,7 +53,6 @@ public class FCmdRoot extends FCommand
super(); super();
this.aliases.addAll(Conf.baseCommandAliases); this.aliases.addAll(Conf.baseCommandAliases);
this.aliases.removeAll(Collections.singletonList(null)); // remove any nulls from extra commas this.aliases.removeAll(Collections.singletonList(null)); // remove any nulls from extra commas
this.allowNoSlashAccess = Conf.allowNoSlashCommand;
//this.requiredArgs.add(""); //this.requiredArgs.add("");
//this.optionalArgs.put("","") //this.optionalArgs.put("","")

View File

@ -48,8 +48,6 @@ public class Econ
if ( ! Conf.econEnabled) if ( ! Conf.econEnabled)
P.p.log("NOTE: Economy is disabled. You can enable it with the command: f config econEnabled true"); P.p.log("NOTE: Economy is disabled. You can enable it with the command: f config econEnabled true");
//P.p.cmdBase.cmdHelp.updateHelp();
oldMoneyDoTransfer(); oldMoneyDoTransfer();
} }

View File

@ -1,5 +1,6 @@
package com.massivecraft.factions.listeners; package com.massivecraft.factions.listeners;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -14,6 +15,7 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerBucketFillEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerKickEvent;
@ -286,95 +288,61 @@ public class FactionsPlayerListener implements Listener
} }
} }
public static boolean preventCommand(String fullCmd, Player player) @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
{ {
if ((Conf.territoryNeutralDenyCommands.isEmpty() && Conf.territoryEnemyDenyCommands.isEmpty() && Conf.permanentFactionMemberDenyCommands.isEmpty())) // Get the player
return false; Player player = event.getPlayer();
fullCmd = fullCmd.toLowerCase();
FPlayer me = FPlayers.i.get(player); FPlayer me = FPlayers.i.get(player);
String shortCmd; // command without the slash at the beginning // With adminmode no commands are denied.
if (fullCmd.startsWith("/")) if (me.hasAdminMode()) return;
shortCmd = fullCmd.substring(1);
else
{
shortCmd = fullCmd;
fullCmd = "/" + fullCmd;
}
if // The full command is converted to lowercase and does include the slash in the front
( String fullCmd = event.getMessage().toLowerCase();
me.hasFaction()
&& if (me.hasFaction() && me.getFaction().getFlag(FFlag.PERMANENT) && isCommandInList(fullCmd, Conf.permanentFactionMemberDenyCommands))
! me.hasAdminMode()
&&
! Conf.permanentFactionMemberDenyCommands.isEmpty()
&&
me.getFaction().getFlag(FFlag.PERMANENT)
&&
isCommandInList(fullCmd, shortCmd, Conf.permanentFactionMemberDenyCommands.iterator())
)
{ {
me.msg("<b>You can't use the command \""+fullCmd+"\" because you are in a permanent faction."); me.msg("<b>You can't use the command \""+fullCmd+"\" because you are in a permanent faction.");
return true; event.setCancelled(true);
return;
} }
Rel rel = me.getRelationToLocation(); Rel rel = me.getRelationToLocation();
if (rel.isAtLeast(Rel.TRUCE) || Board.getFactionAt(me.getLastStoodAt()).isNone()) if (Board.getFactionAt(me.getLastStoodAt()).isNone()) return;
{
return false;
}
if if (rel == Rel.NEUTRAL && isCommandInList(fullCmd, Conf.territoryNeutralDenyCommands))
(
rel == Rel.NEUTRAL
&&
! Conf.territoryNeutralDenyCommands.isEmpty()
&&
! me.hasAdminMode()
&&
isCommandInList(fullCmd, shortCmd, Conf.territoryNeutralDenyCommands.iterator())
)
{ {
me.msg("<b>You can't use the command \""+fullCmd+"\" in neutral territory."); me.msg("<b>You can't use the command \""+fullCmd+"\" in neutral territory.");
return true; event.setCancelled(true);
return;
} }
if if (rel == Rel.ENEMY && isCommandInList(fullCmd, Conf.territoryEnemyDenyCommands))
(
rel == Rel.ENEMY
&&
! Conf.territoryEnemyDenyCommands.isEmpty()
&&
! me.hasAdminMode()
&&
isCommandInList(fullCmd, shortCmd, Conf.territoryEnemyDenyCommands.iterator())
)
{ {
me.msg("<b>You can't use the command \""+fullCmd+"\" in enemy territory."); me.msg("<b>You can't use the command \""+fullCmd+"\" in enemy territory.");
return true; event.setCancelled(true);
return;
} }
return false; return;
} }
private static boolean isCommandInList(String fullCmd, String shortCmd, Iterator<String> iter) private static boolean isCommandInList(String fullCmd, Collection<String> strings)
{ {
String cmdCheck; String shortCmd = fullCmd.substring(1);
Iterator<String> iter = strings.iterator();
while (iter.hasNext()) while (iter.hasNext())
{ {
cmdCheck = iter.next(); String cmdCheck = iter.next();
if (cmdCheck == null) if (cmdCheck == null)
{ {
iter.remove(); iter.remove();
continue; continue;
} }
cmdCheck = cmdCheck.toLowerCase(); cmdCheck = cmdCheck.toLowerCase();
if (fullCmd.startsWith(cmdCheck) || shortCmd.startsWith(cmdCheck)) if (fullCmd.startsWith(cmdCheck)) return true;
return true; if (shortCmd.startsWith(cmdCheck)) return true;
} }
return false; return false;
} }

View File

@ -27,7 +27,6 @@ public abstract class MCommand<T extends MPlugin>
// The different names this commands will react to // The different names this commands will react to
public List<String> aliases; public List<String> aliases;
public boolean allowNoSlashAccess;
// Information on the args // Information on the args
public List<String> requiredArgs; public List<String> requiredArgs;
@ -73,8 +72,6 @@ public abstract class MCommand<T extends MPlugin>
this.permission = null; this.permission = null;
this.allowNoSlashAccess = false;
this.subCommands = new ArrayList<MCommand<?>>(); this.subCommands = new ArrayList<MCommand<?>>();
this.aliases = new ArrayList<String>(); this.aliases = new ArrayList<String>();

View File

@ -7,7 +7,6 @@ import java.util.Map.Entry;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.craftbukkit.libs.com.google.gson.Gson; import org.bukkit.craftbukkit.libs.com.google.gson.Gson;
@ -36,15 +35,9 @@ public abstract class MPlugin extends JavaPlugin
protected boolean loadSuccessful = false; protected boolean loadSuccessful = false;
public boolean getAutoSave() {return this.autoSave;} public boolean getAutoSave() {return this.autoSave;}
public void setAutoSave(boolean val) {this.autoSave = val;} public void setAutoSave(boolean val) {this.autoSave = val;}
public String refCommand = "";
// Listeners // Listeners
private MPluginSecretPlayerListener mPluginSecretPlayerListener; public MPluginSecretPlayerListener mPluginSecretPlayerListener;
private MPluginSecretServerListener mPluginSecretServerListener;
// Our stored base commands
private List<MCommand<?>> baseCommands = new ArrayList<MCommand<?>>();
public List<MCommand<?>> getBaseCommands() { return this.baseCommands; }
// -------------------------------------------- // // -------------------------------------------- //
// ENABLE // ENABLE
@ -70,22 +63,8 @@ public abstract class MPlugin extends JavaPlugin
this.txt = new TextUtil(); this.txt = new TextUtil();
initTXT(); initTXT();
// attempt to get first command defined in plugin.yml as reference command, if any commands are defined in there
// reference command will be used to prevent "unknown command" console messages
try
{
Map<String, Map<String, Object>> refCmd = this.getDescription().getCommands();
if (refCmd != null && !refCmd.isEmpty())
this.refCommand = (String)(refCmd.keySet().toArray()[0]);
}
catch (ClassCastException ex) {}
// Create and register listeners // Create and register listeners
this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this); this.mPluginSecretPlayerListener = new MPluginSecretPlayerListener(this);
this.mPluginSecretServerListener = new MPluginSecretServerListener(this);
getServer().getPluginManager().registerEvents(this.mPluginSecretPlayerListener, this);
getServer().getPluginManager().registerEvents(this.mPluginSecretServerListener, this);
// Register recurring tasks // Register recurring tasks
long saveTicks = 20 * 60 * 30; // Approximately every 30 min long saveTicks = 20 * 60 * 30; // Approximately every 30 min
@ -174,72 +153,6 @@ public abstract class MPlugin extends JavaPlugin
} }
} }
// -------------------------------------------- //
// COMMAND HANDLING
// -------------------------------------------- //
// can be overridden by P method, to provide option
public boolean logPlayerCommands()
{
return true;
}
public boolean handleCommand(CommandSender sender, String commandString, boolean testOnly)
{
return handleCommand(sender, commandString, testOnly, false);
}
public boolean handleCommand(final CommandSender sender, String commandString, boolean testOnly, boolean async)
{
boolean noSlash = true;
if (commandString.startsWith("/"))
{
noSlash = false;
commandString = commandString.substring(1);
}
for (final MCommand<?> command : this.getBaseCommands())
{
if (noSlash && ! command.allowNoSlashAccess) continue;
for (String alias : command.aliases)
{
// disallow double-space after alias, so specific commands can be prevented (preventing "f home" won't prevent "f home")
if (commandString.startsWith(alias+" ")) return false;
if (commandString.startsWith(alias+" ") || commandString.equals(alias))
{
final List<String> args = new ArrayList<String>(Arrays.asList(commandString.split("\\s+")));
args.remove(0);
if (testOnly) return true;
if (async)
{
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable()
{
@Override
public void run()
{
command.execute(sender, args);
}
});
}
else
command.execute(sender, args);
return true;
}
}
}
return false;
}
public boolean handleCommand(CommandSender sender, String commandString)
{
return this.handleCommand(sender, commandString, false);
}
// -------------------------------------------- // // -------------------------------------------- //
// HOOKS // HOOKS
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -4,8 +4,6 @@ import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
import com.massivecraft.factions.zcore.persist.EM; import com.massivecraft.factions.zcore.persist.EM;
@ -15,36 +13,11 @@ import com.massivecraft.factions.zcore.persist.PlayerEntityCollection;
public class MPluginSecretPlayerListener implements Listener public class MPluginSecretPlayerListener implements Listener
{ {
private MPlugin p; public MPlugin p;
public MPluginSecretPlayerListener(MPlugin p) public MPluginSecretPlayerListener(MPlugin p)
{ {
this.p = p; this.p = p;
} Bukkit.getPluginManager().registerEvents(this, this.p);
@EventHandler(priority = EventPriority.LOW)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
{
if (event.isCancelled()) return;
if (p.handleCommand(event.getPlayer(), event.getMessage()))
{
if (p.logPlayerCommands())
Bukkit.getLogger().info("[PLAYER_COMMAND] "+event.getPlayer().getName()+": "+event.getMessage());
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.LOW)
public void onPlayerChat(AsyncPlayerChatEvent event)
{
if (event.isCancelled()) return;
if (p.handleCommand(event.getPlayer(), event.getMessage(), false, true))
{
if (p.logPlayerCommands())
Bukkit.getLogger().info("[PLAYER_COMMAND] "+event.getPlayer().getName()+": "+event.getMessage());
event.setCancelled(true);
}
} }
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)

View File

@ -1,28 +0,0 @@
package com.massivecraft.factions.zcore;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerCommandEvent;
public class MPluginSecretServerListener implements Listener
{
private MPlugin p;
public MPluginSecretServerListener(MPlugin p)
{
this.p = p;
}
@EventHandler(priority = EventPriority.LOWEST)
public void onServerCommand(ServerCommandEvent event)
{
if (event.getCommand().length() == 0) return;
if (p.handleCommand(event.getSender(), event.getCommand()))
{
event.setCommand(p.refCommand);
}
}
}