From 1e8478189ab8e3c19971d100eeb66ea74625a5e3 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Wed, 18 Dec 2013 10:32:15 +1100 Subject: [PATCH] Add VanillaCommand Wrapper to Support New Commands This implements testfor, setblock and summon, as well as the capacity to replace any command with its vanilla version. diff --git a/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java index 5271272..f8d2ecb 100644 --- a/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java +++ b/src/main/java/net/minecraft/server/CommandBlockListenerAbstract.java @@ -96,7 +96,7 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { // Make sure this is a valid command if (commandMap.getCommand(args[0]) == null) { - this.b = 0; + this.b = org.spigotmc.VanillaCommandWrapper.dispatch( sender, command ); // Spigot - Try vanilla commands return; } diff --git a/src/main/java/net/minecraft/server/CommandDispatcher.java b/src/main/java/net/minecraft/server/CommandDispatcher.java index e63f17c..e58be15 100644 --- a/src/main/java/net/minecraft/server/CommandDispatcher.java +++ b/src/main/java/net/minecraft/server/CommandDispatcher.java @@ -62,7 +62,7 @@ public class CommandDispatcher extends CommandHandler implements ICommandDispatc public void a(ICommandListener icommandlistener, int i, String s, Object... aobject) { boolean flag = true; - if (icommandlistener instanceof CommandBlockListenerAbstract && !MinecraftServer.getServer().worldServer[0].getGameRules().getBoolean("commandBlockOutput")) { + if (icommandlistener instanceof CommandBlockListenerAbstract && !MinecraftServer.getServer().worlds.get(0).getGameRules().getBoolean("commandBlockOutput")) { // Spigot - worldServer -> worlds flag = false; } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 0ac8f52..1648d0e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -548,6 +548,12 @@ public final class CraftServer implements Server { if (commandMap.dispatch(sender, commandLine)) { return true; } + // Spigot Start - Try vanilla commands + if ( org.spigotmc.VanillaCommandWrapper.dispatch( sender, commandLine ) != -1 ) + { + return true; + } + // Spigot End sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); @@ -1403,15 +1409,27 @@ public final class CraftServer implements Server { } // Spigot End - List completions = null; + // Spigot Start + List completions = new ArrayList(); try { - completions = getCommandMap().tabComplete(player, message.substring(1)); + message = message.substring( 1 ); + List bukkitCompletions = getCommandMap().tabComplete( player, message ); + if ( bukkitCompletions != null ) + { + completions.addAll( bukkitCompletions ); + } + List vanillaCompletions = org.spigotmc.VanillaCommandWrapper.complete( player, message ); + if ( vanillaCompletions != null ) + { + completions.addAll( vanillaCompletions ); + } + // Spigot End } catch (CommandException ex) { player.sendMessage(ChatColor.RED + "An internal error occurred while attempting to tab-complete this command"); getLogger().log(Level.SEVERE, "Exception when " + player.getName() + " attempted to tab complete " + message, ex); } - return completions == null ? ImmutableList.of() : completions; + return completions; // Spigot } public List tabCompleteChat(Player player, String message) { diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java index c4a5488..b3f2647 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,6 +15,7 @@ import net.minecraft.server.MinecraftServer; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; +import org.bukkit.command.SimpleCommandMap; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.craftbukkit.command.TicksPerSecondCommand; @@ -204,4 +206,17 @@ public class SpigotConfig System.setProperty( "io.netty.eventLoopThreads", Integer.toString( count ) ); Bukkit.getLogger().log( Level.INFO, "Using {0} threads for Netty based IO", count ); } + + private static void replaceCommands() + { + if ( config.contains( "replace-commands" ) ) { + set( "commands.replace-commands", config.getStringList( "replace-commands" ) ); + config.set( "replace-commands", null ); + } + for ( String command : (List) getList( "commands.replace-commands", Arrays.asList( "setblock", "summon", "testforblock", "tellraw" ) ) ) + { + SimpleCommandMap.removeFallback( command ); + VanillaCommandWrapper.allowedCommands.add( command ); + } + } } diff --git a/src/main/java/org/spigotmc/VanillaCommandWrapper.java b/src/main/java/org/spigotmc/VanillaCommandWrapper.java new file mode 100644 index 0000000..a6c76cc --- /dev/null +++ b/src/main/java/org/spigotmc/VanillaCommandWrapper.java @@ -0,0 +1,194 @@ +package org.spigotmc; + +import com.google.common.collect.ImmutableList; +import net.minecraft.server.ChatComponentText; +import net.minecraft.server.ChunkCoordinates; +import net.minecraft.server.EntityMinecartCommandBlock; +import net.minecraft.server.IChatBaseComponent; +import net.minecraft.server.ICommandListener; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.TileEntityCommand; +import net.minecraft.server.World; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.block.Block; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.command.CraftBlockCommandSender; +import org.bukkit.craftbukkit.entity.CraftMinecartCommand; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class VanillaCommandWrapper +{ + + public static final HashSet allowedCommands = new HashSet(); + + public static int dispatch(CommandSender sender, String commandLine) + { + int pos = commandLine.indexOf( ' ' ); + if ( pos == -1 ) + { + pos = commandLine.length(); + } + String name = commandLine.substring( 0, pos ); + if ( !allowedCommands.contains( name ) ) + { + return -1; + } + if ( !sender.hasPermission( "bukkit.command." + name ) ) + { + sender.sendMessage( ChatColor.RED + "You do not have permission for this command" ); + return 0; + } + ICommandListener listener = getListener( sender ); + if ( listener == null ) + { + return -1; + } + return MinecraftServer.getServer().getCommandHandler().a( listener, commandLine ); + } + + public static List complete(CommandSender sender, String commandLine) + { + int pos = commandLine.indexOf( ' ' ); + if ( pos == -1 ) + { + List completions = new ArrayList(); + commandLine = commandLine.toLowerCase(); + for ( String command : allowedCommands ) + { + if ( command.startsWith( commandLine ) && sender.hasPermission( "bukkit.command." + command ) ) + { + completions.add( "/" + command ); + } + } + return completions; + } + String name = commandLine.substring( 0, pos ); + if ( !allowedCommands.contains( name ) || !sender.hasPermission( "bukkit.command." + name ) ) + { + return ImmutableList.of(); + } + ICommandListener listener = getListener( sender ); + if ( listener == null ) + { + return ImmutableList.of(); + } + return MinecraftServer.getServer().getCommandHandler().b( listener, commandLine ); + } + + private static ICommandListener getListener(CommandSender sender) + { + if ( sender instanceof CraftPlayer ) + { + return new PlayerListener( ( (CraftPlayer) sender ).getHandle() ); + } + if ( sender instanceof CraftBlockCommandSender ) + { + CraftBlockCommandSender commandBlock = (CraftBlockCommandSender) sender; + Block block = commandBlock.getBlock(); + return ( (TileEntityCommand) ( (CraftWorld) block.getWorld() ).getTileEntityAt( block.getX(), block.getY(), block.getZ() ) ).a(); + } + if ( sender instanceof CraftMinecartCommand ) + { + return ( (EntityMinecartCommandBlock) ( (CraftMinecartCommand) sender ).getHandle() ).e(); + } + return new ConsoleListener(sender); // Assume console/rcon + } + + private static class PlayerListener implements ICommandListener + { + + private final ICommandListener handle; + + public PlayerListener(ICommandListener handle) + { + this.handle = handle; + } + + @Override + public String getName() + { + return handle.getName(); + } + + @Override + public IChatBaseComponent getScoreboardDisplayName() + { + return handle.getScoreboardDisplayName(); + } + + @Override + public void sendMessage(IChatBaseComponent iChatBaseComponent) + { + handle.sendMessage( iChatBaseComponent ); + } + + @Override + public boolean a(int i, String s) + { + return true; + } + + @Override + public ChunkCoordinates getChunkCoordinates() + { + return handle.getChunkCoordinates(); + } + + @Override + public World getWorld() + { + return handle.getWorld(); + } + } + + private static class ConsoleListener implements ICommandListener { + + private final CommandSender sender; + + public ConsoleListener( CommandSender sender ) + { + this.sender = sender; + } + + @Override + public String getName() + { + return sender.getName(); + } + + @Override + public IChatBaseComponent getScoreboardDisplayName() + { + return new ChatComponentText( getName() ); + } + + @Override + public void sendMessage( IChatBaseComponent iChatBaseComponent ) + { + sender.sendMessage( iChatBaseComponent.e() ); + } + + @Override + public boolean a( int i, String s ) + { + return true; + } + + @Override + public ChunkCoordinates getChunkCoordinates() + { + return new ChunkCoordinates( 0, 0, 0 ); + } + + @Override + public World getWorld() + { + return MinecraftServer.getServer().getWorld(); + } + } +} -- 1.8.3.2