Paper/CraftBukkit-Patches/0073-Add-VanillaCommand-Wrapper-to-Support-New-Commands.patch
2014-01-22 19:19:39 +11:00

323 lines
12 KiB
Diff

From caef5c99c37e68d746b563cc248943463a85b85f Mon Sep 17 00:00:00 2001
From: Thinkofdeath <thethinkofdeath@gmail.com>
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<String> completions = null;
+ // Spigot Start
+ List<String> completions = new ArrayList<String>();
try {
- completions = getCommandMap().tabComplete(player, message.substring(1));
+ message = message.substring( 1 );
+ List<String> bukkitCompletions = getCommandMap().tabComplete( player, message );
+ if ( bukkitCompletions != null )
+ {
+ completions.addAll( bukkitCompletions );
+ }
+ List<String> 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.<String>of() : completions;
+ return completions; // Spigot
}
public List<String> tabCompleteChat(Player player, String message) {
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
index 19f2822..56767ac 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;
public class SpigotConfig
@@ -198,4 +200,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<String>) 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<String> allowedCommands = new HashSet<String>();
+
+ 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<String> complete(CommandSender sender, String commandLine)
+ {
+ int pos = commandLine.indexOf( ' ' );
+ if ( pos == -1 )
+ {
+ List<String> completions = new ArrayList<String>();
+ 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.<String>of();
+ }
+ ICommandListener listener = getListener( sender );
+ if ( listener == null )
+ {
+ return ImmutableList.<String>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