--- a/net/minecraft/server/CommandBlockListenerAbstract.java
+++ b/net/minecraft/server/CommandBlockListenerAbstract.java
@@ -4,6 +4,13 @@
 import java.util.Date;
 import javax.annotation.Nullable;
 
+// CraftBukkit start
+import java.util.ArrayList;
+import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
+import com.google.common.base.Joiner;
+import java.util.logging.Level;
+// CraftBukkit end
+
 public abstract class CommandBlockListenerAbstract implements ICommandListener {
 
     private static final SimpleDateFormat a = new SimpleDateFormat("HH:mm:ss");
@@ -13,6 +20,7 @@
     private String e = "";
     private String f = "@";
     private final CommandObjectiveExecutor g = new CommandObjectiveExecutor();
+    protected org.bukkit.command.CommandSender sender; // CraftBukkit - add sender
 
     public CommandBlockListenerAbstract() {}
 
@@ -92,7 +100,9 @@
 
                 try {
                     this.d = null;
-                    this.b = icommandhandler.a(this, this.e);
+                    // CraftBukkit start - Handle command block commands using Bukkit dispatcher
+                    this.b = executeSafely(this, sender, this.e);
+                    // CraftBukkit end
                 } catch (Throwable throwable) {
                     CrashReport crashreport = CrashReport.a(throwable, "Executing command block");
                     CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Command to be executed");
@@ -124,6 +134,138 @@
         }
     }
 
+    public static int executeSafely(ICommandListener sender, org.bukkit.command.CommandSender bSender, String command) {
+        try {
+            return executeCommand(sender, bSender, command);
+        } catch (CommandException commandexception) {
+            // Taken from CommandHandler
+            ChatMessage chatmessage = new ChatMessage(commandexception.getMessage(), commandexception.getArgs());
+            chatmessage.getChatModifier().setColor(EnumChatFormat.RED);
+            sender.sendMessage(chatmessage);
+        }
+
+        return 0;
+    }
+
+    // CraftBukkit start
+    public static int executeCommand(ICommandListener sender, org.bukkit.command.CommandSender bSender, String command) throws CommandException {
+        org.bukkit.command.SimpleCommandMap commandMap = sender.getWorld().getServer().getCommandMap();
+        Joiner joiner = Joiner.on(" ");
+        if (command.startsWith("/")) {
+            command = command.substring(1);
+        }
+        String[] args = command.split(" ");
+        ArrayList<String[]> commands = new ArrayList<String[]>();
+
+        String cmd = args[0];
+        if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length());
+        if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length());
+
+        // Block disallowed commands
+        if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op")
+                || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip")
+                || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) {
+            return 0;
+        }
+
+        // Handle vanilla commands;
+        org.bukkit.command.Command commandBlockCommand = commandMap.getCommand(args[0]);
+        if (sender.getWorld().getServer().getCommandBlockOverride(args[0])) {
+            commandBlockCommand = commandMap.getCommand("minecraft:" + args[0]);
+        }
+        if (commandBlockCommand instanceof VanillaCommandWrapper) {
+            command = command.trim();
+            if (command.startsWith("/")) {
+                command = command.substring(1);
+            }
+            String as[] = command.split(" ");
+            as = VanillaCommandWrapper.dropFirstArgument(as);
+            if (!((VanillaCommandWrapper) commandBlockCommand).testPermission(bSender)) {
+                return 0;
+            }
+            return ((VanillaCommandWrapper) commandBlockCommand).dispatchVanillaCommand(bSender, sender, as);
+        }
+
+        // Make sure this is a valid command
+        if (commandMap.getCommand(args[0]) == null) {
+            return 0;
+        }
+
+        commands.add(args);
+
+        // Find positions of command block syntax, if any        
+        WorldServer[] prev = MinecraftServer.getServer().worldServer;
+        MinecraftServer server = MinecraftServer.getServer();
+        server.worldServer = new WorldServer[server.worlds.size()];
+        server.worldServer[0] = (WorldServer) sender.getWorld();
+        int bpos = 0;
+        for (int pos = 1; pos < server.worldServer.length; pos++) {
+            WorldServer world = server.worlds.get(bpos++);
+            if (server.worldServer[0] == world) {
+                pos--;
+                continue;
+            }
+            server.worldServer[pos] = world;
+        }
+        try {
+            ArrayList<String[]> newCommands = new ArrayList<String[]>();
+            for (int i = 0; i < args.length; i++) {
+                if (PlayerSelector.isPattern(args[i])) {
+                    for (int j = 0; j < commands.size(); j++) {
+                        newCommands.addAll(buildCommands(sender, commands.get(j), i));
+                    }
+                    ArrayList<String[]> temp = commands;
+                    commands = newCommands;
+                    newCommands = temp;
+                    newCommands.clear();
+                }
+            }
+        } finally {
+            MinecraftServer.getServer().worldServer = prev;
+        }
+
+        int completed = 0;
+
+        // Now dispatch all of the commands we ended up with
+        for (int i = 0; i < commands.size(); i++) {
+            try {
+                if (commandMap.dispatch(bSender, joiner.join(java.util.Arrays.asList(commands.get(i))))) {
+                    completed++;
+                }
+            } catch (Throwable exception) {
+                if (sender.f() instanceof EntityMinecartCommandBlock) {
+                    MinecraftServer.getServer().server.getLogger().log(Level.WARNING, String.format("MinecartCommandBlock at (%d,%d,%d) failed to handle command", sender.getChunkCoordinates().getX(), sender.getChunkCoordinates().getY(), sender.getChunkCoordinates().getZ()), exception);
+                } else if (sender instanceof CommandBlockListenerAbstract) {
+                    CommandBlockListenerAbstract listener = (CommandBlockListenerAbstract) sender;
+                    MinecraftServer.getServer().server.getLogger().log(Level.WARNING, String.format("CommandBlock at (%d,%d,%d) failed to handle command", listener.getChunkCoordinates().getX(), listener.getChunkCoordinates().getY(), listener.getChunkCoordinates().getZ()), exception);
+                } else {
+                    MinecraftServer.getServer().server.getLogger().log(Level.WARNING, String.format("Unknown CommandBlock failed to handle command"), exception);
+                }
+            }
+        }
+
+        return completed;
+    }
+
+    private static ArrayList<String[]> buildCommands(ICommandListener sender, String[] args, int pos) throws CommandException {
+        ArrayList<String[]> commands = new ArrayList<String[]>();
+        java.util.List<EntityPlayer> players = (java.util.List<EntityPlayer>)PlayerSelector.getPlayers(sender, args[pos], EntityPlayer.class);
+
+        if (players != null) {
+            for (EntityPlayer player : players) {
+                if (player.world != sender.getWorld()) {
+                    continue;
+                }
+                String[] command = args.clone();
+                command[pos] = player.getName();
+                commands.add(command);
+            }
+        }
+
+        return commands;
+    }
+    // CraftBukkit end
+
     public String getName() {
         return this.f;
     }