diff --git a/paper-api/pom.xml b/paper-api/pom.xml
index cec0b8025d..abfedfd6ea 100644
--- a/paper-api/pom.xml
+++ b/paper-api/pom.xml
@@ -2,7 +2,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.bukkit</groupId>
     <artifactId>bukkit</artifactId>
-    <version>1.2.5-R5.1-SNAPSHOT</version>
+    <version>1.3.1-R0.1-SNAPSHOT</version>
     <name>Bukkit</name>
     <url>http://www.bukkit.org</url>
 
diff --git a/paper-api/src/main/java/org/bukkit/GameMode.java b/paper-api/src/main/java/org/bukkit/GameMode.java
index b81b069ca4..46ba7f2d0a 100644
--- a/paper-api/src/main/java/org/bukkit/GameMode.java
+++ b/paper-api/src/main/java/org/bukkit/GameMode.java
@@ -11,14 +11,19 @@ import com.google.common.collect.Maps;
  */
 public enum GameMode {
     /**
-     * Creative mode may fly, build instantly, become invulnerable and create free items
+     * Creative mode may fly, build instantly, become invulnerable and create free items.
      */
     CREATIVE(1),
 
     /**
      * Survival mode is the "normal" gameplay type, with no special features.
      */
-    SURVIVAL(0);
+    SURVIVAL(0),
+
+    /**
+     * Adventure mode cannot break blocks, use chat, use buckets, etc.
+     */
+    ADVENTURE(2);
 
     private final int value;
     private final static Map<Integer, GameMode> BY_ID = Maps.newHashMap();
diff --git a/paper-api/src/main/java/org/bukkit/Material.java b/paper-api/src/main/java/org/bukkit/Material.java
index 74edacf059..7ae6045f72 100644
--- a/paper-api/src/main/java/org/bukkit/Material.java
+++ b/paper-api/src/main/java/org/bukkit/Material.java
@@ -211,9 +211,9 @@ public enum Material {
     GRILLED_PORK(320),
     PAINTING(321),
     GOLDEN_APPLE(322),
-    SIGN(323, 1),
+    SIGN(323, 16),
     WOOD_DOOR(324, 1),
-    BUCKET(325, 1),
+    BUCKET(325, 16),
     WATER_BUCKET(326, 1),
     LAVA_BUCKET(327, 1),
     MINECART(328, 1),
@@ -290,7 +290,23 @@ public enum Material {
     RECORD_8(2263, 1),
     RECORD_9(2264, 1),
     RECORD_10(2265, 1),
-    RECORD_11(2266, 1);
+    RECORD_11(2266, 1),
+    WOOD_DOUBLE_STEP(125, Step.class),
+    WOOD_STEP(126, Step.class),
+    COCOA(127),
+    SANDSTONE_STAIRS(128, Stairs.class),
+    EMERALD_ORE(129),
+    ENDER_CHEST(130),
+    TRIPWIRE_HOOK(131, Button.class),
+    TRIPWIRE(132),
+    EMERALD_BLOCK(133),
+    SPRUCE_WOOD_STAIRS(134),
+    BIRCH_WOOD_STAIRS(135),
+    JUNGLE_WOOD_STAIRS(136),
+    BOOK_AND_QUILL(386, 1),
+    WRITTEN_BOOK(387, 1),
+    EMERALD(388, 64);
+    
 
     private final int id;
     private final Class<? extends MaterialData> data;
diff --git a/paper-api/src/main/java/org/bukkit/command/Command.java b/paper-api/src/main/java/org/bukkit/command/Command.java
index 5a7015911c..fca9c91dd7 100644
--- a/paper-api/src/main/java/org/bukkit/command/Command.java
+++ b/paper-api/src/main/java/org/bukkit/command/Command.java
@@ -47,6 +47,22 @@ public abstract class Command {
      */
     public abstract boolean execute(CommandSender sender, String commandLabel, String[] args);
 
+    /**
+     * Executed on tab completion for this command, returning a list of options
+     * the player can tab through.
+     * <p />
+     * By returning null, you tell Bukkit to generate a list of players to send
+     * to the sender.
+     * By returning an empty list, no options will be sent.
+     *
+     * @param sender Source object which is executing this command
+     * @param args All arguments passed to the command, split via ' '
+     * @return null to generate a Player list, otherwise a list of options
+     */
+    public List<String> tabComplete(CommandSender sender, String[] args) {
+        return null;
+    }
+
     /**
      * Returns the name of this command
      *
@@ -110,7 +126,7 @@ public abstract class Command {
         if ((permission == null) || (permission.length() == 0)) {
             return true;
         }
-        
+
         for (String p : permission.split(";")) {
             if (target.hasPermission(p)) {
                 return true;
diff --git a/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java b/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java
index e4a7ba3e7a..384a01ec25 100644
--- a/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java
+++ b/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java
@@ -39,6 +39,8 @@ public class SimpleCommandMap implements CommandMap {
         fallbackCommands.add(new ExpCommand());
         fallbackCommands.add(new ToggleDownfallCommand());
         fallbackCommands.add(new BanListCommand());
+        fallbackCommands.add(new DefaultGameModeCommand());
+        fallbackCommands.add(new SeedCommand());
     }
 
     public SimpleCommandMap(final Server server) {
@@ -139,7 +141,7 @@ public class SimpleCommandMap implements CommandMap {
 
         return null;
     }
-    
+
     public Set<VanillaCommand> getFallbackCommands() {
         return Collections.unmodifiableSet(fallbackCommands);
     }
diff --git a/paper-api/src/main/java/org/bukkit/command/TabCommandExecutor.java b/paper-api/src/main/java/org/bukkit/command/TabCommandExecutor.java
new file mode 100644
index 0000000000..b2ee58c525
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/command/TabCommandExecutor.java
@@ -0,0 +1,10 @@
+package org.bukkit.command;
+
+import java.util.List;
+
+/**
+ * Represents a class which can handle command tab completion and commands
+ */
+public interface TabCommandExecutor extends CommandExecutor {
+    public List<String> onTabComplete();
+}
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/BanCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/BanCommand.java
index aa7f353434..76d4cf6fd8 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/BanCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/BanCommand.java
@@ -1,33 +1,44 @@
 package org.bukkit.command.defaults;
 
+import java.util.List;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
 
 public class BanCommand extends VanillaCommand {
     public BanCommand() {
         super("ban");
         this.description = "Prevents the specified player from using this server";
-        this.usageMessage = "/ban <player>";
+        this.usageMessage = "/ban <player> [reason ...]";
         this.setPermission("bukkit.command.ban.player");
     }
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 1)  {
+        if (args.length == 0)  {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
 
+        // TODO: Ban Reason support
         Bukkit.getOfflinePlayer(args[0]).setBanned(true);
-        if (Bukkit.getPlayer(args[0]) != null) Bukkit.getPlayer(args[0]).kickPlayer("Banned by admin.");
-        Command.broadcastCommandMessage(sender, "Banning " + args[0]);
 
+        Player player = Bukkit.getPlayer(args[0]);
+        if (player != null) {
+            player.kickPlayer("Banned by admin.");
+        }
+
+        sender.sendMessage("Banned player " + args[0]);
         return true;
     }
 
+    @Override
+    public List<String> tabComplete(CommandSender sender, String[] args) {
+        return args.length >= 1 ? null : EMPTY_LIST;
+    }
+
     @Override
     public boolean matches(String input) {
         return input.equalsIgnoreCase("ban");
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/BanIpCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/BanIpCommand.java
index bb08989069..1bb6b0c511 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/BanIpCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/BanIpCommand.java
@@ -1,32 +1,58 @@
 package org.bukkit.command.defaults;
 
+import java.util.List;
+import java.util.regex.Pattern;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
 
 public class BanIpCommand extends VanillaCommand {
+    public static final Pattern ipValidity = Pattern.compile("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
+
     public BanIpCommand() {
         super("ban-ip");
         this.description = "Prevents the specified IP address from using this server";
-        this.usageMessage = "/ban-ip <address>";
+        this.usageMessage = "/ban-ip <address|player> [reason ...]";
         this.setPermission("bukkit.command.ban.ip");
     }
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 1)  {
+        if (args.length < 1)  {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
 
-        Bukkit.banIP(args[0]);
-        Command.broadcastCommandMessage(sender, "Banning ip " + args[0]);
+        // TODO: Ban Reason support
+        if (ipValidity.matcher(args[0]).matches()) {
+            processIPBan(args[0], sender);
+        } else {
+            Player player = Bukkit.getPlayer(args[0]);
+
+            if (player == null) {
+                sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
+                return false;
+            }
+            processIPBan(player.getAddress().getAddress().getHostAddress(), sender);
+        }
 
         return true;
     }
 
+    @Override
+    public List<String> tabComplete(CommandSender sender, String[] args) {
+        return args.length >= 1 ? null : EMPTY_LIST;
+    }
+
+    private void processIPBan(String ip, CommandSender sender) {
+        // TODO: Kick on ban
+        Bukkit.banIP(ip);
+
+        sender.sendMessage("Banned IP Address " + ip);
+    }
+
     @Override
     public boolean matches(String input) {
         return input.equalsIgnoreCase("ban-ip");
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/BanListCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/BanListCommand.java
index 57c37c44d3..668a487737 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/BanListCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/BanListCommand.java
@@ -1,7 +1,7 @@
 package org.bukkit.command.defaults;
 
+import java.util.List;
 import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
 import org.bukkit.OfflinePlayer;
 import org.bukkit.command.CommandSender;
 
@@ -9,7 +9,7 @@ public class BanListCommand extends VanillaCommand {
     public BanListCommand() {
         super("banlist");
         this.description = "View all players banned from this server";
-        this.usageMessage = "/banlist";
+        this.usageMessage = "/banlist [ips|players]";
         this.setPermission("bukkit.command.ban.list");
     }
 
@@ -17,19 +17,31 @@ public class BanListCommand extends VanillaCommand {
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
 
-        StringBuilder message = new StringBuilder().append(ChatColor.GRAY).append("Ban list: ");
+        // TODO: ips support
+        StringBuilder message = new StringBuilder();
+        OfflinePlayer[] banlist = Bukkit.getServer().getBannedPlayers().toArray(new OfflinePlayer[0]);
 
-        int count = 0;
-        for (OfflinePlayer p : Bukkit.getServer().getBannedPlayers()) {
-            if (count++ > 0) {
-                message.append(", ");
+        for (int x = 0; x < banlist.length; x++) {
+            if (x != 0) {
+                if (x == banlist.length - 1) {
+                    message.append(" and ");
+                } else {
+                    message.append(", ");
+                }
             }
-            message.append(p.getName());
+            message.append(banlist[x].getName());
         }
+
+        sender.sendMessage("There are " + banlist.length + " total banned players:");
         sender.sendMessage(message.toString());
         return true;
     }
 
+    @Override
+    public List<String> tabComplete(CommandSender sender, String[] args) {
+        return args.length >= 1 ? null : EMPTY_LIST;
+    }
+
     @Override
     public boolean matches(String input) {
         return input.equalsIgnoreCase("banlist");
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/DefaultGameModeCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/DefaultGameModeCommand.java
new file mode 100644
index 0000000000..d323bee601
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/DefaultGameModeCommand.java
@@ -0,0 +1,52 @@
+package org.bukkit.command.defaults;
+
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.command.CommandSender;
+
+public class DefaultGameModeCommand extends VanillaCommand {
+    public DefaultGameModeCommand() {
+        super("defaultgamemode");
+        this.description = "Set the default gamemode";
+        this.usageMessage = "/defaultgamemode <mode>";
+        this.setPermission("bukkit.command.defaultgamemode");
+    }
+
+    @Override
+    public boolean matches(String input) {
+        return input.equalsIgnoreCase(this.getName());
+    }
+
+    @Override
+    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+        if (args.length == 0) {
+            sender.sendMessage("Useage: " + usageMessage);
+            return false;
+        }
+
+        String modeArg = args[0];
+        int value = -1;
+
+        try {
+            value = Integer.parseInt(modeArg);
+        } catch (NumberFormatException ex) {}
+
+        GameMode mode = GameMode.getByValue(value);
+
+        if (mode == null) {
+            if (modeArg.equalsIgnoreCase("creative") || modeArg.equalsIgnoreCase("c")) {
+                mode = GameMode.CREATIVE;
+            } else if (modeArg.equalsIgnoreCase("adventure") || modeArg.equalsIgnoreCase("a")) {
+                mode = GameMode.ADVENTURE;
+            } else {
+                mode = GameMode.SURVIVAL;
+            }
+        }
+
+        Bukkit.getServer().setDefaultGameMode(mode);
+        sender.sendMessage("Default game mode set to " + mode.toString().toLowerCase());
+
+        return true;
+    }
+
+}
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/DeopCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/DeopCommand.java
index e5c9a1ec65..291c049772 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/DeopCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/DeopCommand.java
@@ -1,9 +1,9 @@
 package org.bukkit.command.defaults;
 
+import java.util.List;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.OfflinePlayer;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
@@ -18,13 +18,11 @@ public class DeopCommand extends VanillaCommand {
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 1)  {
+        if (args.length != 1 || args[0].length() == 0) {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
 
-        Command.broadcastCommandMessage(sender, "De-opping " + args[0]);
-
         OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]);
         player.setOp(false);
 
@@ -32,9 +30,15 @@ public class DeopCommand extends VanillaCommand {
             ((Player) player).sendMessage(ChatColor.YELLOW + "You are no longer op!");
         }
 
+        sender.sendMessage("De-opped " + args[0]);
         return true;
     }
 
+    @Override
+    public List<String> tabComplete(CommandSender sender, String[] args) {
+        return args.length >= 1 ? null : EMPTY_LIST;
+    }
+
     @Override
     public boolean matches(String input) {
         return input.equalsIgnoreCase("deop");
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/ExpCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/ExpCommand.java
index 674e6e009d..478100212a 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/ExpCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/ExpCommand.java
@@ -2,7 +2,6 @@ package org.bukkit.command.defaults;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
@@ -10,32 +9,31 @@ public class ExpCommand extends VanillaCommand {
     public ExpCommand() {
         super("xp");
         this.description = "Gives the specified player a certain amount of experience";
-        this.usageMessage = "/xp <player> <amount>";
+        this.usageMessage = "/xp <amount> [player]";
         this.setPermission("bukkit.command.xp");
     }
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 2) {
+        if (args.length < 1) {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
+        int exp = getInteger(sender, args[0], 0, 5000);
+        Player player = null;
 
-        Player player = Bukkit.getPlayerExact(args[0]);
+        if (args.length > 1) {
+            player = Bukkit.getPlayer(args[1]);
+        } else if (sender instanceof Player) {
+            player = (Player) sender;
+        }
 
         if (player != null) {
-            try {
-                int exp = Integer.parseInt(args[1]);
-
-                Command.broadcastCommandMessage(sender, "Giving " + exp + " exp to " + player.getName());
-
-                player.giveExp(exp);
-            } catch (NumberFormatException ex) {
-                sender.sendMessage("Invalid exp count: " + args[1]);
-            }
+            player.giveExp(exp);
+            sender.sendMessage("Giving " + exp + " exp to " + player.getName());
         } else {
-            sender.sendMessage("Can't find user " + args[0]);
+            sender.sendMessage("Can't find user, was one provided?\n" + ChatColor.RED + "Usage: " + usageMessage);
         }
 
         return true;
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/GameModeCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/GameModeCommand.java
index c1694219e0..90f3ea533e 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/GameModeCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/GameModeCommand.java
@@ -2,7 +2,6 @@ package org.bukkit.command.defaults;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.GameMode;
@@ -11,46 +10,59 @@ public class GameModeCommand extends VanillaCommand {
     public GameModeCommand() {
         super("gamemode");
         this.description = "Changes the player to a specific game mode";
-        this.usageMessage = "/gamemode <player> <gamemode>";
+        this.usageMessage = "/gamemode <mode> [player]";
         this.setPermission("bukkit.command.gamemode");
     }
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 2) {
+        if (args.length == 0) {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
 
-        Player player = Bukkit.getPlayerExact(args[0]);
+        String modeArg = args[0];
+        String playerArg = sender.getName();
+
+        if (args.length == 2) {
+            playerArg = args[1];
+        }
+
+        Player player = Bukkit.getPlayerExact(playerArg);
 
         if (player != null) {
             int value = -1;
 
             try {
-                value = Integer.parseInt(args[1]);
+                value = Integer.parseInt(modeArg);
             } catch (NumberFormatException ex) {}
 
             GameMode mode = GameMode.getByValue(value);
 
-            if (mode != null) {
-                if (mode != player.getGameMode()) {
-                    Command.broadcastCommandMessage(sender, "Setting " + player.getName() + " to game mode " + mode.getValue());
-
-                    player.setGameMode(mode);
-
-                    if (mode != player.getGameMode()) {
-                        Command.broadcastCommandMessage(sender, "The game mode change for " + player.getName() + " was cancelled!");
-                    }
+            if (mode == null) {
+                if (modeArg.equalsIgnoreCase("creative") || modeArg.equalsIgnoreCase("c")) {
+                    mode = GameMode.CREATIVE;
+                } else if (modeArg.equalsIgnoreCase("adventure") || modeArg.equalsIgnoreCase("a")) {
+                    mode = GameMode.ADVENTURE;
                 } else {
-                    sender.sendMessage(player.getName() + " already has game mode " + mode.getValue());
+                    mode = GameMode.SURVIVAL;
+                }
+            }
+
+            if (mode != player.getGameMode()) {
+                player.setGameMode(mode);
+
+                if (mode != player.getGameMode()) {
+                    sender.sendMessage("Game mode change for " + player.getName() + " failed!");
+                } else {
+                    sender.sendMessage("Game mode set to " + mode.toString() + " for " + player.getName());
                 }
             } else {
-                sender.sendMessage("There is no game mode with id " + args[1]);
+                sender.sendMessage(player.getName() + " already has game mode " + mode.getValue());
             }
         } else {
-            sender.sendMessage("Can't find user " + args[0]);
+            sender.sendMessage("Can't find user " + playerArg);
         }
 
         return true;
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/GiveCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/GiveCommand.java
index fffed0c9a3..a970d39232 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/GiveCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/GiveCommand.java
@@ -3,7 +3,6 @@ package org.bukkit.command.defaults;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
@@ -19,7 +18,7 @@ public class GiveCommand extends VanillaCommand {
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if ((args.length < 2) || (args.length > 4)) {
+        if ((args.length < 2)) {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
@@ -30,18 +29,12 @@ public class GiveCommand extends VanillaCommand {
             Material material = Material.matchMaterial(args[1]);
 
             if (material != null) {
-                Command.broadcastCommandMessage(sender, "Giving " + player.getName() + " some " + material.getId() + " (" + material + ")");
-
                 int amount = 1;
                 short data = 0;
 
                 if (args.length >= 3) {
-                    try {
-                        amount = Integer.parseInt(args[2]);
-                    } catch (NumberFormatException ex) {}
+                    amount = this.getInteger(sender, args[2], 1, 64);
 
-                    if (amount < 1) amount = 1;
-                    if (amount > 64) amount = 64;
                     if (args.length >= 4) {
                         try {
                             data = Short.parseShort(args[3]);
@@ -50,6 +43,8 @@ public class GiveCommand extends VanillaCommand {
                 }
 
                 player.getInventory().addItem(new ItemStack(material, amount, data));
+
+                sender.sendMessage("Gave " + player.getName() + " some " + material.getId() + " (" + material + ")");
             } else {
                 sender.sendMessage("There's no item called " + args[1]);
             }
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/KickCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/KickCommand.java
index e30a28e7b5..c82935fb40 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/KickCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/KickCommand.java
@@ -2,7 +2,6 @@ package org.bukkit.command.defaults;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
@@ -10,14 +9,14 @@ public class KickCommand extends VanillaCommand {
     public KickCommand() {
         super("kick");
         this.description = "Removes the specified player from the server";
-        this.usageMessage = "/kick <player>";
+        this.usageMessage = "/kick <player> [reason ...]";
         this.setPermission("bukkit.command.kick");
     }
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length < 1)  {
+        if (args.length < 1 || args[0].length() == 0) {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
@@ -25,10 +24,16 @@ public class KickCommand extends VanillaCommand {
         Player player = Bukkit.getPlayerExact(args[0]);
 
         if (player != null) {
-            Command.broadcastCommandMessage(sender, "Kicking " + player.getName());
-            player.kickPlayer("Kicked by admin");
+            String reason = "Kicked by an operator.";
+
+            if (args.length > 1) {
+                reason = createString(args, 1);
+            }
+
+            player.kickPlayer(reason);
+            sender.sendMessage("Kicked player " + player.getName() + ". With reason:\n" + reason);
         } else {
-            sender.sendMessage("Can't find user " + args[0] + ". No kick.");
+            sender.sendMessage( args[0] + " not found.");
         }
 
         return true;
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/KillCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/KillCommand.java
index 0deff08cc2..d3049f7122 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/KillCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/KillCommand.java
@@ -26,6 +26,7 @@ public class KillCommand extends VanillaCommand {
 
             ede.getEntity().setLastDamageCause(ede);
             player.damage(ede.getDamage());
+            sender.sendMessage("Ouch. That look like it hurt.");
         } else {
             sender.sendMessage("You can only perform this command as a player");
         }
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/ListCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/ListCommand.java
index 009e4421e9..489edd2889 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/ListCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/ListCommand.java
@@ -16,21 +16,23 @@ public class ListCommand extends VanillaCommand {
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
 
-        StringBuilder players = new StringBuilder();
+        StringBuilder online = new StringBuilder();
 
-        for (Player player : Bukkit.getOnlinePlayers()) {
+        Player[] players = Bukkit.getOnlinePlayers();
+
+        for (Player player : players) {
             // If a player is hidden from the sender don't show them in the list
             if (sender instanceof Player && !((Player) sender).canSee(player))
                 continue;
 
-            if (players.length() > 0) {
-                players.append(", ");
+            if (online.length() > 0) {
+                online.append(", ");
             }
 
-            players.append(player.getDisplayName());
+            online.append(player.getDisplayName());
         }
 
-        sender.sendMessage("Connected players: " + players.toString());
+        sender.sendMessage("There are " + players.length + "/" + Bukkit.getMaxPlayers() + " players online:\n" + online.toString());
 
         return true;
     }
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/MeCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/MeCommand.java
index d76b84fe30..4ec16baf53 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/MeCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/MeCommand.java
@@ -22,11 +22,10 @@ public class MeCommand extends VanillaCommand {
 
         StringBuilder message = new StringBuilder();
         message.append(sender.getName());
-        if (args.length > 0) {
-            for (String arg : args) {
-                message.append(" ");
-                message.append(arg);
-            }
+
+        for (String arg : args) {
+            message.append(" ");
+            message.append(arg);
         }
 
         Bukkit.broadcastMessage("* " + message.toString());
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/OpCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/OpCommand.java
index 1878507af4..7806a7691b 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/OpCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/OpCommand.java
@@ -3,9 +3,7 @@ package org.bukkit.command.defaults;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.OfflinePlayer;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
 
 public class OpCommand extends VanillaCommand {
     public OpCommand() {
@@ -18,20 +16,15 @@ public class OpCommand extends VanillaCommand {
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 1)  {
+        if (args.length != 1 || args[0].length() == 0)  {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
 
-        Command.broadcastCommandMessage(sender, "Opping " + args[0]);
-
         OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]);
         player.setOp(true);
 
-        if (player instanceof Player) {
-            ((Player) player).sendMessage(ChatColor.YELLOW + "You are now op!");
-        }
-
+        sender.sendMessage("Opped " + args[0]);
         return true;
     }
 
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/PardonCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/PardonCommand.java
index 76e409bf67..b085b6a879 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/PardonCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/PardonCommand.java
@@ -2,7 +2,6 @@ package org.bukkit.command.defaults;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 
 public class PardonCommand extends VanillaCommand {
@@ -22,8 +21,7 @@ public class PardonCommand extends VanillaCommand {
         }
 
         Bukkit.getOfflinePlayer(args[0]).setBanned(false);
-        Command.broadcastCommandMessage(sender, "Pardoning " + args[0]);
-
+        sender.sendMessage("Pardoned " + args[0]);
         return true;
     }
 
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/PardonIpCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/PardonIpCommand.java
index 4cc4e6520f..6dc91bd968 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/PardonIpCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/PardonIpCommand.java
@@ -2,7 +2,6 @@ package org.bukkit.command.defaults;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
 import org.bukkit.command.CommandSender;
 
 public class PardonIpCommand extends VanillaCommand {
@@ -21,8 +20,12 @@ public class PardonIpCommand extends VanillaCommand {
             return false;
         }
 
-        Bukkit.unbanIP(args[0]);
-        Command.broadcastCommandMessage(sender, "Pardoning ip " + args[0]);
+        if (BanIpCommand.ipValidity.matcher(args[0]).matches()) {
+            Bukkit.unbanIP(args[0]);
+            sender.sendMessage("Pardoned ip " + args[0]);
+        } else {
+            sender.sendMessage("Invalid ip");
+        }
 
         return true;
     }
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/SaveOffCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/SaveOffCommand.java
index 628b88c1c1..a7a52c5f85 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/SaveOffCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/SaveOffCommand.java
@@ -17,12 +17,12 @@ public class SaveOffCommand extends VanillaCommand {
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
 
-        Command.broadcastCommandMessage(sender, "Disabling level saving..");
-
         for (World world : Bukkit.getWorlds()) {
             world.setAutoSave(false);
         }
 
+
+        Command.broadcastCommandMessage(sender, "Disabled level saving..");
         return true;
     }
 
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/SaveOnCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/SaveOnCommand.java
index 7e90252cce..4c1bfec633 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/SaveOnCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/SaveOnCommand.java
@@ -17,12 +17,11 @@ public class SaveOnCommand extends VanillaCommand {
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
 
-        Command.broadcastCommandMessage(sender, "Enabling level saving..");
-
         for (World world : Bukkit.getWorlds()) {
             world.setAutoSave(true);
         }
 
+        Command.broadcastCommandMessage(sender, "Enabled level saving..");
         return true;
     }
 
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/SayCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/SayCommand.java
index 9048528707..7fcf581d52 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/SayCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/SayCommand.java
@@ -4,6 +4,7 @@ import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.command.CommandSender;
 import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.entity.Player;
 
 public class SayCommand extends VanillaCommand {
     public SayCommand() {
@@ -30,7 +31,7 @@ public class SayCommand extends VanillaCommand {
             }
         }
 
-        if (!(sender instanceof ConsoleCommandSender)) {
+        if (sender instanceof Player) {
             Bukkit.getLogger().info("[" + sender.getName() + "] " + message);
         }
 
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/SeedCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/SeedCommand.java
new file mode 100644
index 0000000000..08258e5a1d
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/SeedCommand.java
@@ -0,0 +1,26 @@
+package org.bukkit.command.defaults;
+
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SeedCommand extends VanillaCommand {
+    public SeedCommand() {
+        super("seed");
+        this.description = "Shows the world seed";
+        this.usageMessage = "/seed";
+        this.setPermission("bukkit.command.seed");
+    }
+
+    @Override
+    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+        long seed;
+        if (sender instanceof Player) {
+            seed = ((Player) sender).getWorld().getSeed();
+        } else {
+            seed = Bukkit.getWorlds().get(0).getSeed();
+        }
+        sender.sendMessage("Seed: " + seed);
+        return true;
+    }
+}
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/TeleportCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/TeleportCommand.java
index 79ae480c32..f5dac7857f 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/TeleportCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/TeleportCommand.java
@@ -2,7 +2,7 @@ package org.bukkit.command.defaults;
 
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
+import org.bukkit.Location;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
@@ -11,30 +11,51 @@ public class TeleportCommand extends VanillaCommand {
     public TeleportCommand() {
         super("tp");
         this.description = "Teleports the given player to another player";
-        this.usageMessage = "/tp <player> <target>";
+        this.usageMessage = "/tp [player] <target>\n/tp [player] <x> <y> <z>";
         this.setPermission("bukkit.command.teleport");
     }
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
         if (!testPermission(sender)) return true;
-        if (args.length != 2)  {
+        if (args.length < 1 || args.length > 4) {
             sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
             return false;
         }
 
-        Player victim = Bukkit.getPlayerExact(args[0]);
-        Player target = Bukkit.getPlayerExact(args[1]);
+        Player player;
 
-        if (victim == null) {
-            sender.sendMessage("Can't find user " + args[0] + ". No tp.");
-        } else if (target == null) {
-            sender.sendMessage("Can't find user " + args[1] + ". No tp.");
+        if (args.length == 1 || args.length == 3) {
+            if (sender instanceof Player) {
+                player = (Player) sender;
+            } else {
+                sender.sendMessage("Please provide a player!");
+                return true;
+            }
         } else {
-            Command.broadcastCommandMessage(sender, "Teleporting " + victim.getName() + " to " + target.getName());
-            victim.teleport(target, TeleportCause.COMMAND);
+            player = Bukkit.getPlayerExact(args[0]);
         }
 
+        if (player == null) {
+            sender.sendMessage("Player not found: " + args[0]);
+        }
+
+        if (args.length < 3) {
+            Player target = Bukkit.getPlayerExact(args[args.length - 1]);
+            if (target == null) {
+                sender.sendMessage("Can't find user " + args[args.length - 1] + ". No tp.");
+            }
+            player.teleport(target, TeleportCause.COMMAND);
+            sender.sendMessage("Teleported " + player.getName() + " to " + target.getName());
+        } else if (player.getWorld() != null) {
+            int x = getInteger(sender, args[args.length - 3], -30000000, 30000000);
+            int y = getInteger(sender, args[args.length - 2], 0, 256);
+            int z = getInteger(sender, args[args.length - 1], -30000000, 30000000);
+
+            Location location = new Location(player.getWorld(), x, y, z);
+            player.teleport(location);
+            sender.sendMessage("Teleported " + player.getName() + " to " + x + "," + y + "," + z);
+        }
         return true;
     }
 
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/TimeCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/TimeCommand.java
index 81c6014869..9cc160ecec 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/TimeCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/TimeCommand.java
@@ -16,43 +16,49 @@ public class TimeCommand extends VanillaCommand {
 
     @Override
     public boolean execute(CommandSender sender, String currentAlias, String[] args) {
-        if (args.length != 2) {
+        if (args.length < 2) {
             sender.sendMessage(ChatColor.RED + "Incorrect usage. Correct usage:\n" + usageMessage);
             return false;
         }
 
-        int value = 0;
+        int value;
 
-        try {
-            value = Integer.parseInt(args[1]);
-        } catch (NumberFormatException ex) {
-            sender.sendMessage("Unable to convert time value, " + args[1]);
-            return true;
-        }
-
-        if (args[0].equalsIgnoreCase("add")) {
-            if (!sender.hasPermission("bukkit.command.time.add")) {
-                sender.sendMessage(ChatColor.RED + "You don't have permission to add to the time");
-            } else {
-                for (World world : Bukkit.getWorlds()) {
-                    world.setFullTime(world.getFullTime() + value);
-                }
-
-                Command.broadcastCommandMessage(sender, "Added " + value + " to time");
-            }
-        } else if (args[0].equalsIgnoreCase("set")) {
+        if (args[0].equals("set")) {
             if (!sender.hasPermission("bukkit.command.time.set")) {
                 sender.sendMessage(ChatColor.RED + "You don't have permission to set the time");
-            } else {
-                for (World world : Bukkit.getWorlds()) {
-                    world.setTime(value);
-                }
-
-                Command.broadcastCommandMessage(sender, "Set time to " + value);
+                return true;
             }
+
+            if (args[1].equals("day")) {
+                value = 0;
+            } else if (args[1].equals("night")) {
+                value = 12500;
+            } else {
+                value = getInteger(sender, args[1], 0);
+            }
+
+            for (World world : Bukkit.getWorlds()) {
+                world.setTime(value);
+            }
+
+            Command.broadcastCommandMessage(sender, "Set time to " + value);
+            sender.sendMessage("Set time to " + value);
+        } else if (args[0].equals("add")) {
+            if (!sender.hasPermission("bukkit.command.time.add")) {
+                sender.sendMessage(ChatColor.RED + "You don't have permission to set the time");
+                return true;
+            }
+
+            value = getInteger(sender, args[1], 0);
+
+            for (World world : Bukkit.getWorlds()) {
+                world.setFullTime(world.getFullTime() + value);
+            }
+
+            Command.broadcastCommandMessage(sender, "Added " + value + " to time");
+            sender.sendMessage("Added " + value + " to time");
         } else {
-            sender.sendMessage("Unknown method, use either \"add\" or \"set\"");
-            return true;
+            sender.sendMessage("Unknown method. Usage: " + usageMessage);
         }
 
         return true;
diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/VanillaCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/VanillaCommand.java
index cfb0769a35..8a76ebed47 100644
--- a/paper-api/src/main/java/org/bukkit/command/defaults/VanillaCommand.java
+++ b/paper-api/src/main/java/org/bukkit/command/defaults/VanillaCommand.java
@@ -1,9 +1,13 @@
 package org.bukkit.command.defaults;
 
+import java.util.ArrayList;
 import java.util.List;
 import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
 
 public abstract class VanillaCommand extends Command {
+    static final List<String> EMPTY_LIST = new ArrayList(0);
+
     protected VanillaCommand(String name) {
         super(name);
     }
@@ -12,5 +16,40 @@ public abstract class VanillaCommand extends Command {
         super(name, description, usageMessage, aliases);
     }
 
-    public abstract boolean matches(String input);
+    public boolean matches(String input) {
+        return input.equalsIgnoreCase(this.getName());
+    }
+
+    protected int getInteger(CommandSender sender, String value, int min) {
+        return getInteger(sender, value, min, Integer.MAX_VALUE);
+    }
+
+    protected int getInteger(CommandSender sender, String value, int min, int max) {
+        int i = min;
+        try {
+            i = Integer.valueOf(value);
+        } catch (NumberFormatException ex) {
+            sender.sendMessage("Invalid exp count: " + value);
+        }
+        if (i < min) {
+            i = min;
+        } else if (i > max) {
+            i = max;
+        }
+
+        return i;
+    }
+
+    protected String createString(String[] args, int start) {
+        StringBuilder string = new StringBuilder();
+
+        for (int x = start; x < args.length; x++) {
+            string.append(args[x]);
+            if (x != args.length - 1) {
+                string.append(" ");
+            }
+        }
+
+        return string.toString();
+    }
 }
diff --git a/paper-api/src/main/java/org/bukkit/event/inventory/InventoryType.java b/paper-api/src/main/java/org/bukkit/event/inventory/InventoryType.java
index 4a343c9048..c23908b942 100644
--- a/paper-api/src/main/java/org/bukkit/event/inventory/InventoryType.java
+++ b/paper-api/src/main/java/org/bukkit/event/inventory/InventoryType.java
@@ -39,7 +39,16 @@ public enum InventoryType {
      * The creative mode inventory, with only 9 QUICKBAR slots and nothing else. (The actual
      * creative interface with the items is client-side and cannot be altered by the server.)
      */
-    CREATIVE(9,"Creative");
+    CREATIVE(9,"Creative"),
+    /**
+     * The merchant inventory, with 2 TRADE-IN slots, and 1 RESULT slot.
+     */
+    MERCHANT(3,"Villager"),
+    /**
+     * The ender chest inventory, with 27 slots.
+     */
+    ENDER_CHEST(27,"Ender Chest");
+
     private final int size;
     private final String title;
 
diff --git a/paper-api/src/main/java/org/bukkit/inventory/MerchantInventory.java b/paper-api/src/main/java/org/bukkit/inventory/MerchantInventory.java
new file mode 100644
index 0000000000..163f45977c
--- /dev/null
+++ b/paper-api/src/main/java/org/bukkit/inventory/MerchantInventory.java
@@ -0,0 +1,4 @@
+package org.bukkit.inventory;
+
+public interface MerchantInventory extends Inventory {
+}
diff --git a/paper-api/src/main/java/org/bukkit/util/permissions/CommandPermissions.java b/paper-api/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
index b6b505bd4b..33c38ac38f 100644
--- a/paper-api/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
+++ b/paper-api/src/main/java/org/bukkit/util/permissions/CommandPermissions.java
@@ -105,7 +105,9 @@ public final class CommandPermissions {
         DefaultPermissions.registerPermission(PREFIX + "version", "Allows the user to view the version of the server", PermissionDefault.TRUE, commands);
         DefaultPermissions.registerPermission(PREFIX + "gamemode", "Allows the user to change the gamemode of another player", PermissionDefault.OP, commands);
         DefaultPermissions.registerPermission(PREFIX + "xp", "Allows the user to give themselves or others arbitrary values of experience", PermissionDefault.OP, commands);
-        DefaultPermissions.registerPermission(PREFIX + "toggledownfall", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands);
+        DefaultPermissions.registerPermission(PREFIX + "defaultgamemode", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands);
+        DefaultPermissions.registerPermission(PREFIX + "seed", "Allows the user to toggle rain on/off for a given world", PermissionDefault.OP, commands);
+
 
         commands.recalculatePermissibles();