1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 04:00:30 +00:00

Various improvements to command system

- Ensure usage is consistent
 - Allow computer selectors to return multiple values
 - Fix commands being marked as usable when it isn't
 - Add /computercraft turn-on, a counter to /computercraft shutdown
This commit is contained in:
SquidDev 2018-02-13 11:45:13 +00:00
parent 5ae38a3f18
commit 4c14431a3d
4 changed files with 80 additions and 40 deletions

View File

@ -1,6 +1,6 @@
package dan200.computercraft.shared.command; package dan200.computercraft.shared.command;
import com.google.common.collect.Lists; import com.google.common.collect.Sets;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.Computer; import dan200.computercraft.core.computer.Computer;
@ -40,8 +40,8 @@ public final class CommandComputerCraft extends CommandDelegate
root.register( new SubCommandBase( root.register( new SubCommandBase(
"dump", "[id]", "Display the status of computers.", UserLevel.OWNER_OP, "dump", "[id]", "Display the status of computers.", UserLevel.OWNER_OP,
"Display the status of all computers or specific information about one computer. You can either specify the computer's instance " + "Display the status of all computers or specific information about one computer. You can specify the " +
"id (e.g. 123) or computer id (e.g #123)." "computer's instance id (e.g. 123), computer id (e.g #123) or label (e.g. \"@My Computer\")."
) )
{ {
@Override @Override
@ -126,25 +126,25 @@ public final class CommandComputerCraft extends CommandDelegate
{ {
return arguments.size() == 1 return arguments.size() == 1
? ComputerSelector.completeComputer( arguments.get( 0 ) ) ? ComputerSelector.completeComputer( arguments.get( 0 ) )
: Collections.<String>emptyList(); : Collections.emptyList();
} }
} ); } );
root.register( new SubCommandBase( root.register( new SubCommandBase(
"shutdown", "[ids...]", "Shutdown computers remotely.", UserLevel.OWNER_OP, "shutdown", "[ids...]", "Shutdown computers remotely.", UserLevel.OWNER_OP,
"Shutdown the listed computers or all if none are specified. You can either specify the computer's instance " + "Shutdown the listed computers or all if none are specified. You can specify the computer's instance id " +
"id (e.g. 123) or computer id (e.g #123)." "(e.g. 123), computer id (e.g #123) or label (e.g. \"@My Computer\")."
) )
{ {
@Override @Override
public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) throws CommandException public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) throws CommandException
{ {
List<ServerComputer> computers = Lists.newArrayList(); Set<ServerComputer> computers = Sets.newHashSet();
if( arguments.size() > 0 ) if( arguments.size() > 0 )
{ {
for( String arg : arguments ) for( String arg : arguments )
{ {
computers.add( ComputerSelector.getComputer( arg ) ); computers.addAll( ComputerSelector.getComputers( arg ) );
} }
} }
else else
@ -166,7 +166,48 @@ public final class CommandComputerCraft extends CommandDelegate
public List<String> getCompletion( @Nonnull CommandContext context, @Nonnull List<String> arguments ) public List<String> getCompletion( @Nonnull CommandContext context, @Nonnull List<String> arguments )
{ {
return arguments.size() == 0 return arguments.size() == 0
? Collections.<String>emptyList() ? Collections.emptyList()
: ComputerSelector.completeComputer( arguments.get( arguments.size() - 1 ) );
}
} );
root.register( new SubCommandBase(
"turn-on", "ids...", "Turn computers on remotely.", UserLevel.OWNER_OP,
"Turn on the listed computers. You can specify the computer's instance id (e.g. 123), computer id (e.g #123) " +
"or label (e.g. \"@My Computer\")."
)
{
@Override
public void execute( @Nonnull CommandContext context, @Nonnull List<String> arguments ) throws CommandException
{
Set<ServerComputer> computers = Sets.newHashSet();
if( arguments.size() > 0 )
{
for( String arg : arguments )
{
computers.addAll( ComputerSelector.getComputers( arg ) );
}
}
else
{
computers.addAll( ComputerCraft.serverComputerRegistry.getComputers() );
}
int on = 0;
for( ServerComputer computer : computers )
{
if( !computer.isOn() ) on++;
computer.turnOn();
}
context.getSender().sendMessage( text( "Turned on " + on + " / " + computers.size() + " computers" ) );
}
@Nonnull
@Override
public List<String> getCompletion( @Nonnull CommandContext context, @Nonnull List<String> arguments )
{
return arguments.size() == 0
? Collections.emptyList()
: ComputerSelector.completeComputer( arguments.get( arguments.size() - 1 ) ); : ComputerSelector.completeComputer( arguments.get( arguments.size() - 1 ) );
} }
} ); } );
@ -222,7 +263,7 @@ public final class CommandComputerCraft extends CommandDelegate
{ {
return arguments.size() == 1 return arguments.size() == 1
? ComputerSelector.completeComputer( arguments.get( 0 ) ) ? ComputerSelector.completeComputer( arguments.get( 0 ) )
: Collections.<String>emptyList(); : Collections.emptyList();
} }
} ); } );

View File

@ -12,7 +12,7 @@ import java.util.function.Predicate;
public final class ComputerSelector public final class ComputerSelector
{ {
private static ServerComputer getComputer( Predicate<ServerComputer> predicate, String kind ) throws CommandException private static List<ServerComputer> getComputers( Predicate<ServerComputer> predicate, String selector ) throws CommandException
{ {
// We copy it to prevent concurrent modifications. // We copy it to prevent concurrent modifications.
List<ServerComputer> computers = Lists.newArrayList( ComputerCraft.serverComputerRegistry.getComputers() ); List<ServerComputer> computers = Lists.newArrayList( ComputerCraft.serverComputerRegistry.getComputers() );
@ -22,41 +22,40 @@ public final class ComputerSelector
if( predicate.test( searchComputer ) ) candidates.add( searchComputer ); if( predicate.test( searchComputer ) ) candidates.add( searchComputer );
} }
if( candidates.size() == 0 ) if( candidates.isEmpty() )
{ {
throw new CommandException( "No such computer for " + kind ); throw new CommandException( "No computer matching " + selector );
}
else if( candidates.size() == 1 )
{
return candidates.get( 0 );
} }
else else
{ {
StringBuilder builder = new StringBuilder( "Multiple computers with " ) return candidates;
.append( kind ).append( " (instances " ); }
}
boolean first = true; public static ServerComputer getComputer( String selector ) throws CommandException
for( ServerComputer computer : candidates ) {
List<ServerComputer> computers = getComputers( selector );
if( computers.size() == 1 )
{
return computers.get( 0 );
}
else
{
StringBuilder builder = new StringBuilder( "Multiple computers matching " )
.append( selector ).append( " (instances " );
for( int i = 0; i < computers.size(); i++ )
{ {
if( first ) if( i > 1 ) builder.append( ", " );
{ builder.append( computers.get( i ).getInstanceID() );
first = false;
}
else
{
builder.append( ", " );
}
builder.append( computer.getInstanceID() );
} }
builder.append( ")" ); builder.append( ")" );
throw new CommandException( builder.toString() ); throw new CommandException( builder.toString() );
} }
} }
public static ServerComputer getComputer( String selector ) throws CommandException public static List<ServerComputer> getComputers( String selector ) throws CommandException
{ {
if( selector.length() > 0 && selector.charAt( 0 ) == '#' ) if( selector.length() > 0 && selector.charAt( 0 ) == '#' )
{ {
@ -72,17 +71,17 @@ public final class ComputerSelector
throw new CommandException( "'" + selector + "' is not a valid number" ); throw new CommandException( "'" + selector + "' is not a valid number" );
} }
return getComputer( x -> x.getID() == id, "id " + id ); return getComputers( x -> x.getID() == id, selector );
} }
else if( selector.length() > 0 && selector.charAt( 0 ) == '@' ) else if( selector.length() > 0 && selector.charAt( 0 ) == '@' )
{ {
String label = selector.substring( 1 ); String label = selector.substring( 1 );
return getComputer( x -> Objects.equals( label, x.getLabel() ), "label '" + label + "'" ); return getComputers( x -> Objects.equals( label, x.getLabel() ), selector );
} }
else if( selector.length() > 0 && selector.charAt( 0 ) == '~' ) else if( selector.length() > 0 && selector.charAt( 0 ) == '~' )
{ {
String familyName = selector.substring( 1 ); String familyName = selector.substring( 1 );
return getComputer( x -> x.getFamily().name().equalsIgnoreCase( familyName ), "family '" + familyName + "'" ); return getComputers( x -> x.getFamily().name().equalsIgnoreCase( familyName ), selector );
} }
else else
{ {
@ -103,7 +102,7 @@ public final class ComputerSelector
} }
else else
{ {
return computer; return Collections.singletonList( computer );
} }
} }
} }

View File

@ -36,7 +36,7 @@ public class CommandDelegate implements ICommand
@Override @Override
public String getUsage( @Nonnull ICommandSender sender ) public String getUsage( @Nonnull ICommandSender sender )
{ {
return "/" + command.getName() + " " + command.getUsage( new CommandContext( sender.getServer(), sender, command ) ); return new CommandContext( sender.getServer(), sender, command ).getFullUsage();
} }
@Nonnull @Nonnull

View File

@ -86,7 +86,7 @@ public class CommandRoot implements ISubCommand
{ {
for( ISubCommand command : subCommands.values() ) for( ISubCommand command : subCommands.values() )
{ {
if( command.checkPermission( context ) ) return true; if( !(command instanceof SubCommandHelp) && command.checkPermission( context ) ) return true;
} }
return false; return false;
} }
@ -108,7 +108,7 @@ public class CommandRoot implements ISubCommand
ISubCommand command = subCommands.get( arguments.get( 0 ) ); ISubCommand command = subCommands.get( arguments.get( 0 ) );
if( command == null || !command.checkPermission( context ) ) if( command == null || !command.checkPermission( context ) )
{ {
throw new CommandException( getName() + " " + getUsage( context ) ); throw new CommandException( context.getFullUsage() );
} }
command.execute( context.enter( command ), arguments.subList( 1, arguments.size() ) ); command.execute( context.enter( command ), arguments.subList( 1, arguments.size() ) );